#tensorflow #keras #vgg-net
#tensorflow #keras #vgg-net
Вопрос:
Я загружаю автономный VGG19 на виртуальную машину Ubuntu с помощью Tensorflow1.14.0 следующим образом :
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)
однако, когда я хочу использовать VGG19 из tensorflow.keras для подавления двух полностью соединенных слоев 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
Я думаю, что функция function должна быть обновлена (переписана), чтобы использовать ее с VGG19 из tensorflow.keras. Как я мог его адаптировать?
Спасибо
Ответ №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())
в соответствии с их требованиями к фильтрам является тензором 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
Комментарии:
1. Спасибо за ваш ответ. Я понимаю, что я должен заменить «веса = VGG19_layers[n_layer][0][0][2][0][0]» по «весам=VGG19_layers[n_layers].веса[0][0][2][0][0]» и «смещение=VGG19_layers[n_layers].смещение[0][0][2][0][1]» по «смещению=VGG19_layers[n_layers].смещение[0][0][2][0][1]». При этом я получаю сообщение об ошибке «индекс вне диапазона», связанное со смещением.
2. Когда я смотрю на смещение, его ядро представляет собой вектор из 64 элементов, поэтому вы можете индексировать только один раз, чтобы получить к ним доступ:
VGG19_layers[1].bias
Out:<tf.Variable 'block1_conv1/bias:0' shape=(64,) dtype=float32>
3. VGG19_layers[1].смещение[0]
4. большое вам спасибо. Я постараюсь обновить свой код с учетом ваших рекомендаций. Могу ли я спросить позже, если код все еще не работает?
5. конечно. Нет проблем, приятель