You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不同训练测试拆分比例下LinearRegression预测差异大的原因及解决

LinearRegression预测结果随训练测试拆分比例异常的原因及解决方法

问题场景

你在使用LinearRegression训练线性模型时,发现了一个奇怪的现象:当设置test_size=0.2时,测试集的预测结果里出现了极端大的异常值(比如那个4.17353113e+07),但训练集的预测值都很正常;而把测试集比例调到0.4之后,训练和测试的预测结果就都恢复正常了。

初始拆分(test_size=0.2)的代码与输出

x_train,x_test,y_train,true_p=train_test_split(train,y,random_state=121,test_size=0.2,shuffle=True)
lreg=LinearRegression()
lreg.fit(x_train,y_train)
train_pred=lreg.predict(x_train)
test_pred=lreg.predict(x_test)
  • 训练集预测结果:
    array([12.37512481, 11.67234874, 11.82821202, ..., 12.61139596, 12.13886881, 12.42435563])
    
  • 测试集预测结果(存在异常值):
    array([ 1.21885520e+01, 1.13462088e+01, 1.14144208e+01, 1.22832932e+01, 1.29980626e+01, 1.17641183e+01, 1.20982465e+01, 1.15846156e+01, 1.17403904e+01, 4.17353113e+07, 1.27941840e+01, 1.21739628e+01, ..., 1.22022858e+01, 1.15779229e+01, 1.24931376e+01, 1.26387188e+01, 1.18341585e+01, 1.18411881e+01, 1.21475986e+01, 1.25104774e+01])
    

调整拆分比例(test_size=0.4)的代码与输出

x_train,x_test,y_train,true_p=train_test_split(train,y,random_state=121,test_size=0.4,shuffle=True)
lreg=LinearRegression()
lreg.fit(x_train,y_train)
train_pred=lreg.predict(x_train)
test_pred=lreg.predict(x_test)
  • 训练集预测结果:
    array([11.95505983, 12.66847164, 11.81978843, 12.82992812, 12.44707462, 11.78809995, 11.92753084, 12.6082893 , 12.22644843, 11.93325658, 12.2449481 ,..., 11.69256008, 11.67984786, 12.54313682, 12.30652695])
    
  • 测试集预测结果(无异常值):
    array([12.22133867, 11.18863973, 11.46923967, 12.26340761, 12.99240451, 11.77865948, 12.04321231, 11.44137667, 11.71213919, 11.44206212, ..., 12.15412777, 12.39184805, 10.96310233, 12.06243916, 12.11383494, 12.28327695, 11.19989021, 12.61439939, 12.22474378])
    

原因分析

咱们直接点说,这个问题的核心是你的数据里存在离群点(outlier),而拆分比例的变化刚好改变了这个离群点的分配位置:

  • 当test_size=0.2时,这个极端样本被分到了测试集里。线性回归是用最小二乘法拟合的,对离群点特别敏感——训练模型时根本没见过这种极端数据,所以用它预测测试集里的这个离群点时,就会输出极端大的值。
  • 当test_size=0.4时,这个离群点被分到了训练集里。此时模型会被这个点“拉偏”,但测试集里没有极端样本,所以预测结果看起来都正常。

你设置了random_state=121,这让拆分结果固定了,所以两种比例下的差异完全是这个离群点的位置导致的。

解决方法(针对test_size=0.2的场景)

1. 检测并处理离群点

首先得找到这个离群点:

  • 你可以用箱线图查看特征和目标变量的分布,找出超出四分位间距(IQR)3倍以上的样本;
  • 或者计算每个特征的Z分数,标记Z分数绝对值大于3的样本。

处理方式分两种:

  • 如果是数据录入错误导致的离群点,直接删掉就行;
  • 如果是真实存在的极端样本,推荐用稳健回归模型,比如RANSACRegressor或者HuberRegressor,它们对离群点的鲁棒性比普通线性回归强很多。

示例代码(用RANSAC):

from sklearn.linear_model import RANSACRegressor

# 拆分数据保持test_size=0.2
x_train,x_test,y_train,true_p=train_test_split(train,y,random_state=121,test_size=0.2,shuffle=True)
# RANSAC会自动筛选出符合模型的内点,忽略离群点
ransac_reg = RANSACRegressor(LinearRegression(), random_state=121)
ransac_reg.fit(x_train, y_train)
# 重新预测
train_pred = ransac_reg.predict(x_train)
test_pred = ransac_reg.predict(x_test)

2. 对特征做标准化处理

线性回归对特征的尺度很敏感,如果某个特征的数值范围特别大,也可能导致预测异常。用StandardScaler把所有特征缩放到均值为0、方差为1的范围,能缓解这个问题:

from sklearn.preprocessing import StandardScaler

# 先标准化所有特征
scaler = StandardScaler()
train_scaled = scaler.fit_transform(train)

# 再拆分数据
x_train,x_test,y_train,true_p=train_test_split(train_scaled,y,random_state=121,test_size=0.2,shuffle=True)
lreg=LinearRegression()
lreg.fit(x_train,y_train)
train_pred=lreg.predict(x_train)
test_pred=lreg.predict(x_test)

3. 用交叉验证替代单次拆分

单次拆分很容易因为样本分配的偶然性出现问题,用交叉验证能更全面地评估模型性能,也能避免这种“刚好抽到离群点到测试集”的情况:

from sklearn.model_selection import cross_val_predict
from sklearn.preprocessing import StandardScaler

# 先标准化特征
scaler = StandardScaler()
train_scaled = scaler.fit_transform(train)

lreg = LinearRegression()
# 用5折交叉验证得到所有样本的预测结果
cv_predictions = cross_val_predict(lreg, train_scaled, y, cv=5)

内容的提问来源于stack exchange,提问作者Aneesh Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:27:57