【问题标题】:DeepLearning4j NN for prediction function doesn't converge预测函数的 DeepLearning4j NN 不收敛
【发布时间】:2021-10-05 03:57:36
【问题描述】:

我正在尝试在 DL4j 中进行简单的预测(稍后将用于具有 n 个特征的大型数据集),但无论我做什么,我的网络都不想学习并且表现得非常奇怪。当然,我学习了所有教程并执行了 dl4j repo 中显示的相同步骤,但它对我不起作用。

对于我使用的虚拟特征数据:

*double[val][x] 特征;其中 val = linspace(-10,10)...;和 x= Math.sqrt(Math.abs(val)) * val;

我的y是:双[y]标签;其中 y = Math.sin(val) / val

DataSetIterator dataset_train_iter = getTrainingData(x_features, y_outputs_train, batchSize, rnd);
    DataSetIterator dataset_test_iter = getTrainingData(x_features_test, y_outputs_test, batchSize, rnd);

    // Normalize data, including labels (fitLabel=true)
    NormalizerMinMaxScaler normalizer = new NormalizerMinMaxScaler(0, 1);
    normalizer.fitLabel(false);
    normalizer.fit(dataset_train_iter);              
    normalizer.fit(dataset_test_iter);

    // Use the .transform function only if you are working with a small dataset and no iterator
    normalizer.transform(dataset_train_iter.next());
    normalizer.transform(dataset_test_iter.next());

    dataset_train_iter.setPreProcessor(normalizer);
    dataset_test_iter.setPreProcessor(normalizer);

    //DataSet setNormal = dataset.next();

//创建网络

MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
                .weightInit(WeightInit.XAVIER)
                //.miniBatch(true)
                //.l2(1e-4)
                //.activation(Activation.TANH)
                .updater(new Nesterovs(0.1,0.3))
                .list()
                .layer(new DenseLayer.Builder().nIn(numInputs).nOut(20).activation(Activation.TANH)
                        .build())
                .layer(new DenseLayer.Builder().nIn(20).nOut(10).activation(Activation.TANH)
                        .build())
                .layer( new DenseLayer.Builder().nIn(10).nOut(6).activation(Activation.TANH)
                        .build())
                .layer(new OutputLayer.Builder(LossFunctions.LossFunction.MSE)
                        .activation(Activation.IDENTITY)
                        .nIn(6).nOut(1).build())
                .build();

//训练和拟合网络

final MultiLayerNetwork net = new MultiLayerNetwork(conf);
net.init();
    net.setListeners(new ScoreIterationListener(100));
    //Train the network on the full data set, and evaluate in periodically
    final INDArray[] networkPredictions = new INDArray[nEpochs / plotFrequency];
    for (int i = 0; i < nEpochs; i++) {
        //in fit we have already Backpropagation. See Release deeplearning
        // https://deeplearning4j.konduit.ai/release-notes/1.0.0-beta3
        net.fit(dataset_train_iter);
        dataset_train_iter.reset();
        if((i+1) % plotFrequency == 0)  networkPredictions[i/ plotFrequency] = net.output(x_features, false);
    }

// 评估和绘图

    dataset_test_iter.reset();
    dataset_train_iter.reset();

    INDArray predicted = net.output(dataset_test_iter, false);
    System.out.println("PREDICTED ARRAY                " + predicted);
    INDArray output_train = net.output(dataset_train_iter, false);

    //Revert data back to original values for plotting
    // normalizer.revertLabels(predicted);
    normalizer.revertLabels(output_train);
    normalizer.revertLabels(predicted);

    PlotUtil.plot(om, y_outputs_train, networkPredictions);

我的输出看起来很奇怪(见下图),即使我使用 miniBatch(1, 20,100 个样本/批次)更改 epoch 数或添加隐藏节点和隐藏层(尝试添加 1000 个节点和 5 层)。网络要么输出非常随机的值,要么输出一个常数 y。我只是无法识别,这里出了什么问题。为什么网络甚至没有接近 train 函数。

另一个问题:iter.reset() 究竟做了什么。 Iterator 是否将指针转回 DataSetIterator 中的 0-Batch?

【问题讨论】:

  • 也许我不得不提一下,我直接从我的 double[][] 和 double[] 数组创建 x_features 和 y_labels,如下所示:INDArray matrix = Nd4j.create(double[][]); 然后创建我的 DataSetIterator这样:DataSet allData = new DataSet(x, y); final List&lt;DataSet&gt; list = allData.asList(); Collections.shuffle(list, rng); return new ListDataSetIterator&lt;&gt;(list, batchSize);

标签: java regression prediction deeplearning4j dl4j


【解决方案1】:

一个很常见的问题是人们在做这样的玩具问题,这是 dl4j 对 minibatch 的假设(99% 的问题往往是这样)。您实际上并没有进行小批量学习(这实际上破坏了实际使用迭代器的意义,迭代器旨在迭代数据集的切片,而不是内存中的小数据集) - 一个小建议是只使用普通的数据集 api (这是从 dataset.next() 返回的内容)

确保关闭 dl4j 分配给所有损失的小批量惩罚: .minibatch(false) - 你可以在这里看到该配置: https://github.com/eclipse/deeplearning4j/blob/master/deeplearning4j/deeplearning4j-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetConfiguration.java#L434

可以在此处找到测试此行为的单元测试: https://github.com/eclipse/deeplearning4j/blob/b4047006ac8175df295c2f3c008e7601437ea4dc/deeplearning4j/deeplearning4j-core/src/test/java/org/deeplearning4j/gradientcheck/GradientCheckTests.java#L94

为了后代,这里是相关配置:


        MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder().miniBatch(false)
                .dataType(DataType.DOUBLE)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT).updater(new NoOp())
                .list()
                .layer(0,
                        new DenseLayer.Builder().nIn(4).nOut(3)
                                .dist(new NormalDistribution(0, 1))
                                .activation(Activation.TANH)
                                .build())
                .layer(1, new OutputLayer.Builder(LossFunction.MCXENT)
                        .activation(Activation.SOFTMAX).nIn(3).nOut(3).build())
                .build();

您会注意到两件事:1 是 minibatch 为 false,2 是数据类型 double 的配置。也欢迎您尝试解决您的问题。 用于节省内存的 Dl4j 也倾向于将 float 作为默认数据类型。

在处理较大的问题时这是一个合理的假设,但可能不适用于玩具问题。

作为参考,您可以在此处找到小批量数学的应用: https://github.com/eclipse/deeplearning4j/blob/fc735d30023981ebbb0fafa55ea9520ec44292e0/deeplearning4j/deeplearning4j-nn/src/main/java/org/deeplearning4j/nn/updater/BaseMultiLayerUpdater.java#L332

这会影响梯度更新。

分数惩罚可以在输出层找到: https://github.com/eclipse/deeplearning4j/blob/master/deeplearning4j/deeplearning4j-nn/src/main/java/org/deeplearning4j/nn/layers/BaseOutputLayer.java#L84

从本质上讲,这两种方法都会自动惩罚损失更新和梯度更新中反映的数据集的损失更新。

【讨论】:

  • 非常感谢。我已经尝试过您的配置,但它并没有大大改善我的网络。似乎输出是完全随机的,或者权重不会更新。也许它取决于迭代器或 ..im 完全丢失了 drive.google.com/file/d/1c5aqZAOs51YdkH5wrdIgxO90FiOC1urU/… 对于这个预测,我使用了: BatchSize: 10 ;时代:100
  • 我建议的另一件事是实际标准化您的标签或使用 RMSE。标准化你的标签可以让网络更容易学习。当您想要未标准化的输出时,dl4j 中的规范化器都具有针对输入特征和标签的还原功能。
猜你喜欢
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 1970-01-01
  • 2016-01-19
  • 2018-06-05
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多