OPENNLP-1472 Fix flaky (sub-) test of GradientDescentUtilsTest in sandbox component 'nlp-utils' (#88)
- adjusts parameter alpha in GradientDescentUtilsTest from `0.00002` to `0.00001`
- aforementioned param change results in stable convergence, checked via RepeatedTest (JUnit)
- optimizes how random values are obtained in `GradientDescentUtils`
- fixes a potentially unpredictable BigDecimal value in `AnomalyDetectionUtils` (see JavaDoc of that constructor)
diff --git a/nlp-utils/src/main/java/org/apache/opennlp/utils/anomalydetection/AnomalyDetectionUtils.java b/nlp-utils/src/main/java/org/apache/opennlp/utils/anomalydetection/AnomalyDetectionUtils.java
index 009441f..0f38415 100644
--- a/nlp-utils/src/main/java/org/apache/opennlp/utils/anomalydetection/AnomalyDetectionUtils.java
+++ b/nlp-utils/src/main/java/org/apache/opennlp/utils/anomalydetection/AnomalyDetectionUtils.java
@@ -96,7 +96,7 @@
private static double calculateGaussianProbability(TrainingExample x, double[] mus,
double[] sigmas) {
assert mus.length == sigmas.length : "parameters not aligned";
- BigDecimal px = new BigDecimal(1d);
+ BigDecimal px = new BigDecimal("1");
for (int i = 0; i < mus.length; i++) {
BigDecimal firstTerm = BigDecimal.ONE.divide(BigDecimal.valueOf(Math.sqrt(2d * Math.PI * sigmas[i])), RoundingMode.CEILING);
BigDecimal secondTerm = BigDecimal.valueOf(Math.exp(-1 * (Math.pow(x.getInputs()[i] - mus[i], 2) / (2 * Math.pow(sigmas[i], 2)))));
diff --git a/nlp-utils/src/main/java/org/apache/opennlp/utils/regression/GradientDescentUtils.java b/nlp-utils/src/main/java/org/apache/opennlp/utils/regression/GradientDescentUtils.java
index 67613b5..ce99ebb 100644
--- a/nlp-utils/src/main/java/org/apache/opennlp/utils/regression/GradientDescentUtils.java
+++ b/nlp-utils/src/main/java/org/apache/opennlp/utils/regression/GradientDescentUtils.java
@@ -18,8 +18,6 @@
*/
package org.apache.opennlp.utils.regression;
-import java.util.Arrays;
-import java.util.Random;
import org.apache.opennlp.utils.TrainingSet;
/**
@@ -31,10 +29,13 @@
private static final int MAX_ITERATIONS = 100000;
/**
- * Calculates batch gradient descent on the give hypothesis, training set and learning rate alpha.
- * The algorithms iteratively adjusts the hypothesis parameters
+ * Calculates batch gradient descent on a {@link Hypothesis}, {@link TrainingSet} and
+ * learning rate {@code alpha}. The algorithms iteratively adjusts the hypothesis parameters
*
- * @param trainingSet the training set used to fit the parameters
+ * <p>
+ * Note: This implementation uses {@link LinearCombinationHypothesis} as hypothesis.
+ *
+ * @param trainingSet the {@link TrainingSet} used to fit the parameters
* @param alpha the learning rate alpha used to define how big the descent steps are
*/
public static void batchGradientDescent(TrainingSet trainingSet, double alpha) {
@@ -52,7 +53,7 @@
if (newCost > cost) {
throw new RuntimeException("failed to converge at iteration " + iterations + " with cost going from " + cost + " to " + newCost);
} else if (cost == newCost || newCost < THRESHOLD || iterations > MAX_ITERATIONS) {
- System.out.println(cost + " with parameters " + Arrays.toString(parameters) + "(" + iterations + " iterations)");
+ // System.out.println(cost + " with parameters " + Arrays.toString(parameters) + "(" + iterations + " iterations)");
break;
}
@@ -72,8 +73,7 @@
private static double[] initializeRandomWeights(int size) {
double[] doubles = new double[size];
for (int i = 0; i < doubles.length; i++) {
- Random rand = new Random();
- doubles[i] = rand.nextDouble() * 0.1d;
+ doubles[i] = Math.random() * 0.1d;
}
return doubles;
}
diff --git a/nlp-utils/src/test/java/org/apache/opennlp/utils/regression/GradientDescentUtilsTest.java b/nlp-utils/src/test/java/org/apache/opennlp/utils/regression/GradientDescentUtilsTest.java
index 258985f..a551a5d 100644
--- a/nlp-utils/src/test/java/org/apache/opennlp/utils/regression/GradientDescentUtilsTest.java
+++ b/nlp-utils/src/test/java/org/apache/opennlp/utils/regression/GradientDescentUtilsTest.java
@@ -20,6 +20,7 @@
import org.apache.opennlp.utils.TestUtils;
import org.apache.opennlp.utils.TrainingSet;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
@@ -27,11 +28,17 @@
*/
class GradientDescentUtilsTest {
- @Test
- void testConvergence() {
- TrainingSet trainingSet = new TrainingSet();
+ private TrainingSet trainingSet;
+
+ @BeforeEach
+ public void setup() {
+ trainingSet = new TrainingSet();
TestUtils.fillTrainingSet(trainingSet, 100, 5);
- GradientDescentUtils.batchGradientDescent(trainingSet, 0.00002);
+ }
+
+ @Test // @RepeatedTest(1000)
+ void testConvergence() {
+ GradientDescentUtils.batchGradientDescent(trainingSet, 0.00001);
}
}