波士顿房价是一个非常经典的多元线性回归入门案例数据集。波士顿房价预测数据集包含了可能会影响房价的十三个因素,并给出了实际的房价(单位为万美元)
波士顿房价数据集数据集下载地址:https://www.kaggle.com/datasets/altavish/boston-housing-dataset?resource=download
而我们这里直接通过pandas包获取,因为这个数据集是pandas包中自带的数据集
数据处理
首先导入需要的python包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt #绘图
from sklearn import datasets #数据集
from sklearn.linear_model import LinearRegression #线性回归模型
接着导入所需要的波士顿房价数据,boston.data
是所有的自变量,也就是影响因素。boston.target
为实际房价,单位为万美元
# 导入数据
boston = datasets.load_boston()
# 将房价信息转成dataFrame格式
df_boston_house_data = pd.DataFrame(boston.data, columns=boston.feature_names)
df_boston_house_data['PRICE'] = boston.target
#boston.target和'PRICE'列即为房价
输出所有的变量名(在JYnotebook中可以直接打印,pycharm等中需要加上print)
#对应房价的影响因素,对应标题列
boston.feature_names#输出结果
array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'])
可以看出有十三个变量,每个变量的解释与类型如下:
属变量名 | 解释 | 类型 |
---|---|---|
CRIM | 该镇的人均犯罪率 | 连续值 |
ZN | 占地面积超过25,000平方呎的住宅用地比例 | 连续值 |
INDUS | 非零售商业用地比例 | 连续值 |
CHAS | 是否邻近 Charles River(查尔斯河) | 离散值,1=邻近;0=不邻近 |
NOX | 一氧化氮浓度 | 连续值 |
RM | 每栋房屋的平均客房数 | 连续值 |
AGE | 1940年之前建成的自用单位比例 | 连续值 |
DIS | 到波士顿5个就业中心的加权距离 | 连续值 |
RAD | 到径向公路的可达性指数 | 连续值 |
TAX | 全值财产税率 | 连续值 |
PTRATIO | 学生与教师的比例 | 连续值 |
B | 黑人占比 ,处理后的占比数据 | 连续值 |
LSTAT | 低收入人群占比 | 连续值 |
MEDV | 同类房屋价格的中位数 | 连续值 |
看一下数据集的数量情况,输出结果表示这个数据集共有506行,14列(即之前说过的13个影响因素与房价列)
df_boston_house_data.shape# 输出结果(506, 14)
#打印前五列
df_boston_house_data.head(5)#查看整体的数据情况
df_boston_house_data.describe()
从结果看这一个数据集非常干净,没有缺失值,所以无需进行其他处理,可以直接建模
对于所有的数据,我们需要划分训练集与测试集。其中训练集用来训练模型,得到模型的相关参数,而测试集用来测试得到的模型的准确性。我们选取80%的数据作为训练数据,剩下的20%作为测试数据
为了随机选取数据集中的数据,首先新建一个包含506个数据的序列,然后使用shuffle函数来将序列的所有元素随机排序,然后根据打乱的序号来选取前80%的数据,这样就做到了随机选取80%数据进行训练
#拆分训练集和测试集,取80%为训练集
index=np.arange(506)
#np.random.shuffle 洗牌函数,将数据顺序打乱
np.random.shuffle(index)
index[:10]#输出前10列,可以看到顺序已经被打乱了
之后根据随机后index切分原有的数据,得到训练数据集和测试数据集
train_index=index[:405]
test_index=index[405:]
#训练数据集
X_train = boston.data[train_index]
Y_train = boston.target[train_index]
display(X_train.shape,Y_train.shape)
两个训练数据集分别为405行13列和405行1列。
#测试数据集
X_test = boston.data[test_index]
Y_test = boston.target[test_index]
display(X_test.shape,Y_test.shape)
两个测试数据集分别为101行13列和101行1列。
建模
使用sklearn中的LinearRegression函数建模,这个函数的相关参数和解释如下:
lr = sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)
返回一个线性回归模型,损失函数为误差均方函数。
参数详解:
- fit_intercept:默认True,是否计算模型的截距,为False时,则数据中心化处理
- normalize:默认False,是否中心化,或者使用sklearn.preprocessing.StandardScaler()
- copy_X:默认True,否则X会被改写
- n_jobs:默认为1,表示使用CPU的个数。当-1时,代表使用全部CPU
调用方法:
- coef_:训练后的输入端模型系数,如果label有两个,即y值有两列。那么是一个2D的array
- intercept_:截距
- predict(x):预测数据
- score:评估
#将后面输出各参数的形式改为小数,比较好看一点
np.set_printoptions(suppress = True)model=LinearRegression(fit_intercept=True)
model.fit(X_train,Y_train)#输出所有自变量的参数值
display(model.coef_,model.intercept_)#输出得到所有自变量的参数值为
array([ -0.11773312, 0.04681254, -0.04002632, 3.68539789,-17.97706949, 3.21418931, 0.01994593, -1.44502271,0.33251652, -0.01158733, -0.89816759, 0.00669943,-0.60311895])
#当然由于是随机选取了80%的数据进行训练,所以如果你实际复现的代码得到的参数是和我得出来得参数有差别的
建模完成后我们可以使用predict()
方法来根据得出的模型和测试集变量得数据得到预测的房价结果
#根据得出的模型,输入测试集的数据,并与测试集的结果比较
y_predict=model.predict(X_test).round(2)
#输出前30个预测结果
y_predict[:30]
为了更方便的查看对应的结果,将实际值和预测值放到一起比较一下:
# 绘制预测值与真实值图# 规定字体,避免乱码import matplotlib.pyplot as plt
plt.figure(figsize=(14, 5))# 调整输出的图片大小
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(Y_test, color="r", label="实际价格") # 颜色表示
plt.plot(y_predict, color=(0, 0, 0), label="预测价格")
plt.xlabel("测试序号") # x轴命名表示
plt.ylabel("价格") # y轴命名表示
plt.title("实际值与预测值折线图")
plt.legend() # 增加图例
plt.show() # 显示图片
从显示的图片中可以看出模型的结果似乎还不错。
模型评估
最后就是定量的对模型进行研究,与我们之前说的一元线性回归类似,对于多元线性回归模型好坏的判断指标一般有:
R 2 R^2 R2评价指标
sklearn在实现线性回归时默认采用 R 2 R^2 R2指标, R 2 R^2 R2越大表示模型越好,其定义如下:
R 2 = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ‾ ) 2 ∈ [ 0 , 1 ] R^2=1-\frac{\sum_{i=1}^n(y_i-\hat{y}_i)^2}{\sum_{i=1}^n(y_i-\overline{y})^2}\in[0,1] R2=1−∑i=1n(yi−y)2∑i=1n(yi−y^i)2∈[0,1]
其中 y ‾ \overline{y} y表示真实值的平均值。
回到我们得到的模型中,得到的R方结果为0.74,结果还是不错的
#R方模型评估,越接近1证明模型越好
model.score(X_test,Y_test)
均方误差MAE
其实就是最小二乘法中的损失函数,计算方程预测值与实际值的距离,结果越小表示结果越好
M A E = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ , ∈ [ 0 , + ∞ ) \large{MAE=\frac{1}{n} \sum_{i=1}^n |y_i - \hat{y}_i|},\;\;\in[0,+\infty) MAE=n1i=1∑n∣yi−y^i∣,∈[0,+∞)
#最小二乘法损失函数评估,越小模型结果越好
from sklearn.metrics import mean_squared_error
mean_squared_error(Y_test,y_predict)
这个模型得出的结果为 22.6448
波士顿房价预测是一个比较简单的建模,因为这一个数据集非常干净,没有缺失或者需要处理的数据,同时建模的变量也是筛选好的,而在实际的建模中我们会遇到非常多的变量,需要进行数据清洗和特征工程,并不断的验证优化才能得到好用的参数和模型,这些在实际的建模中会是更重要的步骤。对于初学者来说我们可以从这一个案例中了解建模的相关基础代码和流程,后续会接着介绍其他更复杂的案例。
参考文章:
https://muxiner.github.io/ml-boston-housing/
https://www.heywhale.com/mw/project/5eee291fcaa99b002d6d9dfd