CNN训练报错:预期dense_10形状(1,)却得到(19316,)求解决方案
首先咱们直接抓核心:你遇到的报错完全是因为损失函数和任务类型不匹配,再加上模型里有个多余的层,以及生成器、训练参数的小问题,一步步来改就行。
1. 为什么Keras期望形状是(1,)?
你用了sparse_categorical_crossentropy作为损失函数——这个损失是专门给单标签分类任务设计的,它要求你的标签是单个整数(比如类别0、1、2...),形状自然是(1,)。但你的任务是输出19316维的数组(对应拉平的标签图像),属于回归任务(比如图像重建、像素级预测这类),完全不适用分类损失,所以Keras才会报形状不匹配的错误。
2. 具体修改步骤
(1)替换损失函数
把分类损失换成回归类损失,比如最常用的均方误差(如果你的标签是归一化到0-1区间的,也可以用mean_absolute_error,按需选择):
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mse'], options=run_opts)
(2)删除多余的Softmax层
你的模型在Flatten之前加了Activation('softmax'),这个层是分类任务用来输出概率分布的,回归任务完全不需要,而且放在卷积池化之后会破坏特征,必须删掉:
# 删掉这一行多余的层 model.add(Activation('softmax'))
(3)修正生成器的小问题
生成器里的transpose()完全没必要,因为flatten()之后已经是一维数组了,直接简化;另外生成器里的num计算逻辑也有问题,不需要提前截断,让循环自然处理即可:
def generator(data_arr, batch_size=10): num = len(data_arr) # Loop forever so the generator never terminates while True: # 按batch_size遍历,自动处理最后一个不足batch的情况 for offset in range(0, num, batch_size): batch_samples = data_arr[offset:offset+batch_size] samples = [] labels = [] for batch_sample in batch_samples: samples.append(batch_sample[0]) labels.append(batch_sample[1].flatten()) X_ = np.array(samples) Y_ = np.array(labels) X_ = X_[:, :, :, newaxis] yield (X_, Y_)
(4)修正fit_generator的步数参数
steps_per_epoch和validation_steps应该是总样本数除以batch_size,而不是直接用样本总数,不然训练会重复循环很多次;同时要保证和生成器的batch_size保持一致:
batch_size = 10 # 和生成器的batch_size统一! nb_epoch = 6 model.fit_generator( train_generator, steps_per_epoch=len(training_data) // batch_size, epochs=nb_epoch, validation_data=validation_generator, validation_steps=len(val_data) // batch_size )
3. 验证修改效果
修改完成后,模型输出层dense_10的形状是(None, 19316),和你的标签形状(batch_size, 19316)完全匹配,不会再报形状不匹配的错误了。
内容的提问来源于stack exchange,提问作者lr99

