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
错误原因
Sequential模型是线性堆叠结构,仅支持单输入单输出的线性层序列,无法直接处理多分支模型拼接。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
关键修改点
- 导入
Input和Model类,替代原有的Sequential。 - 显式定义每个视图的输入层,明确输入形状。
- 将分支模型的输出作为张量传入
Concatenate层,而非直接传入模型实例。 - 用
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
相关产品推荐
相关产品推荐

