如何解决Keras训练时‘Unsupported object type float’报错?
解决Keras模型训练时的"Failed to convert a NumPy array to a Tensor"错误
问题描述
尝试构建用均值填充缺失值的二分类模型,训练时出现错误:Failed to convert a NumPy array to a Tensor (Unsupported object type float),原始代码如下:
from keras.models import Sequential, load_model from keras.layers import Dense,Dropout from sklearn.model_selection import train_test_split import numpy as np import pandas as pd import matplotlib.pyplot as plt import random targetURL='../content/drive/MyDrive/1-2/caffeine.csv' df = pd.read_csv(targetURL) df=pd.get_dummies(df, columns=['sex']) df.isnull().sum().sort_values(ascending=False).head(4) df=df.fillna(df.mean(numeric_only=True)) standardization_df = (df - df.mean(numeric_only=True,axis=0)) / df.std(numeric_only=True,axis=0) x=standardization_df.iloc[:,1:14] y=df.iloc[:,14] y=pd.get_dummies(y) x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, shuffle=True,random_state=3) model = Sequential() model.add(Dense(24, input_dim=13, activation='relu')) model.add(Dense(10, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(1, activation='sigmoid')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) score=model.evaluate(x_test, y_test) history=model.fit(x_train, y_train, epochs=10, batch_size=10, verbose=0, validation_split=0.2) hist_df=pd.df(history.history) y_vloss=hist_df['val_loss'] y_loss=hist_df['loss'] x_len=np.arange(len(y_loss)) plt.plot(x_len, y_vloss, "o", c="red", makersize=2, label='Testset_loss') plt.plot(x_len, y_loss, "o", c="blue", makersize=2, label='Trainset_loss') plt.legend(loc='upper right') plt.xlabel('epoch') plt.ylabel('loss') plt.show()
数据集包含sex(female/male)和target(yes/no)两个文本列,均为二分类取值。
错误原因及修改方案
1. 目标变量与模型输出层、损失函数不匹配
- 问题:
target是二分类,用pd.get_dummies()得到的是2列one-hot编码,但模型最后一层是Dense(1, activation='sigmoid'),对应二分类的二元交叉熵,而非多分类的categorical_crossentropy。 - 修改:
- 将
target转换为0/1的标签编码,而非one-hot; - 损失函数改为
binary_crossentropy。
- 将
2. 错误标准化分类变量
- 问题:
standardization_df包含了sex的one-hot列(0/1),分类变量不需要标准化,否则会破坏其语义。 - 修改:仅对数值列做标准化,再合并one-hot的
sex列到特征集。
3. 数据类型与格式问题
- 问题:Pandas DataFrame转换为Tensor时可能因类型不兼容报错,需确保数据为
float32类型;同时pd.df()是错误的API,应为pd.DataFrame()。
4. 评估时机错误
- 问题:
model.evaluate()在模型训练前执行,此时模型未训练,评估无意义且可能引发异常,应放在训练之后。
5. 绘图参数拼写错误
- 问题:
makersize应为markersize,拼写错误会导致绘图失败。
修正后的完整代码
from keras.models import Sequential, load_model from keras.layers import Dense, Dropout from sklearn.model_selection import train_test_split import numpy as np import pandas as pd import matplotlib.pyplot as plt targetURL='../content/drive/MyDrive/1-2/caffeine.csv' df = pd.read_csv(targetURL) # 处理sex列的one-hot编码 df = pd.get_dummies(df, columns=['sex']) # 均值填充缺失值 df = df.fillna(df.mean(numeric_only=True)) # 分离数值列和分类列(sex的one-hot) numeric_cols = df.select_dtypes(include=[np.number]).columns.drop('target') # 假设目标列名为target,可根据实际调整 categorical_cols = [col for col in df.columns if 'sex_' in col] # 仅对数值列做标准化 standardized_numeric = (df[numeric_cols] - df[numeric_cols].mean()) / df[numeric_cols].std() # 合并标准化后的数值列和分类列作为特征x x = pd.concat([standardized_numeric, df[categorical_cols]], axis=1) # 处理目标变量:将yes/no转换为1/0 y = df['target'].map({'yes': 1, 'no': 0}).astype('float32') # 划分数据集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, shuffle=True, random_state=3) # 转换为numpy数组并指定类型,避免Tensor转换错误 x_train = x_train.values.astype('float32') x_test = x_test.values.astype('float32') y_train = y_train.values.astype('float32') y_test = y_test.values.astype('float32') # 构建模型:二分类用sigmoid输出+binary_crossentropy model = Sequential() model.add(Dense(24, input_dim=x_train.shape[1], activation='relu')) model.add(Dense(10, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 先训练模型 history = model.fit(x_train, y_train, epochs=10, batch_size=10, verbose=1, validation_split=0.2) # 训练后再评估测试集 score = model.evaluate(x_test, y_test) print(f'Test loss: {score[0]}, Test accuracy: {score[1]}') # 提取训练历史 hist_df = pd.DataFrame(history.history) # 绘制损失曲线 y_vloss = hist_df['val_loss'] y_loss = hist_df['loss'] x_len = np.arange(len(y_loss)) plt.plot(x_len, y_vloss, "o", c="red", markersize=2, label='Validation Loss') plt.plot(x_len, y_loss, "o", c="blue", markersize=2, label='Training Loss') plt.legend(loc='upper right') plt.xlabel('Epoch') plt.ylabel('Loss') plt.show()
关键说明
- 若目标列名不是
target,需根据实际数据集列名修改df['target']处的代码; - 用
map()转换目标变量比one-hot更适合单输出的二分类模型; - 明确区分数值列和分类列的预处理逻辑,避免标准化破坏分类变量的意义;
- 强制转换数据类型为
float32,确保与Keras Tensor的兼容性。
内容的提问来源于stack exchange,提问作者lino
相关产品推荐
相关产品推荐

