房价预测实战:从数据洞察到模型部署的完整线性回归指南
最近在整理过去几个数据分析项目时,我发现很多刚开始接触机器学习的朋友,虽然能照着教程跑通代码,但一到自己动手处理真实数据就卡壳。特别是像房价预测这种经典案例,网上教程大多只教“怎么调包”,很少深入讲清楚数据背后的逻辑、可视化怎么真正帮到模型理解,以及那些看似简单的步骤里藏着哪些容易踩的坑。今天,我就以美国房价数据集为例,抛开那些千篇一律的模板,带你走一遍我实际工作中处理回归问题的完整思路。我们会用到 scikit-learn,但重点绝不是机械地调用 LinearRegression().fit(),而是如何像数据分析师一样思考:从数据第一次加载到最终模型评估,每一个环节的可视化与解读如何驱动我们做出更好的决策。
这篇文章适合已经了解 Python 和 pandas 基础,希望将机器学习技能从“会跑代码”提升到“理解并优化模型”的技术人员。我们将不局限于训练一个模型,而是通过一系列可视化技巧,深入观察特征与目标的关系、模型拟合的过程以及预测结果的可靠性,最终构建一个可解释、可评估的预测流程。
1. 数据初探:超越 data.head() 的深度观察
拿到一份新的数据集,比如 usa_housing_price.csv,很多人的第一步是 data.head() 和 data.info()。这没错,但信息量有限。在房价预测的场景里,我们关心的不仅是列名和数据类型,更是每个特征的实际分布、它们与房价的潜在关系,以及是否存在可能影响模型的数据质量问题。
首先,我会习惯性地计算一些关键统计量,并用可视化快速形成整体印象。除了常见的均值、标准差,我特别关注分位数和偏度。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置绘图风格,让图表更美观
plt.style.use('seaborn-v0_8-darkgrid')
sns.set_palette("husl")
# 加载数据
data = pd.read_csv('./data/usa_housing_price.csv')
# 基础统计摘要 - 重点关注分布范围与异常
stats_summary = data.describe(percentiles=[.01, .05, .25, .5, .75, .95, .99])
print(stats_summary)
运行这段代码后,你得到的不仅是最小值、最大值,还能通过1%和99%分位数快速判断是否存在极端离群值。例如,如果“房屋面积”的99%分位数远小于最大值,说明可能存在需要处理的异常大户型数据。
接下来,我更喜欢用分布直方图与核密度估计(KDE)的组合图来观察每个特征。单纯看数字不如一张图来得直观。
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
features = data.columns.drop('Price') # 假设'Price'是目标变量
axes = axes.ravel()
for idx, col in enumerate(features):
ax = axes[idx]
# 绘制直方图与KDE曲线
sns.histplot(data[col], kde=True, ax=ax, bins=30, stat='density', linewidth=0)
ax.set_title(f'{col} Distribution', fontsize=12)
ax.set_xlabel('')
# 在图中标注中位数和均值线
median_val = data[col].median()
mean_val = data[col].mean()
ax.axvline(median_val, color='red', linestyle='--', alpha=0.7, label=f'Median: {median_val:.1f}')
ax.axvline(mean_val, color='green', linestyle='-.', alpha=0.7, label=f'Mean: {mean_val:.1f}')
ax.legend(fontsize=9)
# 隐藏多余的子图
for idx in range(len(features), len(axes)):
axes[idx].set_visible(False)
plt.tight_layout()
plt.show()
提示:观察均值线(绿色点划线)和中位数线(红色虚线)的相对位置。如果两者差距明显,说明数据分布存在偏斜(Skewness),这可能会影响线性回归的假设。例如,收入数据常呈现右偏分布(均值 > 中位数),在建模前可能需要进行对数变换。
通过这组图,你能立刻发现哪些特征分布接近正态(如“平均房龄”),哪些有明显偏斜或双峰分布。这种初步的视觉诊断,为后续的特征工程(如数据变换、处理异常值)提供了明确的方向。
2. 特征与目标关系的可视化艺术
探索特征与房价(目标变量)的关系是核心环节。散点图是标准选择,但如何让散点图传递更多信息?我通常从两个维度升级基础散点图:引入趋势线和添加边际分布。
首先,我们绘制每个特征与房价的散点图,并拟合一条局部加权回归散点平滑法(LOWESS)趋势线。与简单的线性趋势线相比,LOWESS能更灵活地揭示数据中可能存在的非线性关系。
import statsmodels.api as sm
fig, axes = plt.subplots(2, 3, figsize=(16, 10))
features = ['Avg. Area Income', 'Avg. Area House Age', 'Avg. Area Number of Rooms',
'Area Population', 'size']
axes = axes.ravel()
for idx, feature in enumerate(features):
ax = axes[idx]
x = data[feature]
y = data['Price']
# 绘制散点,加入透明度和大小变化,避免点重叠
scatter = ax.scatter(x, y, alpha=0.5, s=10, c='steelblue', edgecolors='white', linewidth=0.5)
# 计算并绘制LOWESS平滑曲线
lowess = sm.nonparametric.lowess(y, x, frac=0.3) # frac控制平滑程度
ax.plot(lowess[:, 0], lowess[:, 1], color='crimson', linewidth=2.5, label='LOWESS Trend')
# 可选:绘制线性回归线作为对比
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(x.values.reshape(-1, 1), y)
y_pred_lr = lr.predict(x.values.reshape(-1,

&spm=1001.2101.3001.5002&articleId=150087614&d=1&t=3&u=4bb5a8f429af4fca9ae2f97f56b2f1ee)
1万+

被折叠的 条评论
为什么被折叠?



