房价预测模型中测试集与训练集R²值差异显著的原因探究
核心原因分析
1. 训练/测试集数据分布不一致
你的代码采用默认随机拆分数据集,如果房屋核心特征(如城市分布、房屋面积区间、房价档位)在两个集合中的占比差异过大,模型在训练集学到的规律无法适配测试集。比如:
- 某高房价城市的样本集中在测试集,训练集仅含少量该城市数据,模型未掌握该区域定价逻辑
- 训练集以小户型为主,测试集却有大量大户型房源,模型泛化能力失效
排查方法:用直方图、箱线图对比训练/测试集的特征分布,比如分别绘制x_train与x_test中log_sqft_lot、各城市dummy变量的占比,以及y_train/y_test的log_price分布,看是否存在明显偏移。
2. 高维特征引发过拟合
你用pd.get_dummies处理城市特征,若数据集包含大量城市,会生成大量dummy列。线性回归在高维空间下容易过度拟合训练集的噪声,导致训练R²虚高,但测试集表现骤降。
解决方向:改用带正则化的模型(如Ridge或Lasso),通过惩罚系数控制模型复杂度,验证泛化效果。
3. 关键特征被遗漏
代码直接丢弃了date、statezip等核心特征:
date包含交易时间信息,不同年份/月份的房价趋势差异明显statezip是比城市更精细的地理标识,同一城市不同邮编的房价可能天差地别
这些特征缺失会导致模型无法捕捉真实定价逻辑,训练集可能靠拟合噪声获得高R²,但测试集无法复用这些无效模式。
4. 异常值干扰模型拟合
虽然过滤了price=0的样本,但未处理其他特征的极端值(如超大面积的sqft_lot)。训练集中的异常值会让模型偏向拟合噪声点,在无异常的测试集上表现拉胯。
排查方法:查看训练集log_sqft_lot和log_price的箱线图,识别并移除超出3σ的极端值后重新训练。
5. 预处理环节的潜在风险
代码在拆分数据集前就完成了get_dummies和log变换:log变换不会引入数据泄露,但如果测试集中存在训练集未覆盖的城市,会导致特征维度不匹配。不过从代码的drop_first设置来看,若所有城市在训练集都有覆盖,该问题暂时不存在,仍需确认数据集城市分布。
具体优化建议
- 改用分层拆分:在
train_test_split中加入stratify参数,保证训练/测试集特征分布一致:x_train, x_test, y_train, y_test = train_test_split(x,y, test_size=0.2, random_state=42, stratify=data_new['city']) - 恢复并加工关键特征:从
date提取年份、月份,保留statezip并转为dummy特征,补充到模型中 - 尝试正则化模型:替换线性回归为Ridge模型:
from sklearn.linear_model import Ridge lm = Ridge(alpha=1.0) lm.fit(x_train_scaled,y_train) - 移除极端异常值:
# 示例:移除log_price的5%/95%分位外的极端值 q1 = data2['log_price'].quantile(0.05) q3 = data2['log_price'].quantile(0.95) data_filtered = data2[(data2['log_price'] >= q1) & (data2['log_price'] <= q3)]
内容的提问来源于stack exchange,提问作者Abir Kar

