使用 VGG16 预训练权重的 Imagenet 分类问题
Issue with Imagenet classification with VGG16 pretrained weights
我试图 运行 在 tensorflow 中使用 VGG16 网络进行香草图像网络分类(通过 Keras backbone 给出 VGG16)。
然而,当我尝试 运行 对样本大象图像进行分类时,它给出了完全出乎意料的结果。
我无法弄清楚可能是什么问题。
这是我使用的完整代码:
import tensorflow as tf
import numpy as np
from PIL import Image
from tensorflow.python.keras._impl.keras.applications import imagenet_utils
model = tf.keras.applications.VGG16()
VGG = model.graph
VGG.get_operations()
input = VGG.get_tensor_by_name("input_1:0")
output = VGG.get_tensor_by_name("predictions/Softmax:0")
print(input)
print(output)
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = np.expand_dims(image_array, axis=0)
with tf.Session(graph=VGG) as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
pred = (sess.run(output,{input:image_array}))
print(imagenet_utils.decode_predictions(pred))
下面是我得到的示例输出:
Tensor("input_1:0", shape=(?, 224, 224, 3), dtype=float32)
Tensor("predictions/Softmax:0", shape=(?, 1000), dtype=float32)
[[('n02281406', 'sulphur_butterfly', 0.0022673723), ('n01882714', 'koala', 0.0021256246), ('n04325704', 'stole', 0.0020583202), ('n01496331', 'electric_ray', 0.0020416214), ('n01797886', 'ruffed_grouse', 0.0020229272)]]
从概率上看,传递的图像数据似乎有问题(因为所有数据都很低)。
但我无法弄清楚哪里出了问题。
而且我非常确定图像是大象作为人!
我认为有 2 个错误,第一个是您必须将所有像素除以 255 来重新缩放图像。
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array /= 255.
image_array = np.expand_dims(image_array, axis=0)
第二点是我在看预测值的时候得到的。您有一个包含 1000 个元素的向量,并且所有元素在重新缩放后都有 0.1% 的预测。这意味着您有一个 non-trained 模型。我不知道如果在 tensorflow 中加载如何,但是在 Keras 上你可以这样做:
app = applications.vgg16
model = app.VGG16(
include_top=False, # this is to have the classifier Standard from imagenet
weights='imagenet', # this load weight, else it's random weight
pooling="avg")
根据我的阅读,您必须下载另一个包含权重的文件,例如 github。
希望对你有帮助,
编辑1:
我尝试了使用 Keras 的相同模型:
from keras.applications.vgg16 import VGG16, decode_predictions
import numpy as np
model = VGG16(weights='imagenet')
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = image_array/255.
x = np.expand_dims(image_array, axis=0)
preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=5)[0])
如果我评论重新缩放,我有错误的预测:
Predicted: [('n03788365', 'mosquito_net', 0.22725257), ('n15075141', 'toilet_tissue', 0.026636025), ('n04209239', 'shower_curtain', 0.019786758), ('n02804414', 'bassinet', 0.01353887), ('n03131574', 'crib', 0.01316699)]
没有重新缩放,这很好:
Predicted: [('n02504458', 'African_elephant', 0.95870858), ('n01871265', 'tusker', 0.040065952), ('n02504013', 'Indian_elephant', 0.0012253703), ('n01704323', 'triceratops', 5.0949382e-08), ('n02454379', 'armadillo', 5.0408511e-10)]
现在,如果我移除权重,我将拥有 "same" 与我在 Tensorflow 中拥有的一样:
Predicted: [('n07717410', 'acorn_squash', 0.0010033853), ('n02980441', 'castle', 0.0010028203), ('n02124075', 'Egyptian_cat', 0.0010028186), ('n04179913', 'sewing_machine', 0.0010027955), ('n02492660', 'howler_monkey', 0.0010027081)]
对我来说,这意味着你没有施加重量。也许它们已下载但未使用。
看来我们可以(或需要?)使用来自 Keras 的会话(它具有带权重的关联加载图),而不是在 Tensorflow 中创建新会话并使用从 Keras 模型获得的图,如下所示
VGG = model.graph
我认为上面的图表没有权重(这就是预测错误的原因),Keras 会话中的图表作为适当的权重(因此这两个图表实例应该不同)
完整代码如下:
import tensorflow as tf
import numpy as np
from PIL import Image
from tensorflow.python.keras._impl.keras.applications import imagenet_utils
from tensorflow.python.keras._impl.keras import backend as K
model = tf.keras.applications.VGG16()
sess = K.get_session()
VGG = model.graph #Not needed and also doesnt have weights in it
VGG.get_operations()
input = VGG.get_tensor_by_name("input_1:0")
output = VGG.get_tensor_by_name("predictions/Softmax:0")
print(input)
print(output)
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = np.expand_dims(image_array, axis=0)
image_array = image_array.astype(np.float32)
image_array = tf.keras.applications.vgg16.preprocess_input(image_array)
pred = (sess.run(output,{input:image_array}))
print(imagenet_utils.decode_predictions(pred))
这给出了预期的结果:
[[('n02504458', 'African_elephant', 0.8518132), ('n01871265', 'tusker', 0.1398836), ('n02504013', 'Indian_elephant', 0.0082286), ('n01704323', 'triceratops', 6.965483e-05), ('n02397096', 'warthog', 1.8662439e-06)]]
感谢 Idavid for the tip about using preprocess_input() function and Nicolas 关于卸载重量的提示。
我试图 运行 在 tensorflow 中使用 VGG16 网络进行香草图像网络分类(通过 Keras backbone 给出 VGG16)。
然而,当我尝试 运行 对样本大象图像进行分类时,它给出了完全出乎意料的结果。
我无法弄清楚可能是什么问题。
这是我使用的完整代码:
import tensorflow as tf
import numpy as np
from PIL import Image
from tensorflow.python.keras._impl.keras.applications import imagenet_utils
model = tf.keras.applications.VGG16()
VGG = model.graph
VGG.get_operations()
input = VGG.get_tensor_by_name("input_1:0")
output = VGG.get_tensor_by_name("predictions/Softmax:0")
print(input)
print(output)
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = np.expand_dims(image_array, axis=0)
with tf.Session(graph=VGG) as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
pred = (sess.run(output,{input:image_array}))
print(imagenet_utils.decode_predictions(pred))
下面是我得到的示例输出:
Tensor("input_1:0", shape=(?, 224, 224, 3), dtype=float32)
Tensor("predictions/Softmax:0", shape=(?, 1000), dtype=float32)[[('n02281406', 'sulphur_butterfly', 0.0022673723), ('n01882714', 'koala', 0.0021256246), ('n04325704', 'stole', 0.0020583202), ('n01496331', 'electric_ray', 0.0020416214), ('n01797886', 'ruffed_grouse', 0.0020229272)]]
从概率上看,传递的图像数据似乎有问题(因为所有数据都很低)。
但我无法弄清楚哪里出了问题。
而且我非常确定图像是大象作为人!
我认为有 2 个错误,第一个是您必须将所有像素除以 255 来重新缩放图像。
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array /= 255.
image_array = np.expand_dims(image_array, axis=0)
第二点是我在看预测值的时候得到的。您有一个包含 1000 个元素的向量,并且所有元素在重新缩放后都有 0.1% 的预测。这意味着您有一个 non-trained 模型。我不知道如果在 tensorflow 中加载如何,但是在 Keras 上你可以这样做:
app = applications.vgg16
model = app.VGG16(
include_top=False, # this is to have the classifier Standard from imagenet
weights='imagenet', # this load weight, else it's random weight
pooling="avg")
根据我的阅读,您必须下载另一个包含权重的文件,例如 github。
希望对你有帮助,
编辑1:
我尝试了使用 Keras 的相同模型:
from keras.applications.vgg16 import VGG16, decode_predictions
import numpy as np
model = VGG16(weights='imagenet')
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = image_array/255.
x = np.expand_dims(image_array, axis=0)
preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=5)[0])
如果我评论重新缩放,我有错误的预测:
Predicted: [('n03788365', 'mosquito_net', 0.22725257), ('n15075141', 'toilet_tissue', 0.026636025), ('n04209239', 'shower_curtain', 0.019786758), ('n02804414', 'bassinet', 0.01353887), ('n03131574', 'crib', 0.01316699)]
没有重新缩放,这很好:
Predicted: [('n02504458', 'African_elephant', 0.95870858), ('n01871265', 'tusker', 0.040065952), ('n02504013', 'Indian_elephant', 0.0012253703), ('n01704323', 'triceratops', 5.0949382e-08), ('n02454379', 'armadillo', 5.0408511e-10)]
现在,如果我移除权重,我将拥有 "same" 与我在 Tensorflow 中拥有的一样:
Predicted: [('n07717410', 'acorn_squash', 0.0010033853), ('n02980441', 'castle', 0.0010028203), ('n02124075', 'Egyptian_cat', 0.0010028186), ('n04179913', 'sewing_machine', 0.0010027955), ('n02492660', 'howler_monkey', 0.0010027081)]
对我来说,这意味着你没有施加重量。也许它们已下载但未使用。
看来我们可以(或需要?)使用来自 Keras 的会话(它具有带权重的关联加载图),而不是在 Tensorflow 中创建新会话并使用从 Keras 模型获得的图,如下所示
VGG = model.graph
我认为上面的图表没有权重(这就是预测错误的原因),Keras 会话中的图表作为适当的权重(因此这两个图表实例应该不同)
完整代码如下:
import tensorflow as tf
import numpy as np
from PIL import Image
from tensorflow.python.keras._impl.keras.applications import imagenet_utils
from tensorflow.python.keras._impl.keras import backend as K
model = tf.keras.applications.VGG16()
sess = K.get_session()
VGG = model.graph #Not needed and also doesnt have weights in it
VGG.get_operations()
input = VGG.get_tensor_by_name("input_1:0")
output = VGG.get_tensor_by_name("predictions/Softmax:0")
print(input)
print(output)
I = Image.open("Elephant.jpg")
new_img = I.resize((224,224))
image_array = np.array(new_img)[:, :, 0:3]
image_array = np.expand_dims(image_array, axis=0)
image_array = image_array.astype(np.float32)
image_array = tf.keras.applications.vgg16.preprocess_input(image_array)
pred = (sess.run(output,{input:image_array}))
print(imagenet_utils.decode_predictions(pred))
这给出了预期的结果:
[[('n02504458', 'African_elephant', 0.8518132), ('n01871265', 'tusker', 0.1398836), ('n02504013', 'Indian_elephant', 0.0082286), ('n01704323', 'triceratops', 6.965483e-05), ('n02397096', 'warthog', 1.8662439e-06)]]
感谢 Idavid for the tip about using preprocess_input() function and Nicolas 关于卸载重量的提示。