CNN Keras 对象定位 - 错误预测
CNN Keras Object Localization - Bad predictions
我是机器学习的初学者,目前我正在尝试预测图像中对象的位置,该图像是我创建的数据集的一部分。
该数据集总共包含大约 300 张图像,包含 2 classes(A 和 Two)。
我创建了一个 CNN,可以预测它是 A 还是 2,准确率约为 88%。
由于这个数据集做得很好,我决定尝试预测卡片的位置(而不是 class)。我阅读了一些文章,根据我的理解,我所要做的就是采用我用来预测 class 的相同 CNN,并将最后一层更改为 4 个节点的密集层。
这就是我所做的,但显然这是行不通的。
这是我的模型:
model = Sequential()
model.add(Conv2D(64,(3,3),input_shape = (150,150,1)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(32,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=2))
model.add(Dense(64))
model.add(Activation("relu"))
model.add(Flatten())
model.add(Dense(4))
model.compile(loss="mean_squared_error",optimizer='adam',metrics=[])
model.fit(X,y,batch_size=1,validation_split=0,
epochs=30,verbose=1,callbacks=[TENSOR_BOARD])
我为模型提供的内容:
X:150x150 像素的灰度图像。每个像素在 [0-1]
之间重新缩放
y:对象的最小X坐标、最大Y坐标、宽高(每个值都在[0-1].
之间)
这是它给我的预测示例:
[array([ 28.66145 , 41.278576, -9.568813, -13.520659], dtype=float32)]
但我真正想要的是:
[0.32, 0.38666666666666666, 0.4, 0.43333333333333335]
我知道这里出了点问题,所以我决定在单个图像上训练和测试我的 CNN(因此它应该过度拟合并预测该单个图像的正确边界框,如果它有效的话)。即使在对这张图片过度拟合之后,预测值也高得离谱。
所以我的问题是:
我做错了什么?
编辑 1
在尝试了@Matias 的解决方案后,即在最后一层添加一个 sigmoid 激活函数,所有输出值现在都在 [0,1] 之间。
但是,即使这样,模型仍然会产生错误的输出。
例如,在同一张图片上训练 10 个 epoch 后,它预测:
[array([0.0000000e+00, 0.0000000e+00, 8.4378130e-18, 4.2288357e-07],dtype=float32)]
但我的预期是:
[0.2866666666666667, 0.31333333333333335, 0.44666666666666666, 0.5]
编辑 2
好的,所以,经过一段时间的试验,我得出的结论是问题要么出在我的模型上(它的构建方式)
或者缺少训练数据。
但即使它是由于缺乏训练数据造成的,我也应该能够在 1 张图像上对其进行过拟合,以便对此图像做出正确的预测,对吧?
我创建了另一个 post,它询问我的最后一个问题,因为原始问题已经得到回答,我不想完全重新编辑 post,因为它会使第一个答案变得毫无意义。
由于您的目标(Y 值)已归一化到 [0, 1] 范围内,因此模型的输出应与该范围匹配。为此,您应该在输出层使用 sigmoid 激活,因此输出被限制在 [0, 1] 范围内:
model.add(Dense(4, activation='sigmoid'))
我是机器学习的初学者,目前我正在尝试预测图像中对象的位置,该图像是我创建的数据集的一部分。
该数据集总共包含大约 300 张图像,包含 2 classes(A 和 Two)。
我创建了一个 CNN,可以预测它是 A 还是 2,准确率约为 88%。
由于这个数据集做得很好,我决定尝试预测卡片的位置(而不是 class)。我阅读了一些文章,根据我的理解,我所要做的就是采用我用来预测 class 的相同 CNN,并将最后一层更改为 4 个节点的密集层。 这就是我所做的,但显然这是行不通的。
这是我的模型:
model = Sequential()
model.add(Conv2D(64,(3,3),input_shape = (150,150,1)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(32,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=2))
model.add(Dense(64))
model.add(Activation("relu"))
model.add(Flatten())
model.add(Dense(4))
model.compile(loss="mean_squared_error",optimizer='adam',metrics=[])
model.fit(X,y,batch_size=1,validation_split=0,
epochs=30,verbose=1,callbacks=[TENSOR_BOARD])
我为模型提供的内容:
X:150x150 像素的灰度图像。每个像素在 [0-1]
之间重新缩放y:对象的最小X坐标、最大Y坐标、宽高(每个值都在[0-1].
之间)这是它给我的预测示例:
[array([ 28.66145 , 41.278576, -9.568813, -13.520659], dtype=float32)]
但我真正想要的是:
[0.32, 0.38666666666666666, 0.4, 0.43333333333333335]
我知道这里出了点问题,所以我决定在单个图像上训练和测试我的 CNN(因此它应该过度拟合并预测该单个图像的正确边界框,如果它有效的话)。即使在对这张图片过度拟合之后,预测值也高得离谱。
所以我的问题是: 我做错了什么?
编辑 1
在尝试了@Matias 的解决方案后,即在最后一层添加一个 sigmoid 激活函数,所有输出值现在都在 [0,1] 之间。
但是,即使这样,模型仍然会产生错误的输出。 例如,在同一张图片上训练 10 个 epoch 后,它预测:
[array([0.0000000e+00, 0.0000000e+00, 8.4378130e-18, 4.2288357e-07],dtype=float32)]
但我的预期是:
[0.2866666666666667, 0.31333333333333335, 0.44666666666666666, 0.5]
编辑 2
好的,所以,经过一段时间的试验,我得出的结论是问题要么出在我的模型上(它的构建方式) 或者缺少训练数据。
但即使它是由于缺乏训练数据造成的,我也应该能够在 1 张图像上对其进行过拟合,以便对此图像做出正确的预测,对吧?
我创建了另一个 post,它询问我的最后一个问题,因为原始问题已经得到回答,我不想完全重新编辑 post,因为它会使第一个答案变得毫无意义。
由于您的目标(Y 值)已归一化到 [0, 1] 范围内,因此模型的输出应与该范围匹配。为此,您应该在输出层使用 sigmoid 激活,因此输出被限制在 [0, 1] 范围内:
model.add(Dense(4, activation='sigmoid'))