构建124x124人像生成CNN模型时遇ValueError问题求助
解决Keras Sequential模型未调用导致的input未定义错误
我正在构建一个用于生成124×124像素人像的CNN模型,代码如下:
model = Sequential() model.add(Embedding(num_samples, PARAM_SIZE, input_shape = (1,))) print (model.output_shape) model.add(Flatten(name='pre_encoder')) print (model.output_shape) model.add(Reshape((PARAM_SIZE, 1, 1), name='encoder')) print (model.output_shape) model.add(Conv2DTranspose(256, 4)) #(4, 4) model.add(Activation("relu")) print (model.output_shape) model.add(Conv2DTranspose(256, 4, strides = 2)) #(10,10) model.add(Activation("relu")) print (model.output_shape) model.add(Conv2DTranspose(128, 4)) #(13, 13) model.add(Activation("relu")) print (model.output_shape) model.add(Conv2DTranspose(64, 4, strides = 2)) #(28,28) model.add(Activation("relu")) print (model.output_shape) model.add(Conv2DTranspose(32, 6, strides = 2)) #(60,60) model.add(Activation("relu")) print (model.output_shape) model.add(Conv2DTranspose(3, 6, strides = 2)) #(124,124) model.add(Activation("sigmoid")) print (model.output_shape) model.compile(optimizer='adam', loss='mse') func = Model(inputs = model.get_layer('encoder').input, outputs = model.layers[-1].output) enc_model = Model(inputs=model.input, outputs=model.get_layer('pre_encoder').output)
运行代码时出现如下错误:
ValueError Traceback (most recent call last) Cell In[11], line 2 1 # model.layers[-1].output ----> 2 model.input File D:\Program_files\envs\btp_project\Lib\site-packages\keras\src\ops\operation.py:228, in Operation.input(self) 218 @property 219 def input(self): 220 """Retrieves the input tensor(s) of a symbolic operation. 221 222 Only returns the tensor(s) corresponding to the *first time* (...) 226 Input tensor or list of input tensors. 227 """ --> 228 return self._get_node_attribute_at_index(0, "input_tensors", "input") File D:\Program_files\envs\btp_project\Lib\site-packages\keras\src\ops\operation.py:259, in Operation._get_node_attribute_at_index(self, node_index, attr, attr_name) 243 """Private utility to retrieves an attribute (e.g. inputs) from a node. 244 245 This is used to implement the properties: (...) 256 The operation's attribute `attr` at the node of index `node_index`. 257 """ 258 if not self._inbound_nodes: --> 259 raise ValueError( 260 f"The layer {self.name} has never been called " 261 f"and thus has no defined {attr_name}." 262 ) 263 if not len(self._inbound_nodes) > node_index: 264 raise ValueError( 265 f"Asked to get {attr_name} at node " 266 f"{node_index}, but the operation has only " 267 f"{len(self._inbound_nodes)} inbound nodes." 268 ) ValueError: The layer sequential has never been called and thus has no defined input.
错误原因
Keras的Sequential模型在未被实际调用(传入数据执行前向传播)之前,不会生成具体的输入/输出张量节点。当你尝试访问model.input或通过model.get_layer('encoder').input创建子模型时,原模型还未完成一次前向计算,因此无法获取这些张量属性。
解决方案
方式一:触发模型前向传播
在创建子模型之前,喂入一个符合输入形状的测试数据,让模型完成一次前向计算,生成所需的节点信息:
import tensorflow as tf from tensorflow.keras.models import Sequential, Model from tensorflow.keras.layers import Embedding, Flatten, Reshape, Conv2DTranspose, Activation # 假设已定义num_samples和PARAM_SIZE num_samples = 10000 PARAM_SIZE = 128 model = Sequential() model.add(Embedding(num_samples, PARAM_SIZE, input_shape=(1,))) print(model.output_shape) model.add(Flatten(name='pre_encoder')) print(model.output_shape) model.add(Reshape((PARAM_SIZE, 1, 1), name='encoder')) print(model.output_shape) model.add(Conv2DTranspose(256, 4)) #(4, 4) model.add(Activation("relu")) print(model.output_shape) model.add(Conv2DTranspose(256, 4, strides=2)) #(10,10) model.add(Activation("relu")) print(model.output_shape) model.add(Conv2DTranspose(128, 4)) #(13, 13) model.add(Activation("relu")) print(model.output_shape) model.add(Conv2DTranspose(64, 4, strides=2)) #(28,28) model.add(Activation("relu")) print(model.output_shape) model.add(Conv2DTranspose(32, 6, strides=2)) #(60,60) model.add(Activation("relu")) print(model.output_shape) model.add(Conv2DTranspose(3, 6, strides=2)) #(124,124) model.add(Activation("sigmoid")) print(model.output_shape) model.compile(optimizer='adam', loss='mse') # 关键:喂入测试数据触发前向传播 test_input = tf.random.uniform((1, 1), maxval=num_samples, dtype=tf.int32) model(test_input) # 现在可正常创建子模型 func = Model(inputs=model.get_layer('encoder').input, outputs=model.layers[-1].output) enc_model = Model(inputs=model.input, outputs=model.get_layer('pre_encoder').output)
方式二:改用函数式API构建模型
函数式API从一开始就显式定义张量流动,所有层的输入输出张量都是明确的,无需依赖模型调用生成节点,更适合需要提取中间层构建子模型的场景:
import tensorflow as tf from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, Flatten, Reshape, Conv2DTranspose, Activation num_samples = 10000 PARAM_SIZE = 128 # 显式定义输入层 input_layer = Input(shape=(1,)) x = Embedding(num_samples, PARAM_SIZE)(input_layer) print(x.shape) pre_encoder = Flatten(name='pre_encoder')(x) print(pre_encoder.shape) encoder = Reshape((PARAM_SIZE, 1, 1), name='encoder')(pre_encoder) print(encoder.shape) x = Conv2DTranspose(256, 4)(encoder) #(4, 4) x = Activation("relu")(x) print(x.shape) x = Conv2DTranspose(256, 4, strides=2)(x) #(10,10) x = Activation("relu")(x) print(x.shape) x = Conv2DTranspose(128, 4)(x) #(13, 13) x = Activation("relu")(x) print(x.shape) x = Conv2DTranspose(64, 4, strides=2)(x) #(28,28) x = Activation("relu")(x) print(x.shape) x = Conv2DTranspose(32, 6, strides=2)(x) #(60,60) x = Activation("relu")(x) print(x.shape) output_layer = Conv2DTranspose(3, 6, strides=2)(x) #(124,124) output_layer = Activation("sigmoid")(output_layer) print(output_layer.shape) model = Model(inputs=input_layer, outputs=output_layer) model.compile(optimizer='adam', loss='mse') # 直接创建子模型,无需提前调用模型 func = Model(inputs=encoder, outputs=output_layer) enc_model = Model(inputs=input_layer, outputs=pre_encoder)
内容的提问来源于stack exchange,提问作者Rishi Saini
相关产品推荐
相关产品推荐

