MNIST数据集使用cross_val_score遇形状不兼容错误:Shapes (None,1)与(None,10)不兼容
MNIST数据集K折交叉验证错误修复方案
你遇到的ValueError: Shapes (None, 1) and (None, 10) are incompatible错误,核心原因是标签格式与损失函数要求不匹配:模型输出是10维的softmax结果,但输入的original_y_train是一维整数标签,而categorical_crossentropy损失函数要求标签为独热编码的二维格式。以下是两种直接可行的修复方案:
方案1:转换标签为独热编码,保留categorical_crossentropy
使用Keras提供的to_categorical工具将一维整数标签转换为10维独热编码,确保标签形状与模型输出一致:
修正后完整代码
from tensorflow.keras.utils import to_categorical from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Flatten from tensorflow.keras.wrappers.scikit_learn import KerasClassifier from sklearn.model_selection import cross_val_score from tensorflow.keras.datasets import mnist # 加载并预处理数据 (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train = X_train / 255.0 # 像素值归一化到0-1区间 # 将整数标签转换为10维独热编码 y_train_onehot = to_categorical(y_train, num_classes=10) # 定义模型构建函数 def build_model(): model = Sequential([ Flatten(input_shape=(28,28)), # 将28*28的二维图像展平为一维 Dense(128, activation='relu'), Dense(10, activation='softmax') # 10类输出,用softmax激活 ]) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) return model # 封装Keras模型为scikit-learn兼容的分类器 estimator = KerasClassifier(build_fn=build_model, epochs=10, batch_size=32, verbose=0) # 执行5折交叉验证 scores = cross_val_score(estimator, X_train, y_train_onehot, cv=5) print(f"交叉验证准确率: {scores.mean():.4f} ± {scores.std():.4f}")
方案2:改用sparse_categorical_crossentropy损失函数(更简洁)
该损失函数专门适配一维整数标签,无需对y_train做任何格式转换,内部会自动完成标签与softmax输出的匹配:
修正后完整代码
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Flatten from tensorflow.keras.wrappers.scikit_learn import KerasClassifier from sklearn.model_selection import cross_val_score from tensorflow.keras.datasets import mnist # 加载并预处理数据(无需修改标签) (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train = X_train / 255.0 # 定义模型构建函数,修改损失函数 def build_model(): model = Sequential([ Flatten(input_shape=(28,28)), Dense(128, activation='relu'), Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', # 替换为适配整数标签的损失函数 metrics=['accuracy']) return model # 直接使用原始标签执行交叉验证 estimator = KerasClassifier(build_fn=build_model, epochs=10, batch_size=32, verbose=0) scores = cross_val_score(estimator, X_train, y_train, cv=5) print(f"交叉验证准确率: {scores.mean():.4f} ± {scores.std():.4f}")
错误根源说明
categorical_crossentropy要求标签是**形状为(样本数, 类别数)的独热编码张量,而MNIST原始标签是形状为(样本数,)或(样本数,1)**的一维整数数组,两者维度不匹配导致报错。上述两种方案分别从标签格式和损失函数适配的角度解决了这个问题,其中方案2更适合MNIST这类整数标签的分类任务,代码更简洁。
内容的提问来源于stack exchange,提问作者hahahahaha
相关产品推荐
相关产品推荐

