神经网络和大型数据集

时间:2016-12-20 05:34:23

标签: java neural-network deep-learning large-files backpropagation

我有一个神经网络的基本框架来识别数字,但我在训练时遇到了一些问题。我的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工作。

2 个答案:

答案 0 :(得分:1)

如果你的backprop在小数据集上工作,那么确实存在很好的问题,即没有问题。当您对此产生怀疑时,可以尝试使用BP来解决XOR问题。

单位有偏见吗?

我曾与那些做同样事情的人讨论过。手数字识别和隐藏层中的15个单位。我看到一个网络谁做得很好。她的拓扑结构是:

输入:784

首先隐藏:500

第二个隐藏:500

第三隐藏:2000

输出:10

你有一组图像,你可以将784像素的图像非线性地转换为来自&lt; 0,1&gt;的15个数字。间隔,你为你的所有图像做这个。您希望您可以根据这15个数字确定单独的数字。从我的观点来看,当我假设你有数千个数据集的例子时,15个隐藏单位对于这样的任务来说太少了。请尝试500个隐藏单位。

学习率对backprop有影响,可能导致收敛问题。

答案 1 :(得分:1)

这似乎是重量初始化的问题。

据我所见,您永远不会将权重初始化为任何特定值。因此网络出现了分歧。你应该至少使用随机初始化。