使用Keras函数式API构建1D卷积分类模型时遇输入错误求助
问题分析与解决方案
嘿,我来帮你捋捋这个问题~你遇到的TypeError: unhashable type: 'numpy.ndarray'其实是两个关键错误导致的,咱们一步步来修正:
核心错误点拆解
- Input层的形状定义错了:Keras里
Input的shape参数只需要描述单个样本的结构,不需要包含总样本数(70408)。你的每个输入是长度为1400的序列,所以应该写shape=(1400,),而不是(samples, mass_size)。 - Model构造时传错了参数:
Model类的第一个参数得是你定义好的Input层对象(mass_input和intensity_input),而不是直接传训练数据数组(mass_data和intensity_data)——这就是你报错的直接原因。
修正后的完整代码
import tensorflow as tf from tensorflow.keras.layers import Input, Conv1D, AveragePooling1D, GlobalAveragePooling1D, concatenate, Dense from tensorflow.keras.models import Model samples = 70408 mass_size = 1400 intensity_size = 1400 output_size = 16450 # 修正Input的shape:只保留单个样本的维度 mass_input = Input(shape=(mass_size,), dtype='float32') mass_net = Conv1D(32, 5, activation='relu')(mass_input) mass_net = AveragePooling1D(3)(mass_net) mass_net = Conv1D(16, 5, activation='relu')(mass_net) mass_net = GlobalAveragePooling1D()(mass_net) intensity_input = Input(shape=(intensity_size,), dtype='float32') intensity_net = Conv1D(32, 5, activation='relu')(intensity_input) intensity_net = AveragePooling1D(3)(intensity_net) intensity_net = Conv1D(16, 5, activation='relu')(intensity_net) intensity_net = GlobalAveragePooling1D()(intensity_net) concatenated = concatenate([mass_net, intensity_net], axis=-1) output = Dense(output_size, activation='softmax')(concatenated) # 修正Model的输入参数:传入Input层,而非数据数组 model = Model([mass_input, intensity_input], output) model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['acc']) # 先确认数据形状没问题 print(mass_data.shape, intensity_data.shape) # 训练时再传入数据数组 model.fit([mass_data, intensity_data], y_train, epochs=10, batch_size=128)
额外提几个小建议
- 类别数过大的优化:16450个类别用
softmax+categorical_crossentropy会很吃内存,而且容易数值不稳定。建议改用sparse_categorical_crossentropy,这样不需要把y_train转成独热编码,能省不少资源。 - 数据预处理:记得把输入序列做标准化/归一化(比如缩到0-1区间,或者做Z-score标准化),这对卷积网络的训练效果影响很大。
- 防过拟合:如果后续出现过拟合,可以考虑加
Dropout层,或者调整卷积层的过滤器数量、核大小。
内容的提问来源于stack exchange,提问作者A Kwon
相关产品推荐
相关产品推荐

