You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow调用Conv2D层出现元组参数报错的修复方法

Keras自定义模型调用报错'_TupleWrapper' object is not callable解决

问题场景

复现Keras MNIST手写数字识别代码时,将模型改写为自定义类形式实现,运行到训练步执行前向传播时触发类型错误。
运行环境:

  • Python 3.8.3 x64
  • TensorFlow 2.10.0-dev20220517
  • Keras 2.10.0
  • Windows 10

原始问题代码(省略测试部分)

%matplotlib inline
from itertools import islice
import itertools
from itertools import count 

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tqdm import trange
from tensorflow.keras import Model
from keras.utils import to_categorical


(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

x_train, x_test = x_train[..., np.newaxis]/255.0, x_test[..., np.newaxis]/255.0

x_train = x_train.reshape((60000, 28, 28, 1))
x_train= x_train.astype('float32') / 255 # 像素值从[0,255]缩放至[0,1]

x_test = x_test.reshape((10000, 28, 28, 1))
x_test = x_test.astype('float32') / 255

train_labels = to_categorical(y_train)
test_labels = to_categorical(y_test)

print("Number of original training examples:", len(x_train))
print("Number of original test examples:", len(x_test))

data_mean = 0.1307
data_std = 0.3081

# 数据归一化
x_train = (x_train/255.0 - data_mean) / data_std
x_test = (x_test/255.0 - data_mean) / data_std
num_classes = 10
input_shape = (28, 28, 1)

# 学习率指数衰减,每个epoch(即len(x_train)步)按gamma系数衰减
scheduler = tf.keras.optimizers.schedules.ExponentialDecay(
    1,
    decay_steps=len(x_train),
    decay_rate=0.7)

# 定义梯度下降优化器
optimizer = tf.keras.optimizers.Adadelta(scheduler)
loss_object = tf.keras.losses.CategoricalCrossentropy()

train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.CategoricalCrossentropy(name='train_accuracy')

test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.CategoricalCrossentropy(name='test_accuracy')

@tf.function
def train_step(images, labels):
    with tf.GradientTape() as tape:
        predictions = model(images)
        loss = loss_object(labels, predictions)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    train_loss(loss)
    train_accuracy(labels, predictions)

@tf.function
def test_step(images, labels):
    predictions = model(images)
    t_loss = loss_object(labels, predictions)

    test_loss(t_loss)
    test_accuracy(labels, predictions)


class MyModel(tf.keras.models.Sequential):
    def __init__(self):
        super(MyModel, self).__init__()
        self.c1 = tf.keras.layers.Conv2D(32, (3,3), strides=(1,1),
                                      padding='valid', 
                                      activation='relu',
                                      input_shape=input_shape),
        self.max2d = tf.keras.layers.MaxPool2D(),
        self.c2 = tf.keras.layers.Conv2D(64, (3,3), strides=(1,1),
                                        padding='valid',
                                        activation='relu'),
        self.dropout1 = tf.keras.layers.Dropout(0.25),
        self.flatten = tf.keras.layers.Flatten(),
        self.dense1 = tf.keras.layers.Dense(64, activation='relu'),
        self.dropout2 = tf.keras.layers.Dropout(0.5),
        self.dense2 = tf.keras.layers.Dense(num_classes, activation='softmax')

    def call(self, x):
        x = self.c1(x)
        x = self.c2 (x)
        x = self.max2d(x)
        x = self.dropout1(x)
        x = self.flatten(x)
        x = self.dense1(x)
        x = self.dropout2(x)
        x = self.dense2(x)
        return x

model = MyModel()

train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

EPOCHS = 5

for epoch in range(EPOCHS):
    for images, labels in train_ds:        
        train_step(images, labels)  # 报错位置

    for test_images, test_labels in test_ds:
        test_step(test_images, test_labels)

完整报错信息

TypeError                                 Traceback (most recent call last)
d:\Machine_Learning\tensorflow_test.ipynb Cell 5' in <module>
      6 for epoch in range(EPOCHS):
      7     for images, labels in train_ds:        
----> 8         train_step(images, labels)
     10     for test_images, test_labels in test_ds:
     11         test_step(test_images, test_labels)

File c:\Python38\lib\site-packages\tensorflow\python\util\traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb

File ~\AppData\Local\Temp\__autograph_generated_file14pr1250.py:9, in outer_factory.<locals>.inner_factory.<locals>.tf__train_step(images, labels)
      7 with ag__.FunctionScope('train_step', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
      8     with ag__.ld(tf).GradientTape() as tape:
----> 9         predictions = ag__.converted_call(ag__.ld(model), (ag__.ld(images),), None, fscope)
     10         loss = ag__.converted_call(ag__.ld(loss_object), (ag__.ld(labels), ag__.ld(predictions)), None, fscope)
     11     gradients = ag__.converted_call(ag__.ld(tape).gradient, (ag__.ld(loss), ag__.ld(model).trainable_variables), None, fscope)

File c:\Python38\lib\site-packages\keras\utils\traceback_utils.py:69, in filter_traceback.<locals>.error_handler(*args, **kwargs)
     66   filtered_tb = _process_traceback_frames(e.__traceback__)
     67   # To get the full stack trace, call:
     68   # `tf.debugging.disable_traceback_filtering()`
---> 69   raise e.with_traceback(filtered_tb) from None
     70 finally:
     71   del filtered_tb

File ~\AppData\Local\Temp\__autograph_generated_filecwsasoc4.py:10, in outer_factory.<locals>.inner_factory.<locals>.tf__call(self, x)
      8 do_return = False
      9 retval_ = ag__.UndefinedReturnValue()
---> 10 x = ag__.converted_call(ag__.ld(self).c1, (ag__.ld(x),), None, fscope)
     11 x = ag__.converted_call(ag__.ld(self).c2, (ag__.ld(x),), None, fscope)
     12 x = ag__.converted_call(ag__.ld(self).max2d, (ag__.ld(x),), None, fscope)

TypeError: in user code:

    File "C:\Users\user\AppData\Local\Temp\ipykernel_17788\3342806354.py", line 21, in train_step  *
        predictions = model(images)
    File "c:\Python38\lib\site-packages\keras\utils\traceback_utils.py", line 69, in error_handler  **
        raise e.with_traceback(filtered_tb) from None
    File "C:\Users\user\AppData\Local\Temp\__autograph_generated_filecwsasoc4.py", line 10, in tf__call
        x = ag__.converted_call(ag__.ld(self).c1, (ag__.ld(x),), None, fscope)

    TypeError: Exception encountered when calling layer "my_model_7" (type MyModel).
    
    in user code:
    
        File "C:\Users\user\AppData\Local\Temp\ipykernel_17788\2012441124.py", line 56, in call  *
            x = self.c1(x)
    
        TypeError: '_TupleWrapper' object is not callable
    
    
    Call arguments received by layer "my_model_7" (type MyModel):
      • x=tf.Tensor(shape=(32, 28, 28, 1), dtype=float32)

根因分析

初期排查时误以为是Conv2D层传入了不符合格式要求的元组类型参数,最终定位问题根源:
模型__init__方法中定义各网络层时,多条层赋值语句末尾存在多余的尾逗号。Python语法规则中,赋值语句末尾的逗号会将等号右侧的对象自动封装为单元素元组,导致原本的Keras层实例被包装为Keras内部的_TupleWrapper元组对象,不再是可调用的层实例,因此前向传播调用层时触发类型错误。

修复方案

移除所有层定义语句末尾的多余尾逗号即可,修复后的正确模型定义代码如下:

class MyModel(tf.keras.models.Sequential):
    def __init__(self):
        super(MyModel, self).__init__()
        self.c1 = tf.keras.layers.Conv2D(32, (3,3), strides=(1,1),
                                      padding='valid', 
                                      activation='relu',
                                      input_shape=input_shape)
        self.max2d = tf.keras.layers.MaxPool2D()
        self.c2 = tf.keras.layers.Conv2D(64, (3,3), strides=(1,1),
                                        padding='valid',
                                        activation='relu')
        self.dropout1 = tf.keras.layers.Dropout(0.25)
        self.flatten = tf.keras.layers.Flatten()
        self.dense1 = tf.keras.layers.Dense(64, activation='relu')
        self.dropout2 = tf.keras.layers.Dropout(0.5)
        self.dense2 = tf.keras.layers.Dense(num_classes, activation='softmax')

    def call(self, x):
        x = self.c1(x)
        x = self.c2 (x)
        x = self.max2d(x)
        x = self.dropout1(x)
        x = self.flatten(x)
        x = self.dense1(x)
        x = self.dropout2(x)
        x = self.dense2(x)
        return x

内容的提问来源于stack exchange,提问作者Broken_Window

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 22:21:36