TensorFlow:加载预训练ResNet模型时出现错误

4
我想使用Tensorflow中的预训练ResNet模型。我下载了模型的代码resnet_v1.py)和检查点resnet_v1_50.ckpt)文件,可以在这里找到。
我已经通过使用以下帖子解决了ImportError: No module named 'nets'错误:请参见此处来自tsveti_iko的答案。
现在我遇到了以下错误,不知道该怎么办:
NotFoundError (see above for traceback): Restoring from checkpoint failed. 
This is most likely due to a Variable name or other graph key that is missing from the checkpoint. 
Please ensure that you have not altered the graph expected based on the checkpoint. Original error:

    Tensor name "resnet_v1_50/block1/unit_1/bottleneck_v1/conv1/biases" 
not found in checkpoint files /home/resnet_v1_50.ckpt
         [[node save/RestoreV2 (defined at my_resnet.py:34)  = 
RestoreV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, ...,
DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], _device="/job:localhost
/replica:0/task:0/device:CPU:0"](_arg_save/Const_0_0, save/RestoreV2
/tensor_names, save/RestoreV2/shape_and_slices)]]

这是我正在使用的代码,尝试加载模型:
import numpy as np
import tensorflow as tf
import resnet_v1

# Restore variables of resnet model
slim = tf.contrib.slim

# Paths
network_dir = "home/resnet_v1_50.ckpt"

# Image dimensions
in_width, in_height, in_channels = 224, 224, 3

# Placeholder
X = tf.placeholder(tf.float32, [None, in_width, in_height, in_channels])

# Define network graph
logits, activations = resnet_v1.resnet_v1_50(X, is_training=False)
prediction = tf.argmax(logits, 1)

with tf.Session() as sess:
    variables_to_restore = slim.get_variables_to_restore()
    saver = tf.train.Saver(variables_to_restore)
    saver.restore(sess, network_dir) 

    # Restore variables
    variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)

    # Feed random image into resnet
    img = np.random.randn(1, in_width, in_height, in_channels)
    pred = sess.run(prediction, feed_dict={X:img})

有人能告诉我为什么它不起作用吗?我该如何更改代码以使其运行?

1个回答

3

也许你可以使用tf.keras.applications中的ResNet50?

根据错误信息,如果您没有以任何方式更改图形,并且这是您的全部源代码,则可能非常难以调试。

如果您选择明智的tf.keras.applications.resnet50方法,您可以简单地这样做:

import tensorflow

in_width, in_height, in_channels = 224, 224, 3

pretrained_resnet = tensorflow.keras.applications.ResNet50(
    weights="imagenet",
    include_top=False,
    input_shape=(in_width, in_height, in_channels),
)

# You can freeze some layers if you want, depends on your task
# Make "top" (last 3 layers below) whatever fits your task as well

model = tensorflow.keras.models.Sequential(
    [
        pretrained_resnet,
        tensorflow.keras.layers.Flatten(),
        tensorflow.keras.layers.Dense(1024, activation="relu"),
        tensorflow.keras.layers.Dense(10, activation="softmax"),
    ]
)

print(model.summary())

现在,尤其是在即将到来的Tensorflow 2.0中,推荐采用这种方法,以确保代码的健全性和可读性。顺便说一句,这个模型与Tensorflow提供的模型相同,是从它那里转移过来的。

您可以在链接的文档和各种博客文章(如this one)或其他网络资源中了解更多关于tf.keras.applications的信息。

Keras中如何操作

回答评论中的问题:

  • 如何将图像传递给网络?:使用model.predict(image)进行预测,其中image是np.array。就这么简单。

  • 如何访问权重?:好吧,这个有点复杂...开玩笑,每个层都有一个.get_weights()方法,返回它的权重和偏置项,您可以使用for layer in model.layers()迭代所有层。您也可以使用model.get_weights()一次获取所有权重。

总之,你将学习Keras,并且在短时间内比调试此问题更加高效。他们有30秒指南的原因。
顺便说一下,Tensorflow默认提供了Keras,因此无论听起来多么令人困惑,Tensorflow的Keras版本是Tensorflow的一部分。这就是为什么我在示例中使用了tensorflow的原因。
使用Tensorflow Hub的解决方案
看起来你可以像这个链接中所述那样通过Hub加载和微调Resnet50。

我刚刚使用原始源代码加载了图形,没有对图形进行任何更改(至少我希望如此)。我不熟悉Keras,因此希望仅使用Tensorflow。我该如何将图像传递到网络中?我还需要访问所有层的权重、偏差和激活。我该如何在Keras中实现这一点? - Gilfoyle
更新了我的回答。Keras不是Tensorflow,因此您可以学习它,使用它而不会妨碍您,并且具有直观的API。哦,如果您真的需要,您可以使用tf.keras.estimator.model_to_estimator将Keras的模型转换为tf.Estimator - Szymon Maszke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接