作业前面具体怎么建立残差网络模型我这里就不多说了,只要按照老师的指导一步一步往下做就好了。我是在作业中Test on your own image这一可选模块中遇到这个问题的,具体问题是不论我输入的是代表什么数字的手势图片,最终预测出来都是数字0。比如我输入的是下面这个代表2的手势图片时,预测如下:
class prediction vector [p(0), p(1), p(2), p(3), p(4), p(5)] = [[1. 0. 0. 0. 0. 0.]]
上面表示预测输出的是0,因为这个残差网络训练计算代价很大,所以在前面要求导入了预训练的参数,我将其在测试集上跑了一下,准确度是98.333333%,所以按照逻辑来想导入我自己的测试图片预测也应该准确啊,就算偶尔不对,但是我输入任何一张手势图片输出都是上面这个,那就有问题了。
经过我自己不懈的查找,终于找到了问题所在,如下:
img_path = 'images/my_image5.jpg'
img = image.load_img(img_path, target_size=(64, 64))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
#x = preprocess_input(x) # 修改为下面这条语句
x = x / 255.
print('Input image shape:', x.shape)
my_image = scipy.misc.imread(img_path)
imshow(my_image)
print("class prediction vector [p(0), p(1), p(2), p(3), p(4), p(5)] = ")
#print(model.predict(x)) # 修改为下面这条语句
print(convert_to_one_hot(np.argmax(model.predict(x)), 6).T)
其主要原因是之前作业对训练集和测试集做的数据预处理操作是除以255.,将数据归一化到(0,1)之间,而这里变为了 preprocess_input()这个函数,我在keras官方网站以及网络上查找了关于它的介绍,发现其处理方式以及结果和前面所说的处理255.有很大不同。
除以255.属于简单缩放方式,它是通过对数据各个维度上的值进行重新调节,使得数据整体上分布在[0,1]或[-1,1]区间;而
preprocess_input是逐样本均值消减方式,也称为移除直流分量(remove DC),具体操作是把每个样本都减去所有样本的统计平均值。即在每个维度上减去样本的均值,对于维度顺序是channels_last的数据,keras中每个维度上的操作如下:
x[..., 0] -= 103.939
x[..., 1] -= 116.779
x[..., 2] -= 123.68
这样导致的结果便是数据处理后范围根本不在[0,1],因此预测会出问题。但这样处理后为什么预测总是0我还没有认识到,如果有知道的网友麻烦告知我,谢谢!
在将代码修正之后,上图的预测如下:
class prediction vector [p(0), p(1), p(2), p(3), p(4), p(5)] = [[0. 0. 1. 0. 0. 0.]]
我之后也试验了一下其他图片,发现预测与实际基本都相符。
参考资料:
https://keras.io/applications/#resnet
https://medium.com/@sci218mike/%E5%9C%96%E7%89%87%E9%A0%90%E8%99%95%E7%90%86%E4%BD%BF%E7%94%A8keras-applications-%E7%9A%84-preprocess-input-6ef0963a483e
https://blog.csdn.net/dcrmg/article/details/79559804
https://blog.csdn.net/ywxuan/article/details/87857921