ValueError: Graph disconnected - 如何将 keras 模型拆分为子模型

数据挖掘 神经网络 喀拉斯 张量流
2021-09-25 15:29:09

keras如果您已安装并安装以下代码段,则应复制该错误tensorflow

import tensorflow as tf
import keras
from keras.layers import Input, Conv2D, MaxPooling2D, GlobalMaxPooling2D, GlobalAveragePooling2D
from keras.layers import Concatenate, Dense, LSTM, Flatten, RepeatVector, TimeDistributed, Dropout
from keras.models import Model
from keras.optimizers import Adam
from keras.layers import Bidirectional, GaussianNoise, BatchNormalization
from keras.layers import CuDNNLSTM as LSTM

# Dimensions
input_shape = (105, 29)
dec_input_shape = (104, 29)

output_len = 104
output_dims = 29

lstm_dim = 256
bottleneck_dim = 128
h_activation = "relu"

bn_momentum=0.9

# Architecture
encoder_inputs = Input(shape=input_shape)
x = encoder_inputs

encoder = Bidirectional(LSTM(lstm_dim//2,
               return_sequences=True,
               return_state=True,
               name="Encoder_LSTM"))

encoder2 = Bidirectional(LSTM(lstm_dim//2,
               return_state=True, 
               name="Encoder_LSTM2"))

x ,state_h, state_c, state_h_reverse, state_c_reverse = encoder(x)
x = BatchNormalization(momentum=bn_momentum)(x)
encoder_outputs, state_h2, state_c2 , state_h2_reverse, state_c2_reverse = encoder2(x)

states = Concatenate(axis=-1)([state_h, state_c, state_h2, state_c2,
                              state_h_reverse, state_c_reverse, state_h2_reverse, state_c2_reverse])

states = BatchNormalization(momentum=bn_momentum)(states)

neck_relu = Dense(bottleneck_dim, activation=h_activation, name='bottleneck_relu')
neck_outputs = neck_relu(states)
neck_outputs = BatchNormalization(momentum=bn_momentum, name="BN_bottleneck")(neck_outputs)

decode_h = Dense(lstm_dim, activation="relu")
decode_c = Dense(lstm_dim, activation="relu")
decode_h2 = Dense(lstm_dim, activation="relu")
decode_c2 = Dense(lstm_dim, activation="relu")

state_h_decoded =  decode_h(neck_outputs)
state_c_decoded =  decode_c(neck_outputs)
state_h_decoded2 =  decode_h2(neck_outputs)
state_c_decoded2 =  decode_c2(neck_outputs)

state_h_decoded_BN =  BatchNormalization(momentum=bn_momentum)
state_c_decoded_BN =  BatchNormalization(momentum=bn_momentum)
state_h_decoded2_BN =  BatchNormalization(momentum=bn_momentum)
state_c_decoded2_BN =  BatchNormalization(momentum=bn_momentum)

state_h_decoded =  state_h_decoded_BN(state_h_decoded)
state_c_decoded =  state_c_decoded_BN(state_c_decoded)
state_h_decoded2 =  state_h_decoded2_BN(state_h_decoded2)
state_c_decoded2 =  state_c_decoded2_BN(state_c_decoded2)

encoder_states = [state_h_decoded, state_c_decoded]
encoder_states2 = [state_h_decoded2, state_c_decoded2]

decoder_inputs = Input(shape=dec_input_shape)

decoder_lstm = LSTM(lstm_dim,
                    return_sequences=True,
                    name='LSTM1_decoder'
                   )
decoder_lstm2 = LSTM(lstm_dim,
                    return_sequences=True,
                    name='LSTM2_decoder'
                   )


xo = decoder_lstm(decoder_inputs, initial_state=encoder_states)
xo = BatchNormalization(momentum=bn_momentum, name="BN_decoder")(xo)
decoder_outputs = decoder_lstm2(xo, initial_state=encoder_states2)

outputs = Dense(output_dims, activation='softmax', name="Dense_decoder")(decoder_outputs)

# Define model
model = Model([encoder_inputs, decoder_inputs], outputs)

模型总结如下: 在此处输入图像描述

我想从完整模型中创建一个子模型,它将层的输出作为输入input_11,将最后一层的输出作为输出,即Dense_decoder. 因此,我将新模型定义为:

model_new = Model(model.get_layer("input_11").output, model.get_layer("Dense_decoder").output)

这给了我以下错误,即图表已断开连接

ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_10:0", shape=(?, 105, 29), dtype=float32) at layer "input_10". The following previous layers were accessed without issue: []

知道为什么会这样吗?或者一般如何规避问题并将其定义model_new为现有完整模型的子模型?

谢谢!

2个回答

无法按照您的定义创建子模型,因为LSTM1_decoderLSTM2_decoder层都依赖于先前的模型层(因此最终依赖于初始输入层)通过它们的初始状态。从您的代码:

xo = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_outputs = decoder_lstm2(xo, initial_state=encoder_states2)

的定义model_new

model_new = Model(model.get_layer("input_11").output, model.get_layer("Dense_decoder").output)

也可以写成

model_new = Model(decoder_inputs, outputs)

与您的原始模型定义相比:

model = Model([encoder_inputs, decoder_inputs], outputs)

使问题变得清晰-您还需要encoder_inputs,此时两个模型是相同的。

我无法让您的示例运行。这是一个代码示例,其中一个新模型是从现有模型的一部分构建的:

# Explicitly define new model input and output by slicing out old model layers
model_new = Model(input=model_old.layers[0].input, 
                  output=model_old.layers[12].output)

# Compile model to inspect
model_new.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

# Visually inspect new model to confirm it has the correct architecture
model_new.summary()