【问题标题】:Neural networks and large data sets神经网络和大型数据集
【发布时间】:2016-12-20 05:34:23
【问题描述】:

我有一个神经网络识别数字的基本框架,但我在训练它时遇到了一些问题。我的反向传播适用于小型数据集,但是当我有超过 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 的双精度数组传递给 forward 方法。

    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。

【问题讨论】:

  • 识别数字是一个分类问题,而不是回归问题。您应该考虑使用 10 个输出,每个输出对应一个数字,并根据输出值最高的输出神经元选择识别的数字。
  • 是的,我实际上已经切换回 10 输出框架

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


【解决方案1】:

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

据我所知,您永远不会将权重初始化为任何特定值。因此网络发散。您至少应该使用随机初始化。

【讨论】:

  • 我用随机值初始化,我只是没有发布那部分代码
  • 然后我会调整学习率。这是可以使您的网络分歧的其他事情之一。此外,输入数据可能相反,这也会影响收敛。
  • 你推荐高学习率还是低学习率?另外,让学习率在整个训练过程中保持可变不是最好吗?
  • 我建议训练不同的学习率。通常你会做 10 个间隔,所以 [0.1, 0.001, 0.0001, 0.00001]。在它实际训练之后,您仍然可以处理诸如在验证错误停止改善后更改学习率之类的事情。但如今随着衰变,它不再需要了。
【解决方案2】:

如果您的反向传播适用于小型数据集,那么确实可以很好地假设没有问题。当您对此感到怀疑时,您可以在 XOR 问题上尝试您的 BP。

单位有偏差吗?

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

输入:784

第一次隐藏:500

第二隐藏:500

第三隐藏:2000

输出:10

您有一组图像,并且您将 784 个像素的图像非线性变换为 间隔的 15 个数字,并且您对集合中的所有图像执行此操作。您希望您可以根据这 15 个数字来正确分隔数字。从我的角度来看,当我假设您拥有包含数千个示例的数据集时,对于这样的任务来说,15 个隐藏单元太少了。请尝试例如 500 个隐藏单元。

而学习率对反向传播有影响,会导致收敛问题。

【讨论】:

  • 我实际上并没有使用偏见,我认为我应该这样做。我会随机初始化它们,但我将如何调整训练中的偏差?
  • 与正常重量完全一样。但是您认为偏差单元输出为 1,因此偏差的更新规则是第 i 个神经元的 delta 偏差 = 误差信号_ofithneuron* learning_rate。
  • 所以我加入了偏差,对于小型数据集,网络的学习速度比以前更快(这很好),但是对于较大的数据集,它仍然存在输出收敛到 0 的问题。 .
猜你喜欢
  • 2012-05-15
  • 2019-11-18
  • 2018-09-20
  • 2019-03-26
  • 2013-01-04
  • 2019-03-19
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多