package org.deeplearning4j.eval;
import org.deeplearning4j.datasets.iterator.ExistingDataSetIterator;
import org.deeplearning4j.nn.conf.ComputationGraphConfiguration;
import org.deeplearning4j.nn.conf.MultiLayerConfiguration;
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
import org.deeplearning4j.nn.conf.layers.OutputLayer;
import org.deeplearning4j.nn.graph.ComputationGraph;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.deeplearning4j.nn.weights.WeightInit;
import org.junit.Test;
import org.nd4j.linalg.activations.Activation;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.dataset.DataSet;
import org.nd4j.linalg.dataset.api.iterator.DataSetIterator;
import org.nd4j.linalg.factory.Nd4j;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* @author Alex Black
*/
public class RegressionEvalTest {
@Test(expected = java.lang.IllegalArgumentException.class)
public void testEvalParameters() {
int specCols = 5;
INDArray labels = Nd4j.ones(3);
INDArray preds = Nd4j.ones(6);
RegressionEvaluation eval = new RegressionEvaluation(specCols);
eval.eval(labels, preds);
}
@Test
public void testPerfectPredictions() {
int nCols = 5;
int nTestArrays = 100;
int valuesPerTestArray = 3;
RegressionEvaluation eval = new RegressionEvaluation(nCols);
for (int i = 0; i < nTestArrays; i++) {
INDArray rand = Nd4j.rand(valuesPerTestArray, nCols);
eval.eval(rand, rand);
}
System.out.println(eval.stats());
for (int i = 0; i < nCols; i++) {
assertEquals(0.0, eval.meanSquaredError(i), 1e-6);
assertEquals(0.0, eval.meanAbsoluteError(i), 1e-6);
assertEquals(0.0, eval.rootMeanSquaredError(i), 1e-6);
assertEquals(0.0, eval.relativeSquaredError(i), 1e-6);
assertEquals(1.0, eval.correlationR2(i), 1e-6);
}
}
@Test
public void testKnownValues() {
double[][] labelsD = new double[][] {{1, 2, 3}, {0.1, 0.2, 0.3}, {6, 5, 4}};
double[][] predictedD = new double[][] {{2.5, 3.2, 3.8}, {2.15, 1.3, -1.2}, {7, 4.5, 3}};
double[] expMSE = {2.484166667, 0.966666667, 1.296666667};
double[] expMAE = {1.516666667, 0.933333333, 1.1};
double[] expRSE = {0.368813923, 0.246598639, 0.530937216};
double[] expCorrs = {0.997013483, 0.968619605, 0.915603032};
INDArray labels = Nd4j.create(labelsD);
INDArray predicted = Nd4j.create(predictedD);
RegressionEvaluation eval = new RegressionEvaluation(3);
for (int xe = 0; xe < 2; xe++) {
eval.eval(labels, predicted);
for (int i = 0; i < 3; i++) {
assertEquals(expMSE[i], eval.meanSquaredError(i), 1e-5);
assertEquals(expMAE[i], eval.meanAbsoluteError(i), 1e-5);
assertEquals(Math.sqrt(expMSE[i]), eval.rootMeanSquaredError(i), 1e-5);
assertEquals(expRSE[i], eval.relativeSquaredError(i), 1e-5);
assertEquals(expCorrs[i], eval.correlationR2(i), 1e-5);
}
eval.reset();
}
}
@Test
public void testRegressionEvaluationMerging() {
Nd4j.getRandom().setSeed(12345);
int nRows = 20;
int nCols = 3;
int numMinibatches = 5;
int nEvalInstances = 4;
List<RegressionEvaluation> list = new ArrayList<>();
RegressionEvaluation single = new RegressionEvaluation(nCols);
for (int i = 0; i < nEvalInstances; i++) {
list.add(new RegressionEvaluation(nCols));
for (int j = 0; j < numMinibatches; j++) {
INDArray p = Nd4j.rand(nRows, nCols);
INDArray act = Nd4j.rand(nRows, nCols);
single.eval(act, p);
list.get(i).eval(act, p);
}
}
RegressionEvaluation merged = list.get(0);
for (int i = 1; i < nEvalInstances; i++) {
merged.merge(list.get(i));
}
double prec = 1e-5;
for (int i = 0; i < nCols; i++) {
assertEquals(single.correlationR2(i), merged.correlationR2(i), prec);
assertEquals(single.meanAbsoluteError(i), merged.meanAbsoluteError(i), prec);
assertEquals(single.meanSquaredError(i), merged.meanSquaredError(i), prec);
assertEquals(single.relativeSquaredError(i), merged.relativeSquaredError(i), prec);
assertEquals(single.rootMeanSquaredError(i), merged.rootMeanSquaredError(i), prec);
}
}
@Test
public void testRegressionEvalMethods(){
//Basic sanity check
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
.weightInit(WeightInit.ZERO)
.list()
.layer(0, new OutputLayer.Builder().activation(Activation.TANH).nIn(10).nOut(5).build())
.build();
MultiLayerNetwork net = new MultiLayerNetwork(conf);
net.init();
INDArray f = Nd4j.zeros(4,10);
INDArray l = Nd4j.ones(4, 5);
DataSet ds = new DataSet(f, l);
DataSetIterator iter = new ExistingDataSetIterator(Collections.singletonList(ds));
RegressionEvaluation re = net.evaluateRegression(iter);
for( int i=0; i<5; i++ ){
assertEquals(1.0, re.meanSquaredError(i), 1e-6);
assertEquals(1.0, re.meanAbsoluteError(i), 1e-6);
}
ComputationGraphConfiguration graphConf = new NeuralNetConfiguration.Builder()
.weightInit(WeightInit.ZERO)
.graphBuilder()
.addInputs("in")
.addLayer("0", new OutputLayer.Builder().activation(Activation.TANH).nIn(10).nOut(5).build(), "in")
.setOutputs("0")
.build();
ComputationGraph cg = new ComputationGraph(graphConf);
cg.init();
RegressionEvaluation re2 = cg.evaluateRegression(iter);
for( int i=0; i<5; i++ ){
assertEquals(1.0, re2.meanSquaredError(i), 1e-6);
assertEquals(1.0, re2.meanAbsoluteError(i), 1e-6);
}
}
@Test
public void testRegressionEvalPerOutputMasking(){
INDArray l = Nd4j.create(new double[][]{
{1,2,3},
{10,20,30},
{-5,-10,-20}});
INDArray predictions = Nd4j.zeros(l.shape());
INDArray mask = Nd4j.create(new double[][]{
{0,1,1},
{1,1,0},
{0,1,0}});
RegressionEvaluation re = new RegressionEvaluation();
re.eval(l, predictions, mask);
double[] mse = new double[]{
(10*10)/1.0,
(2*2 + 20*20 + 10*10)/3,
(3*3)/1.0};
double[] mae = new double[]{
10.0,
(2 + 20 + 10) / 3.0,
3.0};
double[] rmse = new double[]{
10.0,
Math.sqrt((2*2 + 20*20 + 10*10) / 3.0),
3.0};
for( int i=0; i<3; i++ ){
assertEquals(mse[i], re.meanSquaredError(i), 1e-6);
assertEquals(mae[i], re.meanAbsoluteError(i), 1e-6);
assertEquals(rmse[i], re.rootMeanSquaredError(i), 1e-6);
}
}
}