Tensorflow/Keras模型拟合数据时的形状与类型错误求助
问题解决思路与代码修正
核心问题拆解
你遇到的两个错误分别对应目标变量格式不匹配和特征变量类型不兼容两个核心问题,逐一解决即可:
1. 目标变量(House)的格式问题
第一个报错Shapes (None, 1) and (None, 4) are incompatible,原因是:
- 模型输出层设为4个神经元(对应4类House)并使用
softmax激活,搭配categorical_crossentropy损失时,要求目标变量y必须是one-hot编码格式(形状为(样本数, 4)),但你传入的y_train/y_test是原始字符串类别,形状为(样本数, 1),两者维度不匹配。
两种修正方案:
方案A:将y转换为one-hot编码
from tensorflow.keras.utils import to_categorical from sklearn.preprocessing import LabelEncoder # 先把字符串类别转成整数编码 le = LabelEncoder() y_train_encoded = le.fit_transform(y_train) y_test_encoded = le.transform(y_test) # 再转成one-hot编码 y_train_onehot = to_categorical(y_train_encoded) y_test_onehot = to_categorical(y_test_encoded)
之后拟合模型时传入y_train_onehot和y_test_onehot即可。
方案B:改用sparse_categorical_crossentropy损失
如果不想做one-hot编码,可直接使用针对整数标签的损失函数,只需先把字符串标签转成整数:
from sklearn.preprocessing import LabelEncoder # 目标变量转整数编码 le_y = LabelEncoder() y_train = le_y.fit_transform(y_train) y_test = le_y.transform(y_test) # 编译模型时替换损失函数 model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
2. 特征变量(Q1-Q7)的类型问题
第二个报错Cast string to float is not supported,原因是特征X_train/X_test都是字符串类型,而Keras全连接层(Dense)只能处理数值型输入,无法直接解析字符串。
根据你的数据特征(每个Q的取值是离散文本类别),可采用以下编码方式:
方案A:OneHot编码(适合类别数较少的特征)
from sklearn.preprocessing import OneHotEncoder # 对所有Q特征做one-hot编码 encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore') X_train_encoded = encoder.fit_transform(X_train) X_test_encoded = encoder.transform(X_test) # 注意修改模型input_shape为编码后的特征维度 model = keras.Sequential([ layers.Dense(64, activation='relu', input_shape=[X_train_encoded.shape[1]]), layers.Dense(32, activation='relu'), layers.Dense(16, activation='relu'), layers.Dense(4, activation='softmax') ])
方案B:Label编码(适合有序类别,或作为Embedding层前置处理)
from sklearn.preprocessing import LabelEncoder # 对每个特征列单独做Label编码 for col in X_train.columns: le = LabelEncoder() X_train[col] = le.fit_transform(X_train[col]) X_test[col] = le.transform(X_test[col]) # 转成numpy数组(可选,Keras也支持DataFrame输入) X_train = X_train.values X_test = X_test.values
此时模型input_shape=[7]可保留,因为每个特征已转为整数数值。
完整修正代码示例
以「sparse_categorical_crossentropy + Label编码特征」方案为例:
from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from tensorflow import keras from tensorflow.keras import layers import pandas as pd # 加载数据集(假设df已准备完成) X = df[['Q1', 'Q2', 'Q3', 'Q4', 'Q5', 'Q6', 'Q7']] y = df['House'] # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 处理特征:Label编码所有字符串特征 for col in X_train.columns: le = LabelEncoder() X_train[col] = le.fit_transform(X_train[col]) X_test[col] = le.transform(X_test[col]) # 处理目标变量:Label编码字符串类别为整数 le_y = LabelEncoder() y_train = le_y.fit_transform(y_train) y_test = le_y.transform(y_test) # 构建模型 model = keras.Sequential([ layers.Dense(64, activation='relu', input_shape=[7]), layers.Dense(32, activation='relu'), layers.Dense(16, activation='relu'), layers.Dense(4, activation='softmax') ]) # 编译模型 model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 拟合模型 model.fit( X_train, y_train, epochs=50, validation_data=(X_test, y_test))
内容的提问来源于stack exchange,提问作者facepet
相关产品推荐
相关产品推荐

