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

Keras合并模型报错:TypeError索引类型错误(ListWrapper)

问题:Keras拼接模型时抛出TypeError: list indices must be integers or slices, not ListWrapper

尝试用model.add(Concatenate([view1_model, view2_model]))拼接两个Keras模型时触发上述错误,相关代码及报错回溯如下:

相关代码

from keras.callbacks import ModelCheckpoint
from sklearn import svm
from sklearn.metrics import accuracy_score
from keras.utils.data_utils import get_file
from keras.layers import Dense, Concatenate
from keras.models import Sequential
from tensorflow.keras.optimizers import RMSprop
from keras.regularizers import l2

def create_model(layer_sizes1, layer_sizes2, input_size1, input_size2,
                    learning_rate, reg_par, outdim_size, use_all_singular_values):
    
    view1_model = build_mlp_net(layer_sizes1, input_size1, reg_par)
    view2_model = build_mlp_net(layer_sizes2, input_size2, reg_par)

    model = Sequential()
    model.add(Concatenate([view1_model, view2_model]))
    #model.add(Merge([view1_model, view2_model], mode='concat'))

    model_optimizer = RMSprop(lr=learning_rate)
    model.compile(loss=cca_loss(outdim_size, use_all_singular_values), optimizer=model_optimizer)

    return model

if __name__ == '__main__':

    save_to = './new_features.gz'

    outdim_size = 10

    input_shape1 = 784
    input_shape2 = 784

    # number of layers with nodes in each one
    layer_sizes1 = [1024, 1024, 1024, outdim_size]
    layer_sizes2 = [1024, 1024, 1024, outdim_size]

    # the parameters for training the network
    learning_rate = 1e-3
    epoch_num = 100
    batch_size = 800

    # the regularization parameter of the network
    reg_par = 1e-5

    # specifies if all the singular values should get used to calculate the correlation or just the top outdim_size ones
    use_all_singular_values = False

    # if a linear CCA should get applied on the learned features extracted from the networks
    apply_linear_cca = True


    # Each view is stored in a gzip file separately
    data1 = load_data('noisymnist_view1.gz', 'https://www2.cs.uic.edu/~vnoroozi/noisy-mnist/noisymnist_view1.gz')
    data2 = load_data('noisymnist_view2.gz', 'https://www2.cs.uic.edu/~vnoroozi/noisy-mnist/noisymnist_view2.gz')

    # Building, training, and producing the new features by DCCA
    model = create_model(layer_sizes1, layer_sizes2, input_shape1, input_shape2,
                            learning_rate, reg_par, outdim_size, use_all_singular_values)
    #model.summary()
    model = train_model(model, data1, data2, epoch_num, batch_size)

报错回溯

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_27/909436112.py in <module>
     47                             learning_rate, reg_par, outdim_size, use_all_singular_values)
     48     #model.summary()
---> 49     model = train_model(model, data1, data2, epoch_num, batch_size)
     50     model.summary()
     51     new_data = test_model(model, data1, data2, outdim_size, apply_linear_cca)

/tmp/ipykernel_27/2946459332.py in train_model(model, data1, data2, epoch_num, batch_size)
     28               batch_size=batch_size, epochs=epoch_num, shuffle=True,
     29               validation_data=([valid_set_x1, valid_set_x2], np.zeros(len(valid_set_x1))),
---> 30               callbacks=[checkpointer])
     31 
     32     model.load_weights("temp_weights.h5")

/opt/conda/lib/python3.7/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
   1182                 _r=1):
   1183               callbacks.on_train_batch_begin(step)
---> 1184               tmp_logs = self.train_function(iterator)
   1185               if data_handler.should_sync:
   1186                 context.async_wait()

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
    883 
    884       with OptionalXlaContext(self._jit_compile):
---> 885         result = self._call(*args, **kwds)
    886 
    887       new_tracing_count = self.experimental_get_tracing_count()

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
    931       # This is the first call of __call__, so we have to initialize.
    932       initializers = []
---> 933       self._initialize(args, kwds, add_initializers_to=initializers)
    934     finally:
    935       # At this point we know that the initialization is complete (or less

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in _initialize(self, args, kwds, add_initializers_to)
    758     self._concrete_stateful_fn = (
    759         self._stateful_fn._get_concrete_function_internal_garbage_collected(  # pylint: disable=protected-access
---> 760             *args, **kwds))
    761 
    762     def invalid_creator_scope(*unused_args, **unused_kwds):

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _get_concrete_function_internal_garbage_collected(self, *args, **kwargs)
   3064       args, kwargs = None, None
   3065     with self._lock:
---> 3066       graph_function, _ = self._maybe_define_function(args, kwargs)
   3067     return graph_function
   3068 
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _maybe_define_function(self, args, kwargs)
   3461 
   3462           self._function_cache.missed.add(call_context_key)
---> 3463           graph_function = self._create_graph_function(args, kwargs)
   3464           self._function_cache.primary[cache_key] = graph_function
   3465 
/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
   3306             arg_names=arg_names,
   3307             override_flat_arg_shapes=override_flat_arg_shapes,
---> 3308             capture_by_value=self._capture_by_value),
   3309         self._function_attributes,
   3310         function_spec=self.function_spec,

/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes, acd_record_initial_resource_uses)
   1005         _, original_func = tf_decorator.unwrap(python_func)
   1006 
---> 1007       func_outputs = python_func(*func_args, **func_kwargs)
   1008 
   1009       # invariant: `func_outputs` contains only Tensors, CompositeTensors,

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in wrapped_fn(*args, **kwds)
    666         # the function a weak reference to itself to avoid a reference cycle.
    667         with OptionalXlaContext(compile_with_xla):
---> 668           out = weak_wrapped_fn().__wrapped__(*args, **kwds)
    669         return out
    670 
/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    992           except Exception as e:  # pylint:disable=broad-except
    993             if hasattr(e, "ag_error_metadata"):
---> 994               raise e.ag_error_metadata.to_exception(e)
    995             else:
    996               raise

TypeError: in user code:

    /opt/conda/lib/python3.7/site-packages/keras/engine/training.py:853 train_function  *
        return step_function(self, iterator)
    /opt/conda/lib/python3.7/site-packages/keras/engine/training.py:842 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /opt/conda/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:1286 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /opt/conda/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:2849 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /opt/conda/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:3632 _call_for_each_replica
        return fn(*args, **kwargs)
    /opt/conda/lib/python3.7/site-packages/keras/engine/training.py:835 run_step  **
        outputs = model.train_step(data)
    /opt/conda/lib/python3.7/site-packages/keras/engine/training.py:787 train_step
        y_pred = self(x, training=True)
    /opt/conda/lib/python3.7/site-packages/keras/engine/base_layer.py:1037 __call__
        outputs = call_fn(inputs, *args, **kwargs)
    /opt/conda/lib/python3.7/site-packages/keras/engine/sequential.py:383 call
        outputs = layer(inputs, **kwargs)
    /opt/conda/lib/python3.7/site-packages/keras/engine/base_layer.py:1030 __call__
        self._maybe_build(inputs)
    /opt/conda/lib/python3.7/site-packages/keras/engine/base_layer.py:2659 _maybe_build
        self.build(input_shapes)  # pylint:disable=not-callable
    /opt/conda/lib/python3.7/site-packages/keras/utils/tf_utils.py:259 wrapper
        output_shape = fn(instance, input_shape)
    /opt/conda/lib/python3.7/site-packages/keras/layers/merge.py:496 build
        del reduced_inputs_shapes[i][self.axis]

    TypeError: list indices must be integers or slices, not ListWrapper

错误原因

  1. Sequential模型是线性堆叠结构,仅支持单输入单输出的线性层序列,无法直接处理多分支模型拼接。
  2. Concatenate层的输入要求是张量,而非完整的Model实例,直接传入模型会导致内部处理时类型不匹配,触发索引错误。

修复方案

改用Keras函数式API构建多输入模型,这是处理多分支、多输入场景的标准方式,修改后的create_model函数如下:

from keras.callbacks import ModelCheckpoint
from sklearn import svm
from sklearn.metrics import accuracy_score
from keras.utils.data_utils import get_file
from keras.layers import Dense, Concatenate, Input
from keras.models import Model  # 替换Sequential为Model类
from tensorflow.keras.optimizers import RMSprop
from keras.regularizers import l2

def create_model(layer_sizes1, layer_sizes2, input_size1, input_size2,
                    learning_rate, reg_par, outdim_size, use_all_singular_values):
    
    # 为每个视图定义独立输入层
    input1 = Input(shape=(input_size1,))
    input2 = Input(shape=(input_size2,))
    
    # 构建两个分支网络,将输入张量传入模型
    view1_output = build_mlp_net(layer_sizes1, input_size1, reg_par)(input1)
    view2_output = build_mlp_net(layer_sizes2, input_size2, reg_par)(input2)

    # 拼接两个分支的输出张量
    concatenated = Concatenate()([view1_output, view2_output])
    
    # 封装为完整的多输入模型
    model = Model(inputs=[input1, input2], outputs=concatenated)

    model_optimizer = RMSprop(lr=learning_rate)
    model.compile(loss=cca_loss(outdim_size, use_all_singular_values), optimizer=model_optimizer)

    return model

关键修改点

  1. 导入Input和Model类,替代原有的Sequential。
  2. 显式定义每个视图的输入层,明确输入形状。
  3. 将分支模型的输出作为张量传入Concatenate层,而非直接传入模型实例。
  4. 用Model类封装多输入和拼接后的输出,形成完整的多输入模型。

补充说明

如果build_mlp_net返回的是Sequential模型,需通过调用模型实例获取输出张量:

# 若build_mlp_net返回Sequential模型
view1_mlp = build_mlp_net(layer_sizes1, input_size1, reg_par)
view1_output = view1_mlp(input1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:40:47