ResNet:训练过程中的准确度为100%,但相同数据的预测准确度为33%
deep-learning
keras
machine-learning
8
0

我是机器学习和深度学习的新手,出于学习目的,我尝试与Resnet一起玩。我试图对小数据(3张不同的图像)进行过拟合,看看是否可以得到几乎为0的损失和1.0的精度-我做到了。

问题在于对训练图像(即用于训练的相同3幅图像)的预测不正确。

训练影像

图片1 图片2 图片3

图片标签

[1,0,0][0,1,0][0,0,1]

我的python代码

#loading 3 images and resizing them
imgs = np.array([np.array(Image.open("./Images/train/" + fname)
                          .resize((197, 197), Image.ANTIALIAS)) for fname in
                 os.listdir("./Images/train/")]).reshape(-1,197,197,1)
# creating labels
y = np.array([[1,0,0],[0,1,0],[0,0,1]])
# create resnet model
model = ResNet50(input_shape=(197, 197,1),classes=3,weights=None)

# compile & fit model
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['acc'])

model.fit(imgs,y,epochs=5,shuffle=True)

# predict on training data
print(model.predict(imgs))

该模型确实拟合了数据:

3/3 [==============================] - 22s - loss: 1.3229 - acc: 0.0000e+00
Epoch 2/5
3/3 [==============================] - 0s - loss: 0.1474 - acc: 1.0000
Epoch 3/5
3/3 [==============================] - 0s - loss: 0.0057 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s - loss: 0.0107 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s - loss: 1.3815e-04 - acc: 1.0000

但预测是:

 [[  1.05677405e-08   9.99999642e-01   3.95520459e-07]
 [  1.11955103e-08   9.99999642e-01   4.14905685e-07]
 [  1.02637095e-07   9.99997497e-01   2.43751242e-06]]

这意味着所有图像的label=[0,1,0]均为label=[0,1,0]

为什么?怎么会这样?

参考资料:
Stack Overflow
收藏
评论
共 1 个回答
高赞 时间 活跃

这是因为批次归一化层。

在训练阶段,通过均值和方差将批次标准化。但是,在测试阶段,使用先前观察到的均值和方差的移动平均值对批次进行归一化。

现在,当观察到的批次数量很少时(例如,在您的示例中为5),这是一个问题,因为在BatchNormalization层中,默认情况下moving_mean初始化为0,而moving_variance初始化为1。

还要考虑默认momentum为0.99,您需要多次更新移动平均线才能收敛到“真实”均值和方差。

这就是为什么预测在早期是错误的,但是在1000个时期后才是正确的。


您可以通过强制BatchNormalization图层在“训练模式”下运行来进行验证。

在训练过程中,精度为1,损失接近零:

model.fit(imgs,y,epochs=5,shuffle=True)
Epoch 1/5
3/3 [==============================] - 19s 6s/step - loss: 1.4624 - acc: 0.3333
Epoch 2/5
3/3 [==============================] - 0s 63ms/step - loss: 0.6051 - acc: 0.6667
Epoch 3/5
3/3 [==============================] - 0s 57ms/step - loss: 0.2168 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s 56ms/step - loss: 1.1921e-07 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s 53ms/step - loss: 1.1921e-07 - acc: 1.0000

现在,如果我们评估模型,我们将观察到高损失和低准确性,因为经过5次更新后,移动平均值仍然非常接近初始值:

model.evaluate(imgs,y)
3/3 [==============================] - 3s 890ms/step
[10.745396614074707, 0.3333333432674408]

但是,如果我们手动指定“学习阶段”变量,并让BatchNormalization图层使用“实际”批次均值和方差,则结果将与fit()观察到的结果相同。

sample_weights = np.ones(3)
learning_phase = 1  # 1 means "training"
ins = [imgs, y, sample_weights, learning_phase]
model.test_function(ins)
[1.192093e-07, 1.0]

也可以通过将动量更改为较小的值来进行验证。

例如,通过向ResNet50所有批处理规范层添加momentum=0.01 ,则在20个纪元后的预测为:

model.predict(imgs)
array([[  1.00000000e+00,   1.34882026e-08,   3.92139575e-22],
       [  0.00000000e+00,   1.00000000e+00,   0.00000000e+00],
       [  8.70998792e-06,   5.31159838e-10,   9.99991298e-01]], dtype=float32)
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号