引言:挑战介绍

在完成了泰坦尼克号生还者预测的分类任务后,我们将转向另一个经典的机器学习问题:房价预测。这是一个典型的**回归(Regression)**问题,因为我们的目标是预测一个连续的数值——房屋的销售价格(SalePrice),而不是一个离散的类别。

我们将使用著名的埃姆斯(Ames)住房数据集,该数据集包含了爱荷华州埃姆斯市房屋的近 80 个特征,如房屋面积、建造年份、车库大小、整体质量等。这个项目的复杂性在于其大量的特征和普遍存在的缺失值,这为我们提供了一个绝佳的实践特征工程和高级数据清洗技术的机会。

步骤一:针对回归问题的探索性数据分析 (EDA)

EDA 的目标和方法在回归问题中略有不同,我们尤其关注目标变量的分布以及数值特征与目标变量之间的关系

加载与初步检查

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据
train_df = pd.read_csv('train.csv') # 假设使用 Ames 数据集
test_df = pd.read_csv('test.csv')

# 查看数据维度和信息
print(train_df.shape)
train_df.info()

分析目标变量 SalePrice

这是回归分析中最重要的一步。许多线性回归模型假设误差呈正态分布,而一个严重偏斜的目标变量可能会违反这一假设,从而影响模型性能。

# 绘制 SalePrice 的分布图
sns.histplot(train_df['SalePrice'], kde=True)
plt.title('Distribution of SalePrice')
plt.show()

# 计算偏度 (skewness)
print(f"Skewness: {train_df['SalePrice'].skew()}")

我们会发现 SalePrice 呈明显的右偏态(正偏态)。为了缓解这种偏斜,通常会对其进行对数变换 (log transformation)。这是一种在回归问题中非常标准和有效的预处理手段。

# 对 SalePrice 进行对数变换
train_df['SalePrice'] = np.log1p(train_df['SalePrice'])

# 再次绘制分布图,观察变换效果
sns.histplot(train_df['SalePrice'], kde=True)
plt.title('Log-Transformed Distribution of SalePrice')
plt.show()

变换后的分布会更接近正态分布,这有助于线性模型的表现。

分析特征与目标变量的关系

  • 相关性热力图: 快速识别哪些数值特征与 SalePrice 相关性最强。

    # 计算相关性矩阵
    corrmat = train_df.corr(numeric_only=True)
    plt.figure(figsize=(12, 9))
    sns.heatmap(corrmat, vmax=.8, square=True)
    plt.show()
    

    我们会发现 OverallQual (整体质量), GrLivArea (地上生活面积), GarageCars (车库容量) 等特征与 SalePrice 有很强的正相关。

  • 散点图: 深入观察最相关特征与 SalePrice 的关系。

    sns.scatterplot(data=train_df, x='GrLivArea', y='SalePrice')
    plt.title('GrLivArea vs. SalePrice')
    plt.show()
    

    散点图可以帮助我们识别线性和非线性关系,以及潜在的异常值。

步骤二:特征工程与数据清洗

Ames 数据集以其复杂的缺失值和多样的特征类型而闻名,是练习特征工程的绝佳材料。

  • 处理缺失值:

    • 对于像 PoolQC (泳池质量), Alley (小巷类型) 等,NaN 实际上代表**“没有该设施”**,因此可以用 'None' (对于分类特征) 或 0 (对于数值特征) 来填充。
    • 对于 LotFrontage (临街宽度) 这类数值特征,可以用该社区(Neighborhood)的临街宽度中位数来填充,这比全局中位数更精确。
  • 创建新特征:

    • 可以组合现有特征来创造更有预测能力的变量,例如 TotalSF = 地下室面积 + 一楼面积 + 二楼面积
    • 将数值特征转换为分类特征,例如将 YrSold (销售年份) 和 MoSold (销售月份) 视为类别,因为它们可能反映了季节性或市场周期性。
  • 处理分类特征:

    • 对于大量的分类特征,使用 pd.get_dummies() 进行独热编码是标准做法。

步骤三:模型构建与评估

训练回归模型

我们将使用一个简单的线性模型,如 Ridge 回归,它在线性回归的基础上增加了 L2 正则化项,有助于防止过拟合。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error

# 假设 X_processed 和 y_log_transformed 是处理好的特征和对数变换后的目标变量
# X_train, X_test, y_train, y_test = train_test_split(...) # 此处省略详细的数据预处理代码

# 实例化并训练模型
ridge_model = Ridge(alpha=10) # alpha 是正则化强度
ridge_model.fit(X_train, y_train)

# 进行预测
y_pred_log = ridge_model.predict(X_test)

# 重要:将预测结果从对数尺度转换回原始尺度
y_pred = np.expm1(y_pred_log)
y_test_orig = np.expm1(y_test)

评估回归模型

分类模型的准确率指标不适用于回归问题。我们需要使用专门的回归评估指标。

指标 公式 解读 关键特性
MAE (平均绝对误差) $ \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| $ 预测值与真实值之差的绝对值的平均值。 直观,单位与目标变量相同,但对大误差不敏感。
MSE (均方误差) $ \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 $ 预测值与真实值之差的平方的均值。 对大误差的惩罚更重。单位是目标变量的平方,不易解释。
RMSE (均方根误差) $ \sqrt{MSE} $ MSE的平方根,单位与目标变量相同。 最常用的回归指标。惩罚大误差,但结果易于解释。
(决定系数) $ 1 - \frac{\sum(y_i - \hat{y}_i)^2}{\sum(y_i - \bar{y})^2} $ 模型可以解释的目标变量方差的比例。 值在 0 到 1 之间,越高越好。与尺度无关,便于跨模型比较。
# 计算 RMSE
rmse = np.sqrt(mean_squared_error(y_test_orig, y_pred))
print(f"Root Mean Squared Error: {rmse}")

RMSE 的值告诉我们,模型的预测平均偏离真实房价多少美元。这个值越低,模型性能越好。

总结与解读

通过房价预测项目,我们深入实践了回归问题的完整流程。我们学会了如何分析和预处理连续型目标变量(对数变换),如何通过相关性分析和可视化来指导特征工程,以及如何使用 RMSE 等指标来科学地评估回归模型的性能。

这个项目展示了特征工程的巨大威力。一个简单的线性模型,在经过精心的特征工程和数据预处理后,也能达到相当不错的预测效果。下一步的提升方向可能包括使用更复杂的模型(如 GradientBoostingRegressorXGBoost)和更高级的特征选择技术。

至此,本系列的核心教程部分已经完成。在最后一部分,我们将介绍一个获取数据的常用技能——网络爬虫,为你的数据科学项目提供更多数据来源。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐