我正在使用 Matconvnet 上的 Matconvnet 对 CNN 进行二进制分类。而现在,我正试图通过 Python 上的 Keras 来实现它。网络一点也不复杂,我在 Matconvnet 上达到了 96% 的准确率。然而,对于 Keras,即使我尽力确保每个设置都与以前完全相同,我也无法得到相同的结果。或者更糟糕的是,该模型根本不起作用。
以下是有关设置的一些详细信息。任何想法或帮助表示赞赏!
输入
图像为 20*20 尺寸。训练规模为 400,测试规模为 100,验证规模为 132。
- Matconvnet:以 20*20*sample_size 方法存储的图像
- Keras:存储在 sample_size*20*20*1 方法中的图像
CNN结构 (3*3)*3 conv-(2*2)maxpooling-全连接-softmax-logloss
Matconvnet:使用卷积层而不是全连接层。这是代码:
function net = initializeCNNA() f=1/100 ; net.layers = {} ; net.layers{end+1} = struct('type', 'conv', ... 'weights', {{f*randn(3,3,1,3, 'single'), zeros(1, 3, 'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'pool', ... 'method', 'max', ... 'pool', [2 2], ... 'stride', 2, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'conv', ... 'weights', {{f*randn(9,9,3,2, 'single'), zeros(1,2,'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'softmaxloss') ; net = vl_simplenn_tidy(net) ;
喀拉斯:
model = Sequential()
model.add(Conv2D(3, (3,3),kernel_initializer=\
keras.initializers.RandomNormal(mean=0.0, stddev=0.1, seed=None), input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2, 2)))
model.add(Flatten())
model.add(Dense(2,activation='softmax',\
kernel_initializer=keras.initializers.RandomNormal(mean=0.0, stddev=0.1, seed=None)))
- 损失函数
- Matconvnet:
softmaxloss
- 喀拉斯:
binary_crossentropy
- Matconvnet:
优化器
Matconvnet:新元
trainOpts.batchSize = 50; trainOpts.numEpochs = 20 ; trainOpts.learningRate = 0.001 ; trainOpts.weightDecay = 0.0005 ; trainOpts.momentum = 0.9 ;
Keras:新元
sgd = optimizers.SGD(lr=0.001, momentum=0.9, decay=0.0005) model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
- 初始化:过滤器:N(0,0.1),偏差:0
- 归一化:除了归一化外,没有批量归一化,而输入的图像具有 0 均值和 1 标准差。
以上是我审查的方面,以确保我进行了正确的复制。但是我不明白为什么它在 Keras 上不起作用。以下是一些猜测:
- Matconvnet 使用卷积层而不是全连接层,这可能意味着一些奇特的方法来更新参数。
- 他们使用不同的算法来应用参数具有不同含义的 SGD。
我还做了其他尝试:
- 将 Keras 中的优化器更改为
Adadelta()
. 没提升。 改变网络结构并使其更深。有用!
但是还是想知道为什么 Matconvnet 可以用一个更简单的方法来达到那么好的结果。