TensorFlow 2分类模型训练报错:输入输出形状不匹配及predict调用问题
解决方案
核心错误分析
你的问题主要来自三个方面:数据格式不匹配Keras的要求、模型层配置错误,以及预测时的输入维度问题。
1. 修正数据格式
Keras要求训练数据的输入x是二维张量(形状为(样本数量, 特征数量)),标签y是二维张量(形状为(样本数量, 类别数量))。你之前把每个样本做成单独的一维张量,导致Keras误判样本数量,引发 cardinality 错误。
修正后的数据准备代码:
import tensorflow as tf print("TensorFlow version:", tf.__version__) names = sorted({"Jack", "John", "Peter", "X"}) sizes = [ [0.0, 0.5, 0.6, 0.7, 0.8, 0.3], # Jack [0.2, 0.6, 0.7, 0.8, 0.5, 0.2], # John [0.0, 0.1, 0.1, 0.4, 0.8, 0.9], # Peter [0.3, 0.9, 0.2, 0.1, 0.0, 0.8] # X ] # 将列表转换为二维张量,形状分别为(4,6)和(4,4) x = tf.convert_to_tensor(sizes, dtype=tf.float32) y = tf.convert_to_tensor([ [1.0, 0.0, 0.0, 0.0], # Jack的one-hot标签 [0.0, 1.0, 0.0, 0.0], # John的one-hot标签 [0.0, 0.0, 1.0, 0.0], # Peter的one-hot标签 [0.0, 0.0, 0.0, 1.0] # X的one-hot标签 ], dtype=tf.float32)
2. 修正模型配置
- 第一个
Dense层必须指定input_shape,告诉模型单个样本的特征维度(这里是6)。 - 输出层需要用
softmax激活函数,将输出转换为符合概率分布的结果(所有类别概率和为1),匹配CategoricalCrossentropy损失函数的要求。
修正后的模型定义与编译:
model = tf.keras.models.Sequential([ # 第一个Dense层指定输入形状,对应单个样本的6个特征 tf.keras.layers.Dense(name="hidden", units=6, activation='relu', input_shape=(6,)), # 输出层用softmax激活,输出4个类别的概率 tf.keras.layers.Dense(name="outputs", units=len(names), activation='softmax') ]) model.compile( optimizer='adam', loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy'] )
3. 训练与预测
现在可以正常训练模型:
# 训练模型,样本量小,增加epochs让模型收敛 model.fit(x, y, epochs=200)
预测时,模型要求输入是批量维度的张量(即使是单个样本,也要包裹成二维数组):
# 单个样本预测,注意外层加[],变成形状(1,6)的输入 test_sample = [0.0, 0.5, 0.6, 0.7, 0.8, 0.3] pred_probs = model.predict([test_sample]) # 输出每个类别的概率 for name, prob in zip(names, pred_probs[0]): print(f"{name}: {prob:.4f}") # 获取概率最高的人物 pred_name = names[tf.argmax(pred_probs, axis=1)[0].numpy()] print(f"\n预测结果:{pred_name}")
关键说明
- 数据格式:堆叠成二维张量后,Keras能正确识别出4个样本,每个样本有6个特征、对应4个类别标签,解决了cardinality不匹配的问题。
- 输出激活:
softmax是分类任务的标准激活函数,确保输出符合概率分布,而relu无法满足这一要求。 - 预测输入:模型默认处理批量数据,因此单个样本需要增加一个批量维度(从
(6,)变成(1,6))。
内容的提问来源于stack exchange,提问作者Rolf
相关产品推荐
相关产品推荐

