【问题标题】:VGG19 from tf.keras does not support indexing来自 tf.keras 的 VGG19 不支持索引
【发布时间】:2020-09-21 00:16:14
【问题描述】:

我正在使用 Tensorflow1.14.0 的 Ubuntu 虚拟机中加载独立的 VGG19,如下所示:

VGG19 = scipy.io.loadmat(path_VGG19) #stored in my disc
VGG19_layers = VGG19['layers'][0]

然后我将它传递给函数_conv2dWithRelu():

def _conv2dWithRelu(prev_layer, n_layer, layer_name,VGG19_layers):
    # get weights for this layer:
    weights = VGG19_layers[n_layer][0][0][2][0][0]
    W = tf.constant(weights)
    bias = VGG19_layers[n_layer][0][0][2][0][1]
    b = tf.constant(np.reshape(bias, (bias.size)))
    # create a conv2d layer
    conv2d = tf.nn.conv2d(prev_layer, filter=W, strides=[1, 1, 1, 1], padding='SAME') + b    
    # add a ReLU function and return
    return tf.nn.relu(conv2d)

但是,当我想使用 tensorflow.keras 中的 VGG19 来抑制两个全连接层 FC 以管理图像输入大小时,我会像这样加载它:

from tensorflow.keras.applications.vgg19 import VGG19
from tensorflow.keras.layers import Input

model = VGG19(weights="imagenet", include_top=False, input_tensor=Input(shape=(1200, 1600,  
        3))) #my target input shape
VGG19_layers = model.layers

问题是当我调用上面定义的函数 _conv2dWithRelu() 时,我收到以下错误:

TypeError: 'InputLayer' object does not support indexing

我认为应该更新(重新编写)函数函数以将其与 tensorflow.keras 中的 VGG19 一起使用。我该如何适应它?

谢谢

【问题讨论】:

    标签: tensorflow keras vgg-net


    【解决方案1】:

    很容易找出问题所在。如果你显示来自model.layers 的结果,你会看到每一层都是一个对象类型

    [<tensorflow.python.keras.engine.input_layer.InputLayer object at 0x7f550fc09510>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550f0c8ed0>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ed32fd0>, <tensorflow.python.keras.layers.pooling.MaxPooling2D object at 0x7f550eca3b10>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ecb5c10>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ecc3ad0>, <tensorflow.python.keras.layers.pooling.MaxPooling2D object at 0x7f550ecd6910>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec5d190>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec69850>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec7a6d0>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec7a850>, <tensorflow.python.keras.layers.pooling.MaxPooling2D object at 0x7f550ec1aed0>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec220d0>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec2cbd0>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ed5b110>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f5516559210>, <tensorflow.python.keras.layers.pooling.MaxPooling2D object at 0x7f5516558810>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ec54b90>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ebdbe10>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ebedf90>, <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7f550ebfe7d0>, <tensorflow.python.keras.layers.pooling.MaxPooling2D object at 0x7f550ec11790>]

    当您通过 VGG19_layers[n_layer][0]0[0][0] 对它们进行索引时,您无法获得它。您应该将 VGG19_layers[n_layer].weights() 替换为权重,而将 VGG19_layers[n_layer].bias() 替换为。

    详情VGG19_layers[1].weights[0][0] 是权重的索引。您可以自己动手解决您的问题。 <tf.Variable 'block1_conv1/kernel:0' shape=(3, 3, 3, 64) dtype=float32>

    此外,VGG19_layers[0] 将是没有权重和偏差的输入层。因此,你应该从[1]开始你的层,而不是[0] VGG19_layers[0].weights "results": []

    当我检查您的代码时,看起来您正试图保持卷积层的权重并将其传递给 relu。然后,不要像您所做的那样对权重进行切片,您应该将整个权重复制到您创建的新卷积的过滤器中。为此,我建议您使用 tf2.x。当您检查 tf2.x 中权重层的值时,它们会为您提供该过滤器的矩阵,您可以通过以下方式调用它

    weights = tf.constant(VGG19_layers[1].weights[0].numpy())

    根据their requirement 的过滤器是一个 4d 张量

    那么你只需要传递给卷积

    conv2d = tf.nn.conv2d(x, filters=weights, strides=[1, 1, 1, 1], padding='SAME')

    The output is ok: `<tf.Tensor: shape=(1, 5, 5, 64), dtype=float32, numpy=
    array([[[[-4.9203668e+00,  3.2815304e-01,  1.2678468e-01, ...,
              -1.8555930e+00,  1.6412614e-01, -7.1041006e-01],
             [-5.3053970e+00,  6.5529823e-01,  8.3891630e-01, ...,
              -3.1440034e+00,  2.6984088e+00,  1.3087101e+00],
             [-3.3932714e+00,  8.7002671e-01,  1.2363169e+00, ...,
              -2.6702189e+00,  4.4932485e+00,  2.9435217e+00],
             [-5.1859131e+00,  3.8122973e-01,  2.3676270e-01, ...,
    ....`
    

    tf.nn.bias_add 相同的操作

    【讨论】:

    • 感谢您的回复。我知道我应该将“weights = VGG19_layers[n_layer][0][0][2][0][0]”替换为“weights=VGG19_layers[n_layers].weights[0][0][2][0] ][0]" 和 "bias=VGG19_layers[n_layers].bias[0][0][2][0][1]" by "bias=VGG19_layers[n_layers].bias[0][0][2] [0][1]”。执行此操作时,我收到与偏差相关的错误“索引超出范围”。
    • 当我查看偏差时,它的内核是一个 64 个元素的向量,因此,您只能索引一次来访问它们:VGG19_layers[1].bias 输出:&lt;tf.Variable 'block1_conv1/bias:0' shape=(64,) dtype=float32&gt;
    • VGG19_layers[1].bias[0]
    • 非常感谢。我将尝试根据您的建议更新我的代码。我可以稍后询问我的代码是否仍然无法正常工作吗?
    • 当然。没问题的朋友
    猜你喜欢
    • 1970-01-01
    • 2022-11-27
    • 2021-09-02
    • 2019-08-18
    • 2019-09-23
    • 1970-01-01
    • 2014-04-23
    • 2019-11-12
    • 2018-10-29
    相关资源
    最近更新 更多