【问题标题】:Can shuffling my training data lead to bad model performance?改组我的训练数据会导致模型性能不佳吗?
【发布时间】:2019-11-29 13:40:21
【问题描述】:

我正在用 C++ 编写一个神经网络,以使用具有 5 个隐藏神经元的单个隐藏层来逼近 xSin(x) 函数。隐藏神经元使用 tanh 激活,输出层使用 Linear 激活。我在 10,000 个 epoch 中使用了 30 个训练示例。

直到我洗牌我的数据,这是我得到的: (红色:预测数据,绿色:实际数据),MSE 也接近 0

但是当我打乱训练示例的索引并验证我的打乱确实打乱时,我得到了糟糕的结果:

,

错误与时代为:

可能会出什么问题?洗牌可以对此负责吗?

这里是简单的代码供参考

//Shuffle Function 
void shuffle(int *array, size_t n)
{
    if (n > 1) //If no. of training examples > 1
    {
        size_t i;
        for (i = 0; i < n - 1; i++)
        {
            size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
            int t = array[j];
            array[j] = array[i];
            array[i] = t;
        }
    }
}


int main(int argc, const char * argv[])
{
    //Some other actions

    ///FOR INDEX SHUFFLING
    int trainingSetOrder[numTrainingSets];
    for(int j=0; j<numTrainingSets; ++j)
        trainingSetOrder[j] = j;


    ///TRAINING
    //std::cout<<"start train\n";
    vector<double> performance, epo; ///STORE MSE, EPOCH
    for (int n=0; n < epoch; n++)
    {

        shuffle(trainingSetOrder,numTrainingSets);
         for (int i=0; i<numTrainingSets; i++)
        {
            int x = trainingSetOrder[i];
            //cout<<" "<<"("<<training_inputs[x][0]<<","<<training_outputs[x][0] <<")";

            /// Forward pass
            for (int j=0; j<numHiddenNodes; j++)
            {
                double activation=hiddenLayerBias[j];
                //std::cout<<"Training Set :"<<x<<"\n";
                 for (int k=0; k<numInputs; k++) {
                    activation+=training_inputs[x][k]*hiddenWeights[k][j];
                }
                hiddenLayer[j] = tanh(activation);
            }

            for (int j=0; j<numOutputs; j++) {
                double activation=outputLayerBias[j];
                for (int k=0; k<numHiddenNodes; k++)
                {
                    activation+=hiddenLayer[k]*outputWeights[k][j];
                }
                outputLayer[j] = lin(activation);
            }



           /// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[i][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

            ///   For W
           //Some Code

            ///Updation
            ///   For V and b
            ///Some Code

            ///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
                }
            }
        }
      }


    return 0;
}

【问题讨论】:

  • 您的代码链接对我不起作用。请养成将有问题的代码直接包含在适当代码标签内的帖子的好习惯,而不是链接到可能并不总是有效的其他地方。
  • 很抱歉给您带来不便。对于这个问题,代码会很长而且很麻烦,因为我没有关注特定的 sn-p。因此,我添加了一个链接。我会改正的。
  • 我明白,没问题 :) AFAIK,改组训练数据集顺序不应该使预测失败。我猜你在洗牌或处理洗牌的数据时犯了一个粗心的错误。但是没有代码,它只能是猜测。
  • shuffle 函数会随机播放索引而不是数据。

标签: c++ neural-network shuffle mean-square-error function-approximation


【解决方案1】:

您的模型似乎没有被随机初始化,因为 init_weight 函数

double init_weight() { return (2*rand()/RAND_MAX -1); }

几乎总是返回 -1,因为它会进行整数除法。这样的初始化可能会使模型很难或无法训练。

修复:

double init_weight() { return 2. * rand() / RAND_MAX - 1; }

上面的2. 的类型为double,这会触发将二元运算符中涉及的其他整数项提升为double


Xavier initialization 是加快训练速度的好方法。

【讨论】:

  • 但正如我在图中显示的那样,模型权重能够做出很好的预测。洗牌是个怎样的问题?
  • @PeDro 这并不能证明太多。修复init_weight 对训练性能有影响吗?
  • 我会尽快测试,但我只能保证该模型之前的均方误差几乎为 0。
  • 我检查了,结果仍然很糟糕。它是别的东西。
【解决方案2】:

我在训练部分发现了 2 个错误(愚蠢!):

1)

/// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[i][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

应该是

/// Backprop
           ///   For V
            double deltaOutput[numOutputs];
            for (int j=0; j<numOutputs; j++) {
                double errorOutput = (training_outputs[x][j]-outputLayer[j]);
                deltaOutput[j] = errorOutput*dlin(outputLayer[j]);
            }

2)

///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
                }
            }

应该是

///   For W and c
            for (int j=0; j<numHiddenNodes; j++) {
                //c
                hiddenLayerBias[j] += deltaHidden[j]*lr;
                //W
                for(int k=0; k<numInputs; k++) {
                  hiddenWeights[k][j]+=training_inputs[x][k]*deltaHidden[j]*lr;
                }
            }

发布哪个,我明白了

【讨论】:

    猜你喜欢
    • 2023-02-06
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2017-03-27
    • 1970-01-01
    • 2020-05-06
    相关资源
    最近更新 更多