从数据可视化到模型优化:波士顿房价预测的完整技术旅程
从数据可视化到模型优化:波士顿房价预测的完整技术旅程
在数据科学领域,房价预测一直是一个经典而富有挑战性的问题。波士顿房价数据集作为机器学习入门的"Hello World"级案例,包含了506个样本和13个特征变量,为我们提供了一个绝佳的学习平台。本文将带您深入探索从数据清洗、可视化分析到模型优化的完整流程,揭示数据科学项目背后的技术决策逻辑。
1. 数据探索与初步分析
任何数据科学项目的第一步都是深入了解数据。波士顿房价数据集记录了1978年波士顿郊区506个区域的房价中位数(MEDV)及其13个影响因素,包括犯罪率(CRIM)、房间数(RM)、教师学生比例(PTRATIO)等。这些特征各具意义,理解它们与房价的关系至关重要。
使用Pandas加载数据后,我们首先进行基本统计:
import pandas as pd
import numpy as np
# 加载数据并添加列名
columns = ['CRIM','ZN','INDUS','CHAS','NOX','RM','AGE','DIS','RAD','TAX','PTRATIO','B','LSTAT','MEDV']
df = pd.read_csv('housing.data', delim_whitespace=True, header=None, names=columns)
# 查看数据概况
print(df.info())
print(df.describe())
数据清洗是确保模型质量的关键。幸运的是,波士顿数据集已经相当干净,没有缺失值。但我们仍需检查异常值:
# 检查异常值
plt.figure(figsize=(12,6))
df.boxplot()
plt.xticks(rotation=45)
plt.show()
数据质量检查要点:
- 检查各特征的数值范围是否合理
- 确认目标变量(MEDV)的分布情况
- 识别可能的异常值或输入错误
2. 多维特征可视化分析
数据可视化是理解特征与目标变量关系的强大工具。Matplotlib和Seaborn的组合可以创建丰富的可视化效果,帮助我们直观把握数据特性。
2.1 特征与房价的散点图矩阵
import matplotlib.pyplot as plt
import seaborn as sns
# 绘制特征与房价的散点图
plt.figure(figsize=(15,10))
for i, col in enumerate(columns[:-1]):
plt.subplot(3,5,i+1)
plt.scatter(df[col], df['MEDV'], alpha=0.5)
plt.title(col)
plt.tight_layout()
plt.show()
从散点图中可以初步观察到:
- RM(房间数)与MEDV呈现明显正相关
- LSTAT(低收入人群比例)与MEDV呈现负相关
- CHAS(查尔斯河虚拟变量)是二元特征,需特殊处理
2.2 相关性热力图
量化特征间相关性有助于后续的特征选择:
# 计算并绘制相关性热力图
corr_matrix = df.corr()
plt.figure(figsize=(12,8))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
plt.show()
关键观察:
- RM与MEDV相关性最高(约0.7)
- LSTAT与MEDV负相关性最强(约-0.74)
- 某些特征间存在高度相关性(如TAX与RAD),可能引发多重共线性问题
3. 特征工程与降维
原始特征并非都同等重要,适当的特征选择和转换可以提升模型性能并降低复杂度。
3.1 基于相关性的特征选择
# 选择与MEDV相关性绝对值大于0.5的特征
high_corr_features = corr_matrix['MEDV'][abs(corr_matrix['MEDV']) > 0.5].index.tolist()
high_corr_features.remove('MEDV')
print("高相关性特征:", high_corr_features)
3.2 LASSO回归特征选择
LASSO(Least Absolute Shrinkage and Selection Operator)回归通过L1正则化可以自动进行特征选择:
from sklearn.linear_model import LassoCV
from sklearn.preprocessing import StandardScaler
# 数据标准化
X = df.drop('MEDV', axis=1)
y = df['MEDV']
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# LASSO交叉验证选择最佳alpha
lasso_cv = LassoCV(cv=10).fit(X_scaled, y)
# 查看特征重要性
lasso_coef = pd.Series(lasso_cv.coef_, index=X.columns)
print("LASSO选择的特征权重:\n", lasso_coef[lasso_coef != 0])
特征选择结果对比:
| 方法 | 选择的主要特征 |
|---|---|
| 相关性分析 | RM, PTRATIO, LSTAT |
| LASSO回归 | RM, DIS, PTRATIO, LSTAT |
3.3 多项式特征扩展
线性模型假设特征与目标变量间存在线性关系,但现实往往更复杂。通过生成多项式特征可以捕捉非线性关系:
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression
# 创建多项式特征管道
poly_model = Pipeline([
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('scaler', StandardScaler()),
('linear', LinearRegression())
])
4. 模型构建与优化
有了精心准备的特征,我们可以构建和优化预测模型了。
4.1 基础线性回归模型
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(
X[['RM', 'LSTAT', 'PTRATIO', 'DIS']], y, test_size=0.2, random_state=42)
# 训练线性回归模型
lr = LinearRegression()
lr.fit(X_train, y_train)
# 评估模型
y_pred = lr.predict(X_test)
print(f"R²分数: {r2_score(y_test, y_pred):.3f}")
print(f"MSE: {mean_squared_error(y_test, y_pred):.3f}")
4.2 岭回归应对多重共线性
当特征间存在高度相关性时,岭回归(Ridge Regression)通过L2正则化可以稳定模型:
from sklearn.linear_model import RidgeCV
# 使用交叉验证选择最佳alpha
alphas = np.logspace(-3, 3, 100)
ridge_cv = RidgeCV(alphas=alphas, cv=10)
ridge_cv.fit(X_train, y_train)
print(f"最佳alpha值: {ridge_cv.alpha_:.3f}")
print(f"R²分数: {ridge_cv.score(X_test, y_test):.3f}")
4.3 模型性能对比
通过交叉验证比较不同模型的性能:
from sklearn.model_selection import cross_val_score
models = {
'Linear Regression': LinearRegression(),
'Ridge Regression': RidgeCV(alphas=alphas, cv=10),
'Polynomial (deg=2)': poly_model
}
for name, model in models.items():
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='r2')
print(f"{name}: 平均R²={scores.mean():.3f} (±{scores.std():.3f})")
模型性能对比结果:
| 模型 | 平均R²分数 | 标准差 |
|---|---|---|
| 线性回归 | 0.688 | 0.052 |
| 岭回归 | 0.692 | 0.048 |
| 二阶多项式 | 0.795 | 0.041 |
4.4 学习曲线分析
学习曲线帮助我们理解模型是否受益于更多数据:
from sklearn.model_selection import learning_curve
train_sizes, train_scores, test_scores = learning_curve(
poly_model, X_train, y_train, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10), scoring='r2')
plt.figure(figsize=(10,6))
plt.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', label='训练分数')
plt.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', label='验证分数')
plt.xlabel('训练样本数')
plt.ylabel('R²分数')
plt.legend()
plt.show()
学习曲线显示,随着训练样本增加,验证分数趋于稳定在0.8左右,表明当前模型架构下,增加更多数据带来的收益有限。
5. 实战陷阱与优化建议
在实际项目中,波士顿房价预测会遇到几个常见陷阱:
5.1 特征缩放的重要性
线性模型和正则化方法对特征尺度敏感。务必进行标准化:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
5.2 避免数据泄露
确保预处理步骤(如缩放)只在训练集上拟合,然后应用到测试集:
# 错误做法:在整个数据集上拟合缩放器
scaler.fit(X) # 会导致数据泄露
# 正确做法:只在训练集上拟合
scaler.fit(X_train)
5.3 模型解释性
线性模型的优势在于可解释性。我们可以分析特征权重:
lr.fit(X_train_scaled, y_train)
coef_df = pd.DataFrame({
'特征': X_train.columns,
'权重': lr.coef_
}).sort_values('权重', ascending=False)
print(coef_df)
特征权重分析:
- RM(房间数)对房价有最大正向影响
- LSTAT(低收入人群比例)对房价有显著负向影响
- DIS(就业中心距离)影响相对较小
5.4 高级优化方向
对于追求更高性能的数据科学家,可以考虑:
-
特征交互:探索特征间的交互作用
df['RM_LSTAT'] = df['RM'] * df['LSTAT'] -
非线性变换:对高度偏态的特征进行对数变换
df['LOG_CRIM'] = np.log(df['CRIM'] + 1) # 加1避免log(0) -
集成方法:尝试随机森林或梯度提升树
from sklearn.ensemble import RandomForestRegressor rf = RandomForestRegressor(n_estimators=100, random_state=42)
波士顿房价预测项目虽然经典,但包含了数据科学工作流的全部要素。通过这个案例,我们实践了从数据探索到模型优化的完整流程,掌握了处理现实世界数据的关键技术。记住,优秀的模型不仅在于算法选择,更在于对数据的深入理解和恰当的特征工程。
更多推荐
所有评论(0)