1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.math4.neuralnet.sofm; 19 20 import org.apache.commons.math4.neuralnet.internal.NeuralNetException; 21 import org.apache.commons.math4.neuralnet.sofm.util.ExponentialDecayFunction; 22 import org.apache.commons.math4.neuralnet.sofm.util.QuasiSigmoidDecayFunction; 23 24 /** 25 * Factory for creating instances of {@link LearningFactorFunction}. 26 * 27 * @since 3.3 28 */ 29 public final class LearningFactorFunctionFactory { 30 /** Class contains only static methods. */ 31 private LearningFactorFunctionFactory() {} 32 33 /** 34 * Creates an exponential decay {@link LearningFactorFunction function}. 35 * It will compute <code>a e<sup>-x / b</sup></code>, 36 * where {@code x} is the (integer) independent variable and 37 * <ul> 38 * <li><code>a = initValue</code> 39 * <li><code>b = -numCall / ln(valueAtNumCall / initValue)</code> 40 * </ul> 41 * 42 * @param initValue Initial value, i.e. 43 * {@link LearningFactorFunction#value(long) value(0)}. 44 * @param valueAtNumCall Value of the function at {@code numCall}. 45 * @param numCall Argument for which the function returns 46 * {@code valueAtNumCall}. 47 * @return the learning factor function. 48 * @throws IllegalArgumentException if {@code initValue <= 0}, 49 * {@code initValue > 1} {@code valueAtNumCall <= 0}, 50 * {@code valueAtNumCall >= initValue} or {@code numCall <= 0}. 51 */ 52 public static LearningFactorFunction exponentialDecay(final double initValue, 53 final double valueAtNumCall, 54 final long numCall) { 55 if (initValue <= 0 || 56 initValue > 1) { 57 throw new NeuralNetException(NeuralNetException.OUT_OF_RANGE, initValue, 0, 1); 58 } 59 60 return new LearningFactorFunction() { 61 /** DecayFunction. */ 62 private final ExponentialDecayFunction decay 63 = new ExponentialDecayFunction(initValue, valueAtNumCall, numCall); 64 65 /** {@inheritDoc} */ 66 @Override 67 public double value(long n) { 68 return decay.applyAsDouble(n); 69 } 70 }; 71 } 72 73 /** 74 * Creates an sigmoid-like {@code LearningFactorFunction function}. 75 * The function {@code f} will have the following properties: 76 * <ul> 77 * <li>{@code f(0) = initValue}</li> 78 * <li>{@code numCall} is the inflexion point</li> 79 * <li>{@code slope = f'(numCall)}</li> 80 * </ul> 81 * 82 * @param initValue Initial value, i.e. 83 * {@link LearningFactorFunction#value(long) value(0)}. 84 * @param slope Value of the function derivative at {@code numCall}. 85 * @param numCall Inflexion point. 86 * @return the learning factor function. 87 * @throws IllegalArgumentException if {@code initValue <= 0}, 88 * {@code initValue > 1}, {@code slope >= 0} or {@code numCall <= 0}. 89 */ 90 public static LearningFactorFunction quasiSigmoidDecay(final double initValue, 91 final double slope, 92 final long numCall) { 93 if (initValue <= 0 || 94 initValue > 1) { 95 throw new NeuralNetException(NeuralNetException.OUT_OF_RANGE, initValue, 0, 1); 96 } 97 98 return new LearningFactorFunction() { 99 /** DecayFunction. */ 100 private final QuasiSigmoidDecayFunction decay 101 = new QuasiSigmoidDecayFunction(initValue, slope, numCall); 102 103 /** {@inheritDoc} */ 104 @Override 105 public double value(long n) { 106 return decay.applyAsDouble(n); 107 } 108 }; 109 } 110 }