我正在使用AForge.net NN库创建一个简单的多层前馈神经网络。我的神经网络是一个由3层组成的激活网络,使用监督学习方法和反向传播学习算法进行训练。
以下是我的初始设置:
//学习率learningRate=0.1;//动量值momentum=0;//双极性S型激活函数的alpha值sigmoidAlphaValue=2.0;//网络输入数量inputSize=5;//网络输出数量predictionSize=1;//迭代次数iterations=10000;//创建多层神经网络 ActivationNetwork network = new ActivationNetwork(new BipolarSigmoidFunction(sigmoidAlphaValue), 5, 5 + 1, 3, 1);//5个输入//输入层6个神经元//隐藏层3个神经元//输出层1个神经元//创建教师BackPropagationLearning teacher = new BackPropagationLearning(network);//设置学习率和动量teacher.LearningRate = learningRate;teacher.Momentum = momentum;
现在我有一些输入序列,看起来像这样,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
使用窗口滑动方法(如此处描述的)将输入作为时间序列,我的输入和
预期输出数组看起来像这样
//迭代 #1double input[][] = new input[0][5] {1,2,3,4,5};double output[][] = new output[0][0] {6};//迭代 #2double input[][] = new input[1][5] {2,3,4,5,6};double output[][] = new output[1][0] {7};//迭代 #3double input[][] = new input[2][5] {3,4,5,6,7};double output[][] = new output[2][0] {8};...//迭代 #ndouble input[][] = new input[n][5] {15,16,17,18,19};double output[][] = new output[n][0] {20};
经过10k次这样的迭代使用
teacher.RunEpoch(input, output);
我的网络成功地针对给定的训练集进行了训练。所以现在,如果我使用输入4,5,6,7,8计算,网络成功地给出了9作为答案,太棒了!
然而,当输入为21,22,23,24,25时,NN未能产生26!
我的问题:如何训练我的网络接受这种未遇到过的输入,以产生在学习过程中发现的训练集中正确的序列模式?
回答:
正如@人名所说,你的模型似乎过拟合了(训练)数据。为了避免这个问题,你可以将你的集合(时间序列)分成3个部分。
训练集
第一个可以是训练集,你只需在其中训练你的网络。
验证集
第二个是验证集,对于每次训练的迭代,你需要在验证集上测试神经网络,并获取错误并将此错误存储在一个变量中和一个神经网络的副本(克隆)中。在下一次迭代中,你需要测试(修改后的)神经网络,如果在验证集上的新错误低于你上次测试的错误,你就存储一个新的“验证神经网络”。这将为你提供一个在非训练集上表现更好的神经网络。这样你就避免了对训练集的过拟合。
在训练结束时,你将拥有两个神经网络。一个是训练神经网络,它是训练集上表现最佳的神经网络,另一个是验证神经网络,它可以为你提供一个在训练集之外表现更好的神经网络。
测试集
这最后一个部分,你只需在未见过的集合上测试你的模型并检查错误。测试集的目的是检查神经网络在未见过的测试中的行为。真正的测试。
一般来说,你可以将整个集合分成3个相等的部分,或者例如
- 60%用于训练
- 20%用于验证
- 20%用于测试
例如,请看下面的图片:
实现它的伪代码示例可能是:
int epochs = 1;double error = 0;double validationError = 10000;object validationNetwork;do{ //训练你的网络 error = getError(trainingSet); //验证部分... var currentValidationError = getError(validationSet); if (currentValidationError < validationError) { validationError = currentValidationError; validationNeuralNetwork = neuralNetwork.Clone(); }} while (epochs < 2000 && error < 0.001);
时间序列的交叉验证
另一方面,你也可以尝试对时间序列进行交叉验证。首先,你将你的集合分成6个部分(或更多),并训练神经网络以验证模型,如下所示:
- 1 : 训练 [1],验证 [2],测试 [3]
- 2 : 训练 [2],验证 [3],测试 [4]
- 3 : 训练 [3],验证 [4],测试 [5]
- 4 : 训练 [4],验证 [5],测试 [6]
如果你愿意,可以分成更多部分。