我目前一直在与 CNN 合作,并且很难处理我认为过度拟合的问题。具体来说,即使我的训练数据收敛到最小误差,我的验证数据仍然拒绝在误差方面下降。我使用的输入数据是 512 x 650 x 1 x 4000(2D 数据,4000 个样本),我试图区分的数据只有两个类(A 类和 B 类)。我知道我将来需要更多的样本,但就目前而言,我只想在投资生成更多数据之前看到我的验证错误下降一点。
我的网络都有大约 60-70 层长,并且包括以下类型的层:
块示例
卷积层 [3 x 3] 过滤器大小,步幅 [1 x 1],填充 [1 1 1 1]
ReLU 层(非线性)
批量归一化(对训练数据收敛和实现速度有很大帮助)
最大池化层 [2 x 2] 过滤器大小,步幅 [2 x 2],填充 [0 0 0 0]
然后我重复这个“块”,直到我的输入数据是 1 x 1 x N 大小,然后我通过几个完全连接的层运行它,然后进入一个 softmax。
下面是我的实际 MatConvNet 代码以供检查,并附有输出图。对于这些图,蓝色代表我的训练错误,橙色代表我的验证错误。我从下面的代码链接我最近的。
我的问题:
1)如何知道他们的数据使用什么过滤器大小?我知道这是一个经验过程,但这背后肯定有某种直觉吗?我已经阅读了有关使用 [3x3] 小型过滤器并使用了很多的论文(VGG.net 等),但即使在考虑到这一点设计了一个 70 层网络之后,仍然没有验证错误下降。
2)我已经尝试过 dropout 层,因为它们很受欢迎,可以减少过度拟合……我在上面显示的“块”中的 ReLU 和池化层之后,将 dropout 层放置在整个网络中,但在所有卷积层之间。不幸的是,它对我的验证数据没有影响,错误仍然是一样的。接下来,我尝试仅在完全连接的层之后使用它,因为那是在我的架构中创建最多神经元(或特征图)的地方,但仍然没有运气。我读过关于辍学的论文。我应该放弃使用它吗?这又是不是又有“窍门”了?
3)如果我尝试使用较小的网络(我已经读过这是一种处理过度拟合的下降方式),我如何有效地减少数据的大小?只是最大池化?
任何建议都会很棒。
再次感谢大家阅读这个长问题。我向你保证,我已经完成了我的研究,发现从长远来看,在这里提问可能对我有更多帮助。
MatConvNet 代码(用于 CNN 设计的 Matlab 工具箱)
opts.train.batchSize = 25;
opts.train.numEpochs = 200 ;
opts.train.continue = true ;
opts.train.gpus = [1] ;
opts.train.learningRate = 1e-3;
opts.train.weightDecay = 0.04;
opts.train.momentum = 0.9;
opts.train.expDir = 'epoch_data';
opts.train.numSubBatches = 1;
bopts.useGpu = numel(opts.train.gpus) > 0 ;
load('imdb4k.mat');
net = dagnn.DagNN() ;
% Block #1
net.addLayer('conv1', dagnn.Conv('size', [3 3 1 64], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'input'}, {'conv1'}, {'conv1f' 'conv1b'});
net.addLayer('relu1', dagnn.ReLU(), {'conv1'}, {'relu1'}, {});
net.addLayer('bn1', dagnn.BatchNorm('numChannels', 64), {'relu1'}, {'bn1'}, {'bn1f', 'bn1b', 'bn1m'});
net.addLayer('pool1', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn1'}, {'pool1'}, {});
% Block #2
net.addLayer('conv2', dagnn.Conv('size', [3 3 64 64], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool1'}, {'conv2'}, {'conv2f' 'conv2b'});
net.addLayer('relu2', dagnn.ReLU(), {'conv2'}, {'relu2'}, {});
net.addLayer('bn2', dagnn.BatchNorm('numChannels', 64), {'relu2'}, {'bn2'}, {'bn2f', 'bn2b', 'bn2m'});
net.addLayer('pool2', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn2'}, {'pool2'}, {});
% Block #3
net.addLayer('conv3', dagnn.Conv('size', [3 3 64 128], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool2'}, {'conv3'}, {'conv3f' 'conv3b'});
net.addLayer('relu3', dagnn.ReLU(), {'conv3'}, {'relu3'}, {});
net.addLayer('bn3', dagnn.BatchNorm('numChannels', 128), {'relu3'}, {'bn3'},
{'bn3f', 'bn3b', 'bn3m'});
net.addLayer('pool3', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn3'}, {'pool3'}, {});
% Block #4
net.addLayer('conv4', dagnn.Conv('size', [3 3 128 128], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool3'}, {'conv4'}, {'conv4f' 'conv4b'});
net.addLayer('relu4', dagnn.ReLU(), {'conv4'}, {'relu4'}, {});
net.addLayer('bn4', dagnn.BatchNorm('numChannels', 128), {'relu4'}, {'bn4'}, {'bn4f', 'bn4b', 'bn4m'});
net.addLayer('pool4', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn4'}, {'pool4'}, {});
% Block #5
net.addLayer('conv5', dagnn.Conv('size', [3 3 128 256], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool4'}, {'conv5'}, {'conv5f' 'conv5b'});
net.addLayer('relu5', dagnn.ReLU(), {'conv5'}, {'relu5'}, {});
net.addLayer('bn5', dagnn.BatchNorm('numChannels', 256), {'relu5'}, {'bn5'}, {'bn5f', 'bn5b', 'bn5m'});
net.addLayer('pool5', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn5'}, {'pool5'}, {});
% Block #6
net.addLayer('conv6', dagnn.Conv('size', [3 3 256 256], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool5'}, {'conv6'}, {'conv6f' 'conv6b'});
net.addLayer('relu6', dagnn.ReLU(), {'conv6'}, {'relu6'}, {});
net.addLayer('bn6', dagnn.BatchNorm('numChannels', 256), {'relu6'}, {'bn6'}, {'bn6f', 'bn6b', 'bn6m'});
net.addLayer('pool6', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn6'}, {'pool6'}, {});
% Block #7
net.addLayer('conv7', dagnn.Conv('size', [3 3 256 512], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool6'}, {'conv7'}, {'conv7f' 'conv7b'});
net.addLayer('relu7', dagnn.ReLU(), {'conv7'}, {'relu7'}, {});
net.addLayer('bn7', dagnn.BatchNorm('numChannels', 512), {'relu7'}, {'bn7'}, {'bn7f', 'bn7b', 'bn7m'});
net.addLayer('pool7', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn7'}, {'pool7'}, {});
% Block #8
net.addLayer('conv8', dagnn.Conv('size', [3 3 512 512], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool7'}, {'conv8'}, {'conv8f' 'conv8b'});
net.addLayer('relu8', dagnn.ReLU(), {'conv8'}, {'relu8'}, {});
net.addLayer('bn8', dagnn.BatchNorm('numChannels', 512), {'relu8'}, {'bn8'}, {'bn8f', 'bn8b', 'bn8m'});
net.addLayer('pool8', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [1 2], 'pad', [0 0 0 0]), {'bn8'}, {'pool8'}, {});
% Block #9
net.addLayer('conv9', dagnn.Conv('size', [3 3 512 512], 'hasBias', true, 'stride', [1, 1], 'pad', [1 1 1 1]), {'pool8'}, {'conv9'}, {'conv9f' 'conv9b'});
net.addLayer('relu9', dagnn.ReLU(), {'conv9'}, {'relu9'}, {});
net.addLayer('bn9', dagnn.BatchNorm('numChannels', 512), {'relu9'}, {'bn9'}, {'bn9f', 'bn9b', 'bn9m'});
net.addLayer('pool9', dagnn.Pooling('method', 'max', 'poolSize', [2, 2], 'stride', [2 2], 'pad', [0 0 0 0]), {'bn9'}, {'pool9'}, {});
% Incorporate MLP
net.addLayer('fc1', dagnn.Conv('size', [1 1 512 1000], 'hasBias', true, 'stride', [1, 1], 'pad', [0 0 0 0]), {'pool9'}, {'fc1'}, {'conv15f' 'conv15b'});
net.addLayer('relu10', dagnn.ReLU(), {'fc1'}, {'relu10'}, {});
net.addLayer('bn10', dagnn.BatchNorm('numChannels', 1000), {'relu10'}, {'bn10'}, {'bn10f', 'bn10b', 'bn10m'});
net.addLayer('classifier', dagnn.Conv('size', [1 1 1000 2], 'hasBias', true, 'stride', [1, 1], 'pad', [0 0 0 0]), {'bn10'}, {'classifier'}, {'conv16f' 'conv16b'});
net.addLayer('prob', dagnn.SoftMax(), {'classifier'}, {'prob'}, {});
% The dagnn.Loss computes the loss incurred by the prediction scores X given the categorical labels
net.addLayer('objective', dagnn.Loss('loss', 'softmaxlog'), {'prob', 'label'}, {'objective'}, {});
net.addLayer('error', dagnn.Loss('loss', 'classerror'), {'prob','label'}, 'error') ;