陈强-机器学习及Python应用-4.11 线性回归案例


前言

入门机器学习,记录学习日常,如有错误请多指正。
参考书目:机器学习及Python应用

一、数据处理

1.数据介绍

案例采用波士顿房价数据, 它包含了波士顿地区1970年房价的中位数与各种影响房价的因素。数据集共有506个数据点,每个数据点包含14个属性,其中13个是数值型特征,如城镇人均犯罪率、住宅用地比例等,以及一个目标变量即房价(MEDV)。

波士顿房价数据集的属性包括:
‌CRIM‌:城镇人均犯罪率
‌ZN‌:住宅用地超过25000平方英尺的比例
‌INDUS‌:城镇非零售商用土地的比例
‌CHAS‌:查尔斯河虚拟变量(如果边界是河流,则为1;否则为0)
‌NOX‌:一氧化氮浓度
‌RM‌:住宅平均房间数
‌AGE‌:1940年之前建成的自用房屋比例
‌DIS‌:到五个波士顿就业中心的加权距离
‌RAD‌:辐射性公路的接近指数
‌TAX‌:每10000美元的全值财产税率
‌PTRATIO‌:城镇师生比例
‌B‌:1000*(Bk - 0.63)^2,其中Bk为城镇中黑人的比例
‌LSTAT‌:人口中地位较低人群的百分比
‌MEDV‌:自有住房的中位数价值(单位:千美元)

2.导入模块和数据文件

导入所需模块

import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error,r2_score

由于sklearn中调用boston数据函数load_boston()已被移除,使用以下方式载入数据(代码繁琐是因为"http://lib.stat.cmu.edu/datasets/boston"中数据排列不整齐)。

data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep=r"\s+", skiprows=22, header=None)#skiprows=22表示跳过前22行数据
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])#自变量
'''
data是一个NumPy数组,是通过水平叠加(np.hstack)raw_df 中的数据而创建的。在这个操作中,选择了raw_df 中的
奇数行(raw_df.values[::2, :])和偶数行的前两列(raw_df.values[1::2, :2])并将它们水平叠加在一起.
[::2, :]表示从开始到结束步长为2;[1::2, :2]表示从1开始步长为2
'''
target = raw_df.values[1::2, 2]#引入Boston房价数据
boston = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :3]])
names = ["CRIM", "ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX", "PTRATIO", "B", "LSTAT", "MEDV"]
Boston=pd.DataFrame(boston,columns=names)#数据框化,数据与变量名匹配

3.数据概况

1)使用info()考察数据信息

print(Boston.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 14 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   CRIM     506 non-null    float64
 1   ZN       506 non-null    float64
 2   INDUS    506 non-null    float64
 3   CHAS     506 non-null    float64
 4   NOX      506 non-null    float64
 5   RM       506 non-null    float64
 6   AGE      506 non-null    float64
 7   DIS      506 non-null    float64
 8   RAD      506 non-null    float64
 9   TAX      506 non-null    float64
 10  PTRATIO  506 non-null    float64
 11  B        506 non-null    float64
 12  LSTAT    506 non-null    float64
 13  MEDV     506 non-null    float64
dtypes: float64(14)
memory usage: 55.5 KB

2)考察数据框前5个观测值:

print(Boston.head())
5行:       CRIM    ZN  INDUS  CHAS    NOX     RM   AGE     DIS  RAD    TAX  \
0  0.00632  18.0   2.31   0.0  0.538  6.575  65.2  4.0900  1.0  296.0   
1  0.02731   0.0   7.07   0.0  0.469  6.421  78.9  4.9671  2.0  242.0   
2  0.02729   0.0   7.07   0.0  0.469  7.185  61.1  4.9671  2.0  242.0   
3  0.03237   0.0   2.18   0.0  0.458  6.998  45.8  6.0622  3.0  222.0   
4  0.06905   0.0   2.18   0.0  0.458  7.147  54.2  6.0622  3.0  222.0   

   PTRATIO       B  LSTAT  MEDV  
0     15.3  396.90   4.98  24.0  
1     17.8  396.90   9.14  21.6  
2     17.8  392.83   4.03  34.7  
3     18.7  394.63   2.94  33.4  
4     18.7  396.90   5.33  36.2 

3)考察此数据库统计特征:

print(Boston.describe())#统计特征
             CRIM          ZN       INDUS        CHAS         NOX          RM  \
count  506.000000  506.000000  506.000000  506.000000  506.000000  506.000000   
mean     3.613524   11.363636   11.136779    0.069170    0.554695    6.284634   
std      8.601545   23.322453    6.860353    0.253994    0.115878    0.702617   
min      0.006320    0.000000    0.460000    0.000000    0.385000    3.561000   
25%      0.082045    0.000000    5.190000    0.000000    0.449000    5.885500   
50%      0.256510    0.000000    9.690000    0.000000    0.538000    6.208500   
75%      3.677083   12.500000   18.100000    0.000000    0.624000    6.623500   
max     88.976200  100.000000   27.740000    1.000000    0.871000    8.780000   

              AGE         DIS         RAD         TAX     PTRATIO           B  \
count  506.000000  506.000000  506.000000  506.000000  506.000000  506.000000   
mean    68.574901    3.795043    9.549407  408.237154   18.455534  356.674032   
std     28.148861    2.105710    8.707259  168.537116    2.164946   91.294864   
min      2.900000    1.129600    1.000000  187.000000   12.600000    0.320000   
25%     45.025000    2.100175    4.000000  279.000000   17.400000  375.377500   
50%     77.500000    3.207450    5.000000  330.000000   19.050000  391.440000   
75%     94.075000    5.188425   24.000000  666.000000   20.200000  396.225000   
max    100.000000   12.126500   24.000000  711.000000   22.000000  396.900000   

            LSTAT        MEDV  
count  506.000000  506.000000  
mean    12.653063   22.532806  
std      7.141062    9.197104  
min      1.730000    5.000000  
25%      6.950000   17.025000  
50%     11.360000   21.200000  
75%     16.955000   25.000000  
max     37.970000   50.000000  

二. 线性回归

1.进行一元回归

1)将房价中位数MEDV对房间数RM进行一元回归:

model=smf.ols('MEDV~RM',data=Boston)#一元回归
'''
此命令生成了smf.ols类的一个实例model,并通过公式'MEDV~RM',指定把数据框Boston的MEDV对RM进行回归
'''
results1=model.fit()#使用fit()方法进行估计
print(results1.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                   MEDV   R-squared:                       0.484
Model:                            OLS   Adj. R-squared:                  0.483
Method:                 Least Squares   F-statistic:                     471.8
Date:                Wed, 21 Aug 2024   Prob (F-statistic):           2.49e-74
Time:                        17:00:03   Log-Likelihood:                -1673.1
No. Observations:                 506   AIC:                             3350.
Df Residuals:                     504   BIC:                             3359.
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept    -34.6706      2.650    -13.084      0.000     -39.877     -29.465
RM             9.1021      0.419     21.722      0.000       8.279       9.925
==============================================================================
Omnibus:                      102.585   Durbin-Watson:                   0.684
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              612.449
Skew:                           0.726   Prob(JB):                    1.02e-133
Kurtosis:                       8.190   Cond. No.                         58.4
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

2.多元回归

1)将房价中位数MEDV对RM和AGE进行回归:

results2=smf.ols('MEDV~RM+AGE',data=Boston).fit()#二元回归
print(results2.summary().tables[1])#仅展示中间表格
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept    -25.2774      2.857     -8.848      0.000     -30.890     -19.665
RM             8.4016      0.412     20.388      0.000       7.592       9.211
AGE           -0.0728      0.010     -7.075      0.000      -0.093      -0.053
==============================================================================

2)将房价中位数MEDV对RM、AGE以及两者交叉项进行回归

results3=smf.ols('MEDV~RM+AGE+RM:AGE',data=Boston).fit()#主效应+交互效应,RM:AGE表示两者相乘
'''
'MEDV~RM+AGE+RM:AGE'可简写为'MEDV~RM*AGE',所得结果相同
'''
print(results3.params)#只展示回归系数
Intercept   -59.592862
RM           13.747467
AGE           0.381529
RM:AGE       -0.071407
dtype: float64

3)将房价中位数MEDV对RM、AGE、交叉项以及两者平方项进行回归

results4=smf.ols('MEDV~RM*AGE+I(RM**2)+I(AGE**2)',data=Boston).fit()
#加入平方项,I()具有保护作用,使得Python将I(RM**2)视为变量RM^2
print(results4.params)
Intercept      67.847165
RM            -24.039817
AGE             0.274171
RM:AGE         -0.034858
I(RM ** 2)      2.706836
I(AGE ** 2)    -0.001169
dtype: float64

4)将房价中位数MEDV对所以特征变量进行回归

all_columns='CRIM+ZN+INDUS+CHAS+NOX+RM+AGE+DIS+RAD+TAX+PTRATIO+B+LSTAT'
formula='MEDV~'+all_columns#定义回归公式
results5=smf.ols(formula,data=Boston).fit()#对所有特征变量进行回归
print(results5.summary().tables[1])

```python
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     36.4595      5.103      7.144      0.000      26.432      46.487
CRIM          -0.1080      0.033     -3.287      0.001      -0.173      -0.043
ZN             0.0464      0.014      3.382      0.001       0.019       0.073
INDUS          0.0206      0.061      0.334      0.738      -0.100       0.141
CHAS           2.6867      0.862      3.118      0.002       0.994       4.380
NOX          -17.7666      3.820     -4.651      0.000     -25.272     -10.262
RM             3.8099      0.418      9.116      0.000       2.989       4.631
AGE            0.0007      0.013      0.052      0.958      -0.025       0.027
DIS           -1.4756      0.199     -7.398      0.000      -1.867      -1.084
RAD            0.3060      0.066      4.613      0.000       0.176       0.436
TAX           -0.0123      0.004     -3.280      0.001      -0.020      -0.005
PTRATIO       -0.9527      0.131     -7.283      0.000      -1.210      -0.696
B              0.0093      0.003      3.467      0.001       0.004       0.015
LSTAT         -0.5248      0.051    -10.347      0.000      -0.624      -0.425
==============================================================================

5)由于上图中AGE高度不显著,去掉变量AGE再次进行回归

formula_noAGE=formula+'-AGE'
print(formula_noAGE)
results6=smf.ols(formula_noAGE,data=Boston).fit()#对出AGE外所有特征变量进行回归
print(results6.params)
除AGE外所有特征变量: MEDV~CRIM+ZN+INDUS+CHAS+NOX+RM+AGE+DIS+RAD+TAX+PTRATIO+B+LSTAT-AGE
回归系数: Intercept    36.436927
CRIM         -0.108006
ZN            0.046334
INDUS         0.020562
CHAS          2.689026
NOX         -17.713540
RM            3.814394
DIS          -1.478612
RAD           0.305786
TAX          -0.012329
PTRATIO      -0.952211
B             0.009321
LSTAT        -0.523852
dtype: float64

三. 模型评估的再抽样方法

1.验证集法

使用验证集法时,现将数据一分为二,其中大部分作为训练集(约70%),其余作为验证集或保留集。在估计模型是,仅使用训练集,然后在验证集进行样本外预测,并计算验证集误差,以此估计测试误差。
1)进行样本分类

x_train,x_test,y_train,y_test=train_test_split(data,target,test_size=0.3,random_state=0)
#将样本分为训练集和验证集,test_size=0.3表示测试集占30%
print(x_train.shape,x_test.shape,y_train.shape,y_test.shape)#形状

数组形状如下:

(354, 13) (152, 13) (354,) (152,)

2)使用sklearn模块LinearRegression类进行OLS回归

model=LinearRegression()#生成实例
model.fit(x_train,y_train)#使用fit()估计
print(model.coef_)#回归系数
回归系数: [-1.21310401e-01  4.44664254e-02  1.13416945e-02  2.51124642e+00
 -1.62312529e+01  3.85906801e+00 -9.98516565e-03 -1.50026956e+00
  2.42143466e-01 -1.10716124e-02 -1.01775264e+00  6.81446545e-03
 -4.86738066e-01]

3)评估

print('拟合优度:',model.score(x_test,y_test))#模型在测试集中的拟合优度,R^2
pred=model.predict(x_test)#测试集预测结果
print('均方误差:',mean_squared_error(y_test,pred))#均方误差
拟合优度: 0.6733825506400186
均方误差: 27.195965766883276

2.K折交叉验证

通过将数据集分成K个互不重叠的子集,每次使用K-1个子集作为训练集,剩下的1个子集作为测试集,重复K次,最终取平均误差作为模型的性能指标。
1)导入交叉验证所需模块

from sklearn.model_selection import KFold
from sklearn.model_selection import LeaveOneOut
from sklearn.model_selection import RepeatedKFold
from sklearn.model_selection import cross_val_score

2)进行10折交叉验证

X=data
y=target
model=LinearRegression()
kfold=KFold(n_splits=10,shuffle=True,random_state=1)
#n_splits=10表示将全样本分为10折,shuffle=True表示随机分组

3)评估
以拟合优度作为得分标准

scores=cross_val_score(model,X,y,cv=kfold)
#cv=kfold指定交叉验证的随机分组为kfold
print('拟合优度:',scores)
print('拟合优度平均值',scores.mean())
print('拟合优度标准差',scores.std())
拟合优度: [0.77863866 0.76632537 0.8729179  0.44002779 0.84715141 0.71692423
 0.72093063 0.59299064 0.69816152 0.75603868]
拟合优度平均值 0.719010682018947
拟合优度标准差 0.11892348692223256

以均方误差作为得分标准

scores_mse=-cross_val_score(model,X,y,cv=kfold,scoring='neg_mean_squared_error')
print('均方误差',scores_mse)
print('均方误差均值',scores_mse.mean())
均方误差 [20.54427466 24.47650033  9.49619045 48.63290854 12.11906454 18.14673907
 17.53359386 38.67822303 34.22829546 13.73556966]
均方误差均值 23.759135960073205

3.将10折交叉验证重复进行10次

1)使用RepeatedKFold类,将10折交叉验证重复进行10次

rkfold=RepeatedKFold(n_splits=10,n_repeats=10,random_state=1)#将10折交叉验证重复10次
scores_mse2=-cross_val_score(model,X,y,cv=rkfold,scoring='neg_mean_squared_error')
print(scores_mse2.shape)
print(scores_mse2.mean())
(100,)#表明scores_mse2对应100个子样本的均方误差
23.962356681713366#均方误差均值

2)画出100个子样本均方误差的直方图与核密度图

sns.displot(pd.DataFrame(scores_mse2))
plt.xlabel('MSE')
plt.title('10-fold CV Repeated 10 Times')
plt.tight_layout()#用于自动调整图形的布局,确保元素如坐标轴标签、刻度和标题不会重叠‌
plt.show()

在这里插入图片描述

4.留一交叉验证

将样本数据等分为n折(n为样本容量),每折只包含一个样本点。由于每次均使用n-1个数据去预测留出的一个数据,故总共需估计n次,估计结果不再具备随机性。

loo=LeaveOneOut()#创建LeaveOneOut()实例,LeaveOneOut()等价于KFold(n_splits=n)
scores_mse4=-cross_val_score(model,X,y,cv=loo,scoring='neg_mean_squared_error')
print(scores_mse4.mean())
均方误差均值: 23.725745519476146
机器学习Python应用》是由陈强撰写的一本针对机器学习Python编程的教程。本书主要介绍了机器学习的基本理论和算法,并通过Python编程语言实现了这些算法。 首先,本书从机器学习的基本概念开始讲解,介绍了监督学习、无监督学习和强化学习等不同的学习任务。然后,详细介绍了机器学习中常用的算法,例如线性回归、逻辑回归、支持向量机、决策树、随机森林和深度学习等。每个算法的原理和应用场景都有详细的说明,并通过代码实例演示了如何使用Python实现这些算法。 此外,本书还介绍了机器学习的评估方法和调参技巧。作者详细解释了模型评估的常用指标,例如准确率、精确率、召回率和F1得分等,并介绍了交叉验证和网格搜索等调参方法。这些内容帮助读者更好地评估和优化机器学习模型。 值得一提的是,本书的代码示例都是使用Python编写的。Python是一种简单易学的编程语言,并且有许多优秀的机器学习库,如Scikit-learn、TensorFlow和Keras等,可以方便地实现机器学习算法。通过本书的学习,读者不仅可以掌握机器学习的基本理论和算法,还可以学会使用Python编程语言来应用这些算法解决实际问题。 总而言之,《机器学习Python应用》是一本专门介绍机器学习Python编程的教程。通过学习本书,读者可以全面了解机器学习的基本概念和算法,并且可以通过Python编程语言实现和应用这些算法。无论是初学者还是有一定编程基础的人士,都可以通过本书掌握机器学习Python编程的基本技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值