上一节我们讲了线性回归的理论知识,那么怎么用呢?这节我们直接进入实战环节。我们将使用sklearn中加州房价数据集,训练一个线性回归模型,预测房子的中位数价格。
- • 输入特征: 收入中位数、人口数等8个特征维度;
一、数据集
我们使用scikit-learn库中的加州房价数据集。
数据规模
一共20640条样本,每条样本有8个特征和1个目标值。
特征说明
目标变量
MedHouseVal:房价中位数(单位:十万美元)
二、代码实战
2.1 环境准备
# numpy 数学计算
import numpy as np
# pandas 处理表格数据
import pandas as pd
# 画图
import matplotlib.pyplot as plt
# 获取加州房价数据集
from sklearn.datasets import fetch_california_housing
# 用来把数据分成训练集和测试集
from sklearn.model_selection import train_test_split
# 线性回归模型
from sklearn.linear_model import LinearRegression
# 模型打分指标
from sklearn.metrics import mean_squared_error, r2_score
2.2 加载数据集
data = fetch_california_housing()
X, y = data.data, data.target # y 单位:千美元(k$)
# 查看特征名
print("特征:", data.feature_names)
print("数据形状:", X.shape) # (20640, 8)
输出结果:
特征: ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
数据形状: (20640, 8)
2.3 划分数据集
划分训练集和测试集,占比分别为80%和20%。
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
2.4 训练模型
model = LinearRegression()
model.fit(X_train, y_train)
2.5 预测结果
y_pred_test = model.predict(X_test)
2.6 评估模型
test_r2 = r2_score(y_test, y_pred_test)
test_mse = mean_squared_error(y_test, y_pred_test)
print(f"测试集 R²: {test_r2:.4f}")
print(f"测试集 MSE: {test_mse:.4f} (单位: (k$)^2)")
结果如下:
测试集 R²: 0.5758
测试集 MSE: 0.5559 (单位: (k$)^2)
- • R方:越接近1越好,代表模型解释了数据中多少波动;
- • MSE: 越小越好,代表预测值与真实值的平均差距;
- • 线性回归用8个特征,解释了房价57.6%的变化。
2.7 特征系数
特征系数也可以看作特征的重要性,在sklearn中,可以使用自带属性查看:
print("前3个特征名字及权重:")
for name, coef in zip(data.feature_names, model.coef_[:3]):
print(f" {name}: {coef:.4f}")
print(f"偏置项 (Intercept): {model.intercept_:.4f}")
结果如下:
前3个特征名字及权重:
MedInc: 0.4487
HouseAge: 0.0097
AveRooms: -0.1233
偏置项 (Intercept): -37.0233
2.8 可视化
# 加载字体,图像中中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(10, 6))
plt.scatter(test_y, y_pred, color='blue')
# 横轴真实价格,纵轴预测价格
plt.plot([test_y.min(), test_y.max()], [test_y.min(), test_y.max()], 'r--', lw=3)
plt.xlabel('真实房价')
plt.ylabel('预测房价')
plt.title('线性回归:加州房价预测效果图')
plt.grid(True, linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
结果如下:
如果点都聚集在红色的虚线附近,说明预测非常准。
三、模型改进
在训练模型前,还有很多特征工程工作可以做,以此来提高模型准确率。比如构造新的特征、去除异常值、归一化等,这里我们先不讲述,直接使用原始特征,只使用多项式和正则化对模型进行改进。
3.1 使用多项式特征
当特征值与目标值不是简单的线性关系时,可以构造多项式特征来表示输入特征与输出之间的非线性关系。在sklearn中,提供了构造函数,可以将原始特征转换为多项式特征,然后再使用线性回归进行训练。
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2, include_bias=False, interaction_only=True)
X_train_poly = poly.fit_transform(X_train)
X_test_poly = poly.transform(X_test)
model_poly = LinearRegression()
model_poly.fit(X_train_poly, y_train)
r2_poly = r2_score(y_test, model_poly.predict(X_test_poly))
print(f"多项式模型 R²: {r2_poly:.4f}")
结果如下:
3.2 L1&L2正则化
from sklearn.linear_model import Lasso, Ridge
# L1正则化
lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)
r2_lasso = r2_score(y_test, lasso.predict(X_test))
# L2正则化
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
r2_ridge = r2_score(y_test, ridge.predict(X_test))
print(f"L1 正则化 R²: {r2_lasso:.4f}")
print(f"L2 正则化 R²: {r2_ridge:.4f}")
结果如下:
L1 正则化 R²: 0.5845
L2 正则化 R²: 0.5759
3.3 结果对比
从中可以看出,使用多项式特征结果有一定提升,但是正则化结果并不明显。
四、完整代码
# 加载所需库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.linear_model import Lasso, Ridge
# 加载字体,图像中中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 获取数据
data = fetch_california_housing()
X, y = data.data, data.target
# 划分训练集、测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 训练模型
model = LinearRegression()
model.fit(X_train, y_train)
# 测试集预测
y_pred_test = model.predict(X_test)
# 评估模型
test_r2 = r2_score(y_test, y_pred_test)
test_mse = mean_squared_error(y_test, y_pred_test)
print(f"测试集 R²: {test_r2:.4f}")
print(f"测试集 MSE: {test_mse:.4f} (单位: (k$)^2)")
# 画图
plt.figure(figsize=(10, 6))
plt.scatter(test_y, y_pred, color='blue')
# 横轴真实价格,纵轴预测价格
plt.plot([test_y.min(), test_y.max()], [test_y.min(), test_y.max()], 'r--', lw=3)
plt.xlabel('真实房价')
plt.ylabel('预测房价')
plt.title('线性回归:加州房价预测效果图')
plt.grid(True, linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
# 多项式
poly = PolynomialFeatures(degree=2, include_bias=False, interaction_only=True)
X_train_poly = poly.fit_transform(X_train)
X_test_poly = poly.transform(X_test)
model_poly = LinearRegression()
model_poly.fit(X_train_poly, y_train)
r2_poly = r2_score(y_test, model_poly.predict(X_test_poly))
print(f"多项式模型 R²: {r2_poly:.4f}")
# L1正则化
lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)
r2_lasso = r2_score(y_test, lasso.predict(X_test))
# L2正则化
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
r2_ridge = r2_score(y_test, ridge.predict(X_test))
print(f"L1 正则化 R²: {r2_lasso:.4f}")
print(f"L2 正则化 R²: {r2_ridge:.4f}")
总结
通过上述代码,我们完成了一个除了特征工程以外的机器学习工作流, =0.62,那么这个结果到底算好还是不好?这个我们将在下一篇文章中进行详细讲解。
说明:文章封面配图使用AI生成。