Перечисляет для реализации различных методов в Java - PullRequest
0 голосов
/ 07 января 2019

Предположим, я построил следующий класс

public enum OptimizationAlgorithmType {

    VANILLA(new HashMap<String, Double>()) {

        private final static String ETA = "eta";
        private Double eta = null;

        public OptimizationAlgorithmType setEta(Double eta) {
            this.eta = eta;
            return this;
        }

        @Override
        public Map<String, Double> getHyperarameters() {
            this.map.put(ETA, eta);
            return this.map;
        }       
    }, 

    MOMENTUM(new HashMap<String, Double>()) {

        private final static String ALPHA = "alpha";
        private final static String BETA = "beta";

        private Double alpha = null;
        private Double beta = null;

        public OptimizationAlgorithmType setAlpha(Double alpha) {
            this.alpha = alpha;
            return this;
        }

        public OptimizationAlgorithmType setBeta(Double beta) {
            this.beta = beta;
            return this;
        }

        @Override
        public Map<String, Double> getHyperarameters() {
            this.map.put(ALPHA, alpha);
            this.map.put(BETA, beta);
            return this.map;
        }
    };

    protected Map<String, Double> map;

    private OptimizationAlgorithmType(Map<String, Double> map) {
        this.map = map;
    }

    public abstract Map<String, Double> getHyperarameters();    
}

Моя цель состояла в том, чтобы создать API, чтобы при выборе указанного Enum были доступны разные методы. Например

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation(feedForward)
        .setNumberThreads(10)
        .setBatch(5)
        .setEpochs(100)
        .setOptimizer(OptimizationAlgorithmType.VANILLA.setEta(0.001));

или

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation(feedForward)
        .setNumberThreads(10)
        .setBatch(5)
        .setEpochs(100)
        .setOptimizer(OptimizationAlgorithmType.MOMENTUM.setAlpha(0.01).setBeta(0.99));

К сожалению, это запрещено. Ide предупреждает о неиспользуемых методах (т. Е. setEta()) - и методы вообще не доступны для выбора из определенного перечисления.

Есть ли уловка, которую я могу использовать, чтобы получить желаемый API?

Спасибо

Редактировать Добавлен альтернативный ответ ниже

Ответы [ 3 ]

0 голосов
/ 11 января 2019

может быть попробовать что-то вроде:

import java.util.Arrays;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

public class So54067082enums_to_implement_different_methods_in_java {
    enum Type {
        vanilla(new TreeSet<>(Arrays.asList(new String[] {"eta"}))),
        momentum(new TreeSet<>(Arrays.asList(new String[] {"alpha","beta"})));
        Type(Set<String> names) {
            this.names=names;

        }
        final Set<String> names;
    }
    static class ParameterSet {
        ParameterSet(Type type) {
            this.type=type;
        }
        Double get(String name) {
            if(type.names.contains(name))
                return map.get(name);
            else throw new RuntimeException("oops");
        }
        void set(String name,Double value) {
            if(type.names.contains(name))
                map.put(name,value);
            else throw new RuntimeException("oops");
        }
        @Override public String toString() {
            return "ParameterSet [type="+type+", map="+map+"]";
        }
        final Type type;
        private final SortedMap<String,Double> map=new TreeMap<>();

    }
    public static void main(String[] args) {
        ParameterSet parameterSet=new ParameterSet(Type.vanilla);
        parameterSet.set("eta",.01);
        System.out.println(parameterSet);
        ParameterSet parameterSet2=new ParameterSet(Type.momentum);
        parameterSet2.set("alpha",.1);
        parameterSet2.set("beta",.9);
        System.out.println(parameterSet2);
    }
}
0 голосов
/ 11 января 2019

Я не понимаю, почему вы не могли просто использовать менее наивный подход к проблеме:

class OptimizationAlgorithm {
  public static class Vanilla implements OptimizationAlgorithm {
    public Vanilla setAlpha(float a) {
      return this;
    }

    public Vanilla setBeta(float a) {
      return this;
    }
  }

  public static Vanilla vanilla() { return new Vanilla(); }
}

backpropagation.setOptimizer(OptimizationAlgorithm.vanilla().setAlpha(0.05f).setBeta(0.10f));

Гораздо меньше стандартного кода, нет проблем с изменяемыми статическими экземплярами и в основном тот же интерфейс извне.

0 голосов
/ 10 января 2019

Я придумал немного лучше

Сначала интерфейс, затем два класса параметров, которые реализуют интерфейс

public interface Hyperparameter {...}   

public enum VanillaParameter implements Hyperparameter {
        ETA {

            @Override
            public Double getValue() {
                return this.etaValue;
            }

            @Override
            public void setValue(Double value) {

                if (value == null) {
                    throw new IllegalStateException("Parameter value cannot be set to null!");
                }
                this.etaValue = value;
            }
        };
        protected Double etaValue = 0.005;
    }

    public enum MomentumParameter implements Hyperparameter {
    ...
    }

Теперь добавьте основной enum класс

    public enum OptimizationType {

        VANILLA{
            private VanillaParameter eta = VanillaParameter.ETA;

            @Override
            public Hyperparameter get(Hyperparameter parameter) {
                switch ((VanillaParameter) parameter) {
                case ETA: return this.eta;
                }
                return null;
            }

            @Override
            public OptimizationType set(Hyperparameter parameter, Double value) {

                switch ((VanillaParameter) parameter) {
                case ETA: 
                    this.eta.setValue(value);
                    break;
                }
                return OptimizationType.VANILLA;
            }
        },
        ...
}

И API выглядит действительно хорошо, на мой взгляд, и напоминает мое первоначальное намерение. Ждем предложений

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation.BackpropagationBuilder(feedForward)
        .setBatch(5)
        .setEpochs(100)
        .setThreads(10)
        .setOptimizer(OptimizationType.MOMENTUM
                .set(MomentumParameter.ALPHA, 0.001)
                .set(MomentumParameter.BETA, 0.92))
        .build();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...