TF2子类API构建双输入模型调用model.summary()报错求助
问题说明
使用TensorFlow 2子类API构建模型时,需要在call()中同时接收输入图像和目标解以完成图像重建,但双输入模式下调用model.summary()报错,单输入模式可正常运行。
可运行的单输入代码
import tensorflow as tf class subclass(tf.keras.Model): def __init__(self): super().__init__() self.conv = tf.keras.layers.Conv2D(28, 3, strides=1) self.pool = tf.keras.layers.MaxPool2D((2, 2)) self.dense_1 = tf.keras.layers.Dense(units=512, activation='relu') self.dense_2 = tf.keras.layers.Dense(units=784, activation='relu') def model(self): x = tf.keras.layers.Input(shape=(28, 28, 3)) return tf.keras.Model(inputs=[x], outputs=self.call(x)) def call(self, inputs): x = inputs x = self.conv(x) x = self.pool(x) v = tf.nn.relu(x) rec = self.dense_1(v) rec = self.dense_2(rec) return v, rec sub = subclass() sub.model().summary()
报错的双输入代码
import tensorflow as tf class subclass(tf.keras.Model): def __init__(self): super().__init__() self.conv = tf.keras.layers.Conv2D(28, 3, strides=1) self.pool = tf.keras.layers.MaxPool2D((2, 2)) self.dense_1 = tf.keras.layers.Dense(units=512, activation='relu') self.dense_2 = tf.keras.layers.Dense(units=784, activation='relu') def model(self): x = tf.keras.layers.Input(shape=(28, 28, 3)) y0 = tf.cast(tf.range(0, 10, 1), dtype=tf.float32) y = tf.keras.layers.Input(y0) return tf.keras.Model(inputs=[x, y], outputs=self.call([x, y])) def call(self, inputs): x, y = inputs # Match shapes for product y = tf.expand_dims(y, axis=-1) y = tf.expand_dims(y, axis=0) y = tf.expand_dims(y, axis=0) x = self.conv(x) x = self.pool(x) x = tf.reshape(x, (-1, x.shape[1] * x.shape[2], 10)) x = tf.expand_dims(x, axis=-1) v = tf.nn.relu(x) # Necessary operation for my reconstruction v_masked = tf.multiply(y, v) reconstruction = self.dense_1(v_masked) rec = self.dense_2(reconstruction) return v, rec sub = subclass() sub.model().summary()
报错信息
TypeError: Dimension value must be integer or None or have an __index__ method, got value '<tf.Tensor: shape=(), dtype=float32, numpy=0.0>' with type '<class 'tensorflow.python.framework.ops.EagerTensor'>'
或类似报错:
OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed in Graph execution. Use Eager execution or decorate this function with @tf.function. During handling of the above exception, another exception occurred: TypeError Traceback (most recent call last) TypeError: only integer scalar arrays can be converted to a scalar index ... TypeError: Error converting shape to a TensorShape: only integer scalar arrays can be converted to a scalar index.
问题根源
- Input层定义错误:
tf.keras.layers.Input()需要传入形状参数(如shape=(10,)),而非具体张量y0,否则会导致维度解析失败。 - 静态形状误用:
x.shape[1] * x.shape[2]使用了Tensor的静态形状,在图模式下静态形状元素是Tensor对象,无法直接做算术运算,需改用动态形状获取方式tf.shape(x)。
修正后的代码
import tensorflow as tf class subclass(tf.keras.Model): def __init__(self): super().__init__() self.conv = tf.keras.layers.Conv2D(28, 3, strides=1) self.pool = tf.keras.layers.MaxPool2D((2, 2)) self.dense_1 = tf.keras.layers.Dense(units=512, activation='relu') self.dense_2 = tf.keras.layers.Dense(units=784, activation='relu') def model(self): # 正确定义Input层:指定输入形状 x = tf.keras.layers.Input(shape=(28, 28, 3)) # y是长度为10的向量,指定shape=(10,) y = tf.keras.layers.Input(shape=(10,)) return tf.keras.Model(inputs=[x, y], outputs=self.call([x, y])) def call(self, inputs): x, y = inputs # 扩展y的维度以匹配x的形状,保持批量维度兼容 y = tf.expand_dims(y, axis=1) y = tf.expand_dims(y, axis=1) y = tf.expand_dims(y, axis=-1) x = self.conv(x) x = self.pool(x) # 使用tf.shape获取动态形状,避免图模式下的静态形状问题 x_shape = tf.shape(x) hw = x_shape[1] * x_shape[2] x = tf.reshape(x, (-1, hw, 10)) x = tf.expand_dims(x, axis=-1) v = tf.nn.relu(x) v_masked = tf.multiply(y, v) reconstruction = self.dense_1(v_masked) rec = self.dense_2(reconstruction) return v, rec sub = subclass() sub.model().summary()
关键修正点
- Input层:将
y = tf.keras.layers.Input(y0)改为y = tf.keras.layers.Input(shape=(10,)),明确输入形状而非传入具体张量。 - 动态形状计算:用
tf.shape(x)[1] * tf.shape(x)[2]替代x.shape[1] * x.shape[2],确保图模式下能正确处理维度计算。 - 维度扩展调整:调整
y的expand_dims顺序,确保和处理后的x维度完全匹配,避免广播错误。
内容的提问来源于stack exchange,提问作者Nankin
相关产品推荐
相关产品推荐

