我是机器学习和深度学习的新手,为了学习目的,我尝试使用Resnet . 我试图过度填充小数据(3个不同的图像),看看我是否可以获得几乎0的损失和1.0的准确度 - 我做到了 .
问题是对 training 图像的预测(即用于训练的相同3个图像)不正确 .
Training Images
Image labels
[1,0,0]
, [0,1,0]
, [0,0,1]
My python code
#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]
为什么?这怎么可能发生?
2 回答
这是因为批量规范化层 .
在培训阶段,批次被标准化为w.r.t.它的均值和方差 . 但是,在测试阶段,批次被标准化为w.r.t.先前观察到的均值和方差的 moving average .
现在,当观察到的批次数很少时(例如,在您的示例中为5),这是一个问题,因为在
BatchNormalization
图层中,默认情况下moving_mean
初始化为0并且moving_variance
初始化为1 .鉴于默认
momentum
为0.99,您需要在收敛到"real"均值和方差之前更新移动平均线很多次 .这就是为什么预测在早期阶段是错误的,但在1000个时代之后是正确的 .
您可以通过强制
BatchNormalization
层在"training mode"中运行来验证它 .在训练期间,准确度为1,损失接近于零:
现在,如果我们评估模型,我们将观察到高损耗和低精度,因为在5次更新后,移动平均线仍然非常接近初始值:
但是,如果我们手动指定"learning phase"变量并让
BatchNormalization
层使用"real"批次均值和方差,则结果与fit()
中观察到的结果相同 .也可以通过将动量更改为更小的值来验证它 .
例如,通过将
momentum=0.01
添加到ResNet50
中的所有批处理范数层,20个历元之后的预测为:我之前遇到过类似的问题,但解决方案非常简单 . 你需要增加时代数 . 这是1000个纪元后的输出
这是培训日志..