2017-07-01 20 views
3
不能复制matconvnet CNN架构

我有一个卷积神经网络在matconvnet以下架构,我用我自己的数据训练:在Keras

function net = cnn_mnist_init(varargin) 
% CNN_MNIST_LENET Initialize a CNN similar for MNIST 
opts.batchNormalization = false ; 
opts.networkType = 'simplenn' ; 
opts = vl_argparse(opts, varargin) ; 

f= 0.0125 ; 
net.layers = {} ; 
net.layers{end+1} = struct('name','conv1',... 
          'type', 'conv', ... 
          'weights', {{f*randn(3,3,1,64, 'single'), zeros(1, 64, 'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','pool1',... 
          'type', 'pool', ... 
          'method', 'max', ... 
          'pool', [3 3], ... 
          'stride', 1, ... 
          'pad', 0); 
net.layers{end+1} = struct('name','conv2',... 
          'type', 'conv', ... 
          'weights', {{f*randn(5,5,64,128, 'single'),zeros(1,128,'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','pool2',... 
          'type', 'pool', ... 
          'method', 'max', ... 
          'pool', [2 2], ... 
          'stride', 2, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('name','conv3',... 
          'type', 'conv', ... 
          'weights', {{f*randn(3,3,128,256, 'single'),zeros(1,256,'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','pool3',... 
          'type', 'pool', ... 
          'method', 'max', ... 
          'pool', [3 3], ... 
          'stride', 1, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('name','conv4',... 
          'type', 'conv', ... 
          'weights', {{f*randn(5,5,256,512, 'single'),zeros(1,512,'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','pool4',... 
          'type', 'pool', ... 
          'method', 'max', ... 
          'pool', [2 2], ... 
          'stride', 1, ... 
          'pad', 0) ; 
net.layers{end+1} = struct('name','ip1',... 
          'type', 'conv', ... 
          'weights', {{f*randn(1,1,256,256, 'single'), zeros(1,256,'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','relu',... 
          'type', 'relu'); 
net.layers{end+1} = struct('name','classifier',... 
          'type', 'conv', ... 
          'weights', {{f*randn(1,1,256,2, 'single'), zeros(1,2,'single')}}, ... 
          'stride', 1, ... 
          'pad', 0,... 
          'learningRate', [1 2]) ; 
net.layers{end+1} = struct('name','loss',... 
          'type', 'softmaxloss') ; 

% optionally switch to batch normalization 
if opts.batchNormalization 
    net = insertBnorm(net, 1) ; 
    net = insertBnorm(net, 4) ; 
    net = insertBnorm(net, 7) ; 
    net = insertBnorm(net, 10) ; 
    net = insertBnorm(net, 13) ; 
end 

% Meta parameters 
net.meta.inputSize = [28 28 1] ; 
net.meta.trainOpts.learningRate = [0.01*ones(1,10) 0.001*ones(1,10) 0.0001*ones(1,10)]; 
disp(net.meta.trainOpts.learningRate); 
pause; 
net.meta.trainOpts.numEpochs = length(net.meta.trainOpts.learningRate) ; 
net.meta.trainOpts.batchSize = 256 ; 
net.meta.trainOpts.momentum = 0.9 ; 
net.meta.trainOpts.weightDecay = 0.0005 ; 

% -------------------------------------------------------------------- 
function net = insertBnorm(net, l) 
% -------------------------------------------------------------------- 
assert(isfield(net.layers{l}, 'weights')); 
ndim = size(net.layers{l}.weights{1}, 4); 
layer = struct('type', 'bnorm', ... 
       'weights', {{ones(ndim, 1, 'single'), zeros(ndim, 1, 'single')}}, ... 
       'learningRate', [1 1], ... 
       'weightDecay', [0 0]) ; 
net.layers{l}.biases = [] ; 
net.layers = horzcat(net.layers(1:l), layer, net.layers(l+1:end)) ; 

我想要做的就是建立在keras相同的架构,这是我试过到目前为止:

model = Sequential() 

model.add(Conv2D(64, (3, 3), strides=1, input_shape=input_shape)) 
model.add(MaxPooling2D(pool_size=(3, 3), strides=1)) 

model.add(Conv2D(128, (5, 5), strides=1)) 
model.add(MaxPooling2D(pool_size=(2, 2), strides=2)) 

model.add(Conv2D(256, (3, 3), strides=1)) 
model.add(MaxPooling2D(pool_size=(3, 3), strides=1)) 

model.add(Conv2D(512, (5, 5), strides=1)) 
model.add(MaxPooling2D(pool_size=(2, 2), strides=1)) 

model.add(Conv2D(256, (1, 1))) 
convout1=Activation('relu') 
model.add(convout1) 

model.add(Flatten()) 
model.add(Dense(num_classes, activation='softmax')) 

opt = keras.optimizers.rmsprop(lr=0.0001, decay=0.0005) 
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['binary_accuracy']) 

然而,当我运行matconvnet网络我有87%的准确率,如果我运行keras版本我有77%的准确率。如果他们应该是相同的网络,并且数据是相同的,那么区别在哪里?我的Keras架构出了什么问题?

+2

您的'mathconv'网络是否打开了“BatchNormalization”选项?因为你还没有添加BatchNormalization。 –

+0

没有批次标准化。谢谢! – mad

+1

所以 - 我可以形成答案 - 所以你可以接受它,并使其更加明显? –

回答

1

在您的MatConvNet版本中,您使用SGD的势头。

在Keras,您使用rmsprop

用不同的学习规则,你应该尝试不同的学习率。有时候,在训练CNN时,势头也会有所帮助。

您可以尝试凯拉斯的SGD +动力,让我知道会发生什么?

另一件可能不同的事情是初始化。例如在MatConvNet中,使用f = 0.0125的高斯初始值作为标准偏差。在凯拉斯我不确定默认的初始化。

一般而言,如果您不使用批规范化,网络很容易出现许多数值问题。如果你在这两个网络中使用批量标准化,我敢打赌结果是相似的。是否有任何理由不想使用批规范化?

+0

我会的,谢谢! – mad

+0

我试过这个sgd = keras.optimizers.SGD(lr = 0.0001,decay = 0.0005,动量= 0.9),但结果变得更糟:50%。你相信两个网络的架构是一样的吗? – mad

+1

@mad参见编辑回复 – DataHungry