使用最大池化层时,SGD 学习会卡住(但仅使用 conv + fc 就可以正常工作)

数据挖掘 神经网络 梯度下降 反向传播 卷积 极简主义
2022-02-17 07:43:37

我正在为一个大学项目开发​​一个CNN 库,并且在通过最大池化层实现反向传播时遇到了一些麻烦。

请注意,整个东西是根据神经网络和深度学习书籍和其他资源从头开始构建的 ,所以我知道那里有现成的库,以及执行某些操作的更优化算法(如 FFT 卷积算法),但这件事的重点是了解网络的工作原理并在不使用 3rd 方库的情况下实现所有内容。

我很确定完全连接的层可以正常工作,因为我尝试使用 MNIST 数据集训练一个网络,并且它在不到 60 个时期内迅速达到 96% 以上,就像上面提到的书中提到的那样。

我继续并实现了卷积层,它们似乎也工作得很好,事实上,如果我尝试使用这样的网络(所有层上的 sigmoid 激活):

  • 卷积:28*28*1 个输入,20 个 5*5*1 内核
  • 全连接:24*24*20输入,100输出
  • 全连接:100 个输入,10 个输出,交叉熵成本

这就是我得到的:在此处输入图像描述

如您所见,该网络仅在 3 个 epoch 内就迅速达到了 96% 以上的准确率。

但是,一旦我尝试在卷积层和全连接层之间放置一个 2*2 池化层(就像 Michael Nielsen在他的书第 6 章中所做的那样),我得到的结果如下:

在此处输入图像描述

网络达到 30%,然后就卡在那里了。

我已经检查过,一切似乎都工作正常(但当然我可能是错的,而且我可能是错的,因为这东西没有按应有的方式工作),前向池化层在每个 2*2 窗口中取最大值在所有输入图像中(对每个深度层都这样做),并且在通过池化层进行反向传播期间,我只是使用卷积层的先前输出来放大输入增量,以便每个增量都到达具有最大值的像素在卷积输出中,而所有其他像素都为 0。

我应该从哪里开始寻找错误?我的意思是,显然池层发生了一些事情,但是代码对我来说看起来不错,无论是理论上还是我添加到项目中的实际单元测试。在这里调查问题的正确方法是什么?这个问题有可能的解释吗?

这是我正在使用的代码,如果有人安装了 .NET Core 2.x 并想试用该库(下载/解析 MNIST 数据集的代码已经在库中):

((float[,] X, float[,] Y) training, (float[,] X, float[,] Y) test) = DataParser.LoadDatasets();
INeuralNetwork network = NetworkTrainer.NewNetwork(
    NetworkLayers.Convolutional((28, 28, 1), (5, 5), 20, ActivationFunctionType.Identity),
    NetworkLayers.Pooling((24, 24, 20), ActivationFunctionType.Sigmoid),
    NetworkLayers.FullyConnected(12 * 12 * 20, 100, ActivationFunctionType.Sigmoid),
    NetworkLayers.FullyConnected(100, 10, ActivationFunctionType.Sigmoid, CostFunctionType.CrossEntropy));
await NetworkTrainer.TrainNetworkAsync(network, (training.X, training.Y), 60, 10, null,
    new TestParameters(test, new Progress<BackpropagationProgressEventArgs>(p =>
    {
        Printf($"Epoch {p.Iteration}, cost: {p.Cost}, accuracy: {p.Accuracy}");
    })));

谢谢你的帮助!

0个回答
没有发现任何回复~