如何解决SVR训练时出现的Input X contains NaN错误?
解决SVR训练时的NaN缺失值错误
问题场景
使用SVR进行回归预测时,执行以下代码触发ValueError:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.svm import SVR from sklearn.model_selection import GridSearchCV from sklearn.model_selection import KFold from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn.metrics import mean_absolute_percentage_error from sklearn.metrics import mean_absolute_error import csv from math import sqrt from scipy import stats from sklearn.preprocessing import StandardScaler from sklearn.metrics import r2_score filepath = '/content/drive/MyDrive/TESIS/DATA/' pilihankolom = 35 X = pd.read_csv(filepath+'Data_Radiomic.csv').to_numpy() Y = pd.read_csv(filepath+'Data_Dosiomic.csv', usecols=[pilihankolom]) print(X.shape) Y_label = str(Y.columns) Y = Y.to_numpy() model=SVR(kernel='rbf', C=10, epsilon=0.01) kf = KFold(n_splits=4) X_training, X_testing, Y_training, Y_testing = train_test_split(X, Y, test_size=0.2, random_state=0) print(X_training.shape, X_testing.shape) prediction = [] mse_set = [] for train_index, test_index in kf.split(X_training): print(train_index, test_index) X_train, X_test = X_training[train_index], X_training[test_index] Y_train, Y_test = Y_training[train_index], Y_training[test_index] model.fit(X_train, Y_train) # 此处触发错误 Y_pred = model.predict(X_test) mse_set.append(mean_squared_error(Y_test, Y_pred)) prediction.extend(Y_pred)
错误信息
ValueError: 输入X包含NaN。SVR原生不接受以NaN编码的缺失值。对于监督学习,可考虑使用sklearn.ensemble.HistGradientBoostingClassifier和Regressor,它们原生支持NaN缺失值;也可对数据预处理,如用imputer转换器或删除含缺失值样本。
解决方案
SVR属于不支持缺失值的模型,必须对数据进行预处理,或更换模型,以下是三种可行方案:
1. 删除含缺失值的样本或特征
如果缺失值占比极低,可直接删除对应样本或特征:
# 删除含NaN的行(样本) X = pd.read_csv(filepath+'Data_Radiomic.csv').dropna(axis=0).to_numpy() # 或删除含NaN的列(特征) X = pd.read_csv(filepath+'Data_Radiomic.csv').dropna(axis=1).to_numpy()
注意:删除样本会减少数据集规模,删除特征可能丢失重要信息,需根据数据情况判断。
2. 填充缺失值(推荐)
使用sklearn的填充器对NaN进行插值,常用策略包括均值、中位数、众数,或基于邻近样本的KNN填充:
示例:均值填充+标准化
from sklearn.impute import SimpleImputer # 读取数据保留DataFrame格式,方便预处理 X_df = pd.read_csv(filepath+'Data_Radiomic.csv') Y_df = pd.read_csv(filepath+'Data_Dosiomic.csv', usecols=[pilihankolom]) # 用均值填充NaN imputer = SimpleImputer(strategy='mean') X_imputed = imputer.fit_transform(X_df) # 分割数据集 X_training, X_testing, Y_training, Y_testing = train_test_split(X_imputed, Y_df.to_numpy(), test_size=0.2, random_state=0) # 标准化(需在填充之后执行) scaler = StandardScaler() X_training_scaled = scaler.fit_transform(X_training) X_testing_scaled = scaler.transform(X_testing) # 训练模型(注意SVR要求y为一维数组,用ravel()转换) model=SVR(kernel='rbf', C=10, epsilon=0.01) kf = KFold(n_splits=4) prediction = [] mse_set = [] for train_index, test_index in kf.split(X_training_scaled): X_train, X_test = X_training_scaled[train_index], X_training_scaled[test_index] Y_train, Y_test = Y_training[train_index], Y_training[test_index] model.fit(X_train, Y_train.ravel()) Y_pred = model.predict(X_test) mse_set.append(mean_squared_error(Y_test, Y_pred)) prediction.extend(Y_pred)
可选填充策略:
strategy='median':中位数填充,适合含异常值的数据strategy='most_frequent':众数填充,适合分类特征KNNImputer(n_neighbors=5):基于K近邻样本的均值填充,适合缺失值分布有规律的场景
3. 更换支持原生NaN的模型
如果不想预处理数据,可使用HistGradientBoostingRegressor,它原生支持含NaN的输入:
from sklearn.ensemble import HistGradientBoostingRegressor # 替换SVR为HistGradientBoostingRegressor model = HistGradientBoostingRegressor(random_state=0) # 后续训练流程无需修改(直接用含NaN的X) X_training, X_testing, Y_training, Y_testing = train_test_split(X, Y, test_size=0.2, random_state=0) kf = KFold(n_splits=4) prediction = [] mse_set = [] for train_index, test_index in kf.split(X_training): X_train, X_test = X_training[train_index], X_training[test_index] Y_train, Y_test = Y_training[train_index], Y_training[test_index] model.fit(X_train, Y_train.ravel()) Y_pred = model.predict(X_test) mse_set.append(mean_squared_error(Y_test, Y_pred)) prediction.extend(Y_pred)
内容的提问来源于stack exchange,提问作者Reyhan Fikri
相关产品推荐
相关产品推荐

