将权重从一个Conv2D层复制到另一个Conv2D层

时间:2017-12-06 05:41:05

标签: python tensorflow keras conv-neural-network keras-layer

上下文

我使用Keras训练了一个关于MNIST的模型。我的目标是在第一层之后打印图像,第一层是Conv2D层。为了解决这个问题,我创建了一个具有单个Conv2D图层的新模型,在该图层中,我将权重从受过训练的网络复制到新网络中。

# Visualization for image ofter first convolution
model_temp = Sequential()
model_temp.add(Conv2D(32, (3, 3),
                         activation='relu', 
                         input_shape=(28,28,1,)))

trained_weights = model.layers[0].get_weights()[0]

model_temp.layers[0].set_weights(trained_weights)

activations = model_temp._predict(X_test)

变量model保存来自完整网络的训练数据。此外,Conv2D的输入参数与原始模型中的输入参数完全相同。

我已检查modelmodel_temp的两个权重的形状,并且都返回(3, 3, 1, 32)。从理论上讲,我应该能够从原始中获取权重,并将它们直接输入到新模型中单set_weights()层的Conv2D调用中。

在此卷积之后,变量名为'激活'将是一个张量,它为每个输入图像保存32个(层),26个输出值的矩阵。

错误

因此,当我运行此代码时,我收到此错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-152-4ae260f0fe89> in <module>()
      7 trained_weights = model.layers[0].get_weights()[0]
      8 print(trained_weights.shape)
----> 9 model_test = model_test.layers[0].set_weights(trained_weights)
     10 
     11 activations = model_test._predict(X_test[1, 28, 28, 1])

/usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in set_weights(self, weights)
   1189                              str(len(params)) +
   1190                              ' weights. Provided weights: ' +
-> 1191                              str(weights)[:50] + '...')
   1192         if not params:
   1193             return

ValueError: You called `set_weights(weights)` on layer "conv2d_60" with a  weight list of length 3, but the layer was expecting 2 weights. Provided weights: [[[[ -6.22274876e-01  -2.18614027e-01   5.29607059...

在最后一行,为什么set_weights(weights)要求长度为2而不是3?这个错误信息对我来说有点神秘,所以如果不是两个长度,那么&#34;期待两个权重&#34;意思?

此外,我愿意接受更简单的方法。

进一步调查后

在检查get_weights() params = self.weights if len(params) != len(weights): raise ValueError('You called `set_weights(weights)` on layer "' + self.name + '" with a weight list of length ' + str(len(weights)) + ', but the layer was expecting ' + str(len(params)) + ' weights. Provided weights: ' + str(weights)[:50] + '...') (第1168行)后,在此部分引发了错误:

(3, 3, 1, 32)

此条件检查确定我传入的长度(上面的# Print contents of weights property print(model.layers[0].weights) print(model_test.layers[0].weights) # Length test of tensors from get_weights call len_test = len(model.layers[0].get_weights()[0]) len_test2 = len(model_test.layers[0].get_weights()[0]) print("\nLength get_weights():") print("Trained Model: ", len_test, "Test Model: ", len_test2) # Length test of wights attributes from both models len_test3 = len(model.layers[0].weights) len_test4 = len(model_test.layers[0].weights) print("\nLength weights attribute:") print("Trained Model: ", len_test3, "Test Model: ", len_test4) 张量)是否等于此类的weights属性。所以我测试了这些属性如下:

[<tf.Variable 'conv2d_17/kernel:0' shape=(3, 3, 1, 32) dtype=float32_ref>,         <tf.Variable 'conv2d_17/bias:0' shape=(32,) dtype=float32_ref>]
[<tf.Variable 'conv2d_97/kernel:0' shape=(3, 3, 1, 32) dtype=float32_ref>, <tf.Variable 'conv2d_97/bias:0' shape=(32,) dtype=float32_ref>]

Length get_weights():
('Trained Model: ', 3, 'Test Model: ', 3)

Length weights attribute:
('Trained Model: ', 2, 'Test Model: ', 2)

输出:

tf.Variable

这个输出对我有百分之百的意义,因为每个模型中的这些卷积构造完全相同。它现在也很明显为什么它需要两个长度。这是因为权重属性是Conv2D的两个元素的列表。

进一步调查这个源文件,在第213行,我们看到权重保持&#34;列表trainable_weights和non_trainable_weights(按此顺序)的串联&#34;。

然后确定我可以从原始训练模型的setting an array element with a sequence层中获取权重属性并将其传递给满足此条件但是此条件不会检查传入数据的形状一点都不如果我从原始模型传递权重,我会从numpy中得到<jnlp spec="1.0+" codebase="http://localhost:8080/" href="EDoc.jsp?url=<%=request.getParameter("url")%>&file=<%=request.getParameter("file")%>"> <information> <title>Jnlp Testing</title> <vendor>YONG MOOK KIM</vendor> <homepage href="http://localhost:8080/"> <description>Testing Testing</description> </homepage> </information> <security> <all-permissions/> </security> <resources> <j2se version="1.6+"/> <jar href="SignatureApplet-1.0.jar"/> <extension name="Java Help" href="help.jnlp"/> </resources> <application-desc main-class=" com.narola.digitalsignature.EDoc2Jnlp"> <argument><%=request.getParameter("url")%></argument> <argument><%=request.getParameter("file")%></argument> </application-desc> </jnlp> 错误。

思想

我认为这是源代码中的一个错误。如果有人可以验证这一点,我会很棒。

1 个答案:

答案 0 :(得分:0)

你忘了偏向量。 conv2d的Get_weights()和set_weights()函数返回一个列表,其中权重矩阵作为第一个元素,偏向量作为第二个元素。所以错误正确地表明它需要一个包含2个成员的列表。因此,执行以下操作

trained_weights = model.layers[0].get_weights()
model_temp.layers[0].set_weights(trained_weights)

此外,如果您想从中间层获取输出,则无需手动传输权重。做以下事情会更方便

get_layer_output = K.function([model.input],
                                  [model.layers[0].output])
layer_output = get_layer_output([x])[0]

intermediate_layer_model = Model(inputs=model.input,
                                 outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict(data)
相关问题