我有一个神经网络的基本框架来识别数字,但我在训练时遇到了一些问题。我的back-propogation适用于小型数据集,但是当我有超过50个数据点时,返回值开始收敛到0.当我有数千个数据集时,我得到NaN的成本和回报。
基本结构:3层:784:15:1
784是每个数据集的像素数,隐藏层中的15个神经元,以及一个输出神经元,它返回0到1的值(当你乘以10得到一个数字时)。
public class NetworkManager {
int inputSize;
int hiddenSize;
int outputSize;
public Matrix W1;
public Matrix W2;
public NetworkManager(int input, int hidden, int output) {
inputSize = input;
hiddenSize = hidden;
outputSize = output;
W1 = new Matrix(inputSize, hiddenSize);
W2 = new Matrix(hiddenSize, output);
}
Matrix z2, z3;
Matrix a2;
public Matrix forward(Matrix X) {
z2 = X.dot(W1);
a2 = sigmoid(z2);
z3 = a2.dot(W2);
Matrix yHat = sigmoid(z3);
return yHat;
}
public double costFunction(Matrix X, Matrix y) {
Matrix yHat = forward(X);
Matrix cost = yHat.sub(y);
cost = cost.mult(cost);
double returnValue = 0;
int i = 0;
while (i < cost.m.length) {
returnValue += cost.m[i][0];
i++;
}
return returnValue;
}
Matrix yHat;
public Matrix[] costFunctionPrime(Matrix X, Matrix y) {
yHat = forward(X);
Matrix delta3 = (yHat.sub(y)).mult(sigmoidPrime(z3));
Matrix dJdW2 = a2.t().dot(delta3);
Matrix delta2 = (delta3.dot(W2.t())).mult(sigmoidPrime(z2));
Matrix dJdW1 = X.t().dot(delta2);
return new Matrix[]{dJdW1, dJdW2};
}
}
有网络框架的代码。我将长度为784的双数组传递给正向方法。
int t = 0;
while (t < 10000) {
dJdW = Nn.costFunctionPrime(X, y);
Nn.W1 = Nn.W1.sub(dJdW[0].scalar(3));
Nn.W2 = Nn.W2.sub(dJdW[1].scalar(3));
t++;
}
我称之为调整重量。对于小集合,成本很好地收敛到0,但是较大的集合不会(与100个字符相关的成本总是收敛到13)。如果设置太大,第一次调整就会起作用(并且成本会下降)但是在第二次调整之后,我能得到的就是NaN。
为什么这种实现会因较大的数据集(特别是培训)而失败,我该如何解决这个问题?我尝试了一个类似的结构,有10个输出而不是1个,其中每个都会返回一个接近0或1的值,就像布尔值一样,但同样的事情正在发生。
顺便说一句,我也是在java中这样做,我想知道这是否与问题有关。我想知道这是否是一个空间不足的问题,但我没有得到任何堆空间消息。我是如何反向传播还是其他事情发生了问题?
编辑:我想我知道发生了什么。我认为我的反向传播功能正在陷入局部最低限度。有时培训成功,有时大型数据集失败。因为我从随机权重开始,我得到随机的初始成本。我注意到的是,当成本最初超过一定数量(取决于所涉及的数据集的数量)时,成本会收敛到一个干净的数字(有时是27,其他为17.4),输出收敛到0(这是有道理的) )。当我开始时,我被告知成本函数中的相对最小值,我开始明白为什么。所以现在问题变成了,我如何进行渐变下降,以便我实际上找到全局最小值?顺便说一句,我在Java工作。
答案 0 :(得分:1)
如果你的backprop在小数据集上工作,那么确实存在很好的问题,即没有问题。当您对此产生怀疑时,可以尝试使用BP来解决XOR问题。
单位有偏见吗?
我曾与那些做同样事情的人讨论过。手数字识别和隐藏层中的15个单位。我看到一个网络谁做得很好。她的拓扑结构是:
输入:784
首先隐藏:500
第二个隐藏:500
第三隐藏:2000
输出:10
你有一组图像,你可以将784像素的图像非线性地转换为来自&lt; 0,1&gt;的15个数字。间隔,你为你的所有图像做这个。您希望您可以根据这15个数字确定单独的数字。从我的观点来看,当我假设你有数千个数据集的例子时,15个隐藏单位对于这样的任务来说太少了。请尝试500个隐藏单位。
学习率对backprop有影响,可能导致收敛问题。
答案 1 :(得分:1)
这似乎是重量初始化的问题。
据我所见,您永远不会将权重初始化为任何特定值。因此网络出现了分歧。你应该至少使用随机初始化。