简体   繁体   English

Keras 向中间层提供输入并获得最终输出

[英]Keras give input to intermediate layer and get final output

My model is a simple fully connected network like this:我的模型是一个简单的全连接网络,如下所示:

inp=Input(shape=(10,))
d=Dense(64, activation='relu')(inp)
d=Dense(128,activation='relu')(d)
d=Dense(256,activation='relu')(d)     #want to give input here, layer3
d=Dense(512,activation='relu')(d)
d=Dense(1024,activation='relu')(d)
d=Dense(128,activation='linear')(d)

So, after saving the model I want to give input to layer 3. What I am doing right now is this:因此,在保存模型后,我想为第 3 层提供输入。我现在正在做的是:

model=load_model('blah.h5')    #above described network
print(temp_input.shape)        #(16,256), which is equal to what I want to give

index=3
intermediate_layer_model = Model(inputs=temp_input,
                                 outputs=model.output)

End_output = intermediate_layer_model.predict(temp_input)

But it isn't working, ie I am getting errors like incompatible input, inputs should be tuple etc. The error message is:但它不起作用,即我收到诸如不兼容输入之类的错误,输入应该是元组等。错误消息是:

raise TypeError('`inputs` should be a list or tuple.') 
TypeError: `inputs` should be a list or tuple.

Is there any way I can pass my own inputs in middle of network and get the output instead of giving an input at the start and getting output from the end?有什么方法可以在网络中间传递我自己的输入并获得输出,而不是在开始时提供输入并从最后获得输出? Any help will be highly appreciated.任何帮助将不胜感激。

First you must learn that in Keras when you apply a layer on an input, a new node is created inside this layer which connects the input and output tensors.首先,您必须了解,在 Keras 中,当您在输入上应用层时, 会在该层内创建一个连接输入和输出张量的新节点 Each layer may have multiple nodes connecting different input tensors to their corresponding output tensors.每层可能有多个节点,将不同的输入张量连接到相应的输出张量。 To build a model, these nodes are traversed and a new graph of the model is created which consists all the nodes needed to reach output tensors from input tensors (ie which you specify when creating a model: model = Model(inputs=[...], outputs=[...]) .为了构建模型,遍历这些节点并创建模型的新图,其中包含从输入张量(即您在创建模型时指定的输出张量)所需的所有节点: model = Model(inputs=[...], outputs=[...])

Now you would like to feed an intermediate layer of a model and get the output of the model.现在您想提供模型的中间层并获得模型的输出。 Since this is a new data-flow path, we need to create new nodes for each layer corresponding to this new computational graph.由于这是一个新的数据流路径,我们需要为对应于这个新计算图的每一层创建新节点。 We can do it like this:我们可以这样做:

idx = 3  # index of desired layer
input_shape = model.layers[idx].get_input_shape_at(0) # get the input shape of desired layer
layer_input = Input(shape=input_shape) # a new input tensor to be able to feed the desired layer

# create the new nodes for each layer in the path
x = layer_input
for layer in model.layers[idx:]:
    x = layer(x)

# create the model
new_model = Model(layer_input, x)

Fortunately, your model consists of one-branch and we could simply use a for loop to construct the new model.幸运的是,您的模型由一个分支组成,我们可以简单地使用for循环来构建新模型。 However, for more complex models it may not be easy to do so and you may need to write more codes to construct the new model.但是,对于更复杂的模型,这样做可能并不容易,您可能需要编写更多代码来构建新模型。

Here is another method for achieving the same result.这是实现相同结果的另一种方法。 Initially create a new input layer and then connect it to the lower layers(with weights).最初创建一个新的输入层,然后将其连接到较低的层(带权重)。

For this purpose, first re-initialize these layers(with same name ) and reload the corresponding weights from the parent model using为此,首先重新初始化这些层(具有相同名称)并使用从父模型重新加载相应的权重

new_model.load_weights("parent_model.hdf5", by_name=True ) new_model.load_weights("parent_model.hdf5", by_name=True )

This will load the required weights from the parent model.Just make sure you name your layers properly beforehand.这将从父模型加载所需的权重。只需确保事先正确命名图层。

idx = 3  
input_shape = model.layers[idx].get_input_shape_at(0) layer

new_input = Input(shape=input_shape)

d=Dense(256,activation='relu', name='layer_3')(new_input)
d=Dense(512,activation='relu', name='layer_4'))(d)
d=Dense(1024,activation='relu', name='layer_5'))(d)
d=Dense(128,activation='linear', name='layer_6'))(d)

new_model = Model(new_input, d)
new_model.load_weights("parent_model.hdf5", by_name=True)

This method will work for complex models with multiple inputs or branches.You just need to copy the same code for required layers, connect the new inputs and finally load the corresponding weights.此方法适用于具有多个输入或分支的复杂模型。您只需为所需层复制相同的代码,连接新输入并最终加载相应的权重。

I was having the same problem and the proposed solutions worked for me but I was looking for something more explicit, so here it is for future reference:我遇到了同样的问题,建议的解决方案对我有用,但我正在寻找更明确的东西,所以在这里供将来参考:

 d1 = Dense(64, activation='relu') d2 = Dense(128,activation='relu') d3 = Dense(256,activation='relu') d4 = Dense(512,activation='relu') d5 = Dense(1024,activation='relu') d6 = Dense(128,activation='linear') inp = Input(shape=(10,)) x = d1(inp) x = d2(x) x = d3(x) x = d4(x) x = d5(x) x = d6(x) full_model = tf.keras.Model(inp, x) full_model.summary() intermediate_input = Input(shape=d3.get_input_shape_at(0)) # get shape at node 0 x = d3(intermediate_input) x = d4(x) x = d5(x) x = d6(x) partial_model = tf.keras.Model(intermediate_input, x) partial_model.summary()

Reference: https://keras.io/guides/functional_api/#shared-layers参考: https : //keras.io/guides/functional_api/#shared-layers

You can easily use keras.backend.function for this purpose:为此,您可以轻松使用 keras.backend.function:

import numpy as np
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K

inp=Input(shape=(10,))
d=Dense(64, activation='relu')(inp)
d=Dense(128,activation='relu')(d)
d=Dense(256,activation='relu')(d)     #want to give input here, layer3
d=Dense(512,activation='relu')(d)
d=Dense(1024,activation='relu')(d)
d=Dense(128,activation='linear')(d)

model = Model(inp, d)


foo1 = K.function(
    [inp],
    model.layers[2].output
)

foo2 = K.function(
    [model.layers[2].output],
    model.output
)


X = np.random.rand(1, 10)
X_intermediate = foo1([X])
print(np.allclose(foo2([X_intermediate]), model.predict(X)))

Sorry for ugly function naming - do it best)对不起,丑陋的函数命名 - 尽力而为)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM