本文是学习开源项目‘ensemble learning’之后的总结。平台使用jupyter notebook。
项目链接:https://github.com/datawhalechina/ensemble-learning
章节学习视频链接:https://www.bilibili.com/video/BV1Mb4y1o7ck?p=1 前10p
机器学习的任务可分为有监督学习和无监督学习,典型的有监督学习如回归和分类,本节仅介绍回归和分类相关的问题。
# 引入相关科学计算包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use("ggplot")
import seaborn as sns
使用sklearn构建完整的机器学习项目流程
一般来说,一个完整的机器学习项目分为以下步骤:
- 明确项目任务:回归/分类
- 收集数据集并选择合适的特征。
- 选择度量模型性能的指标。
- 选择具体的模型并进行训练以优化模型。
- 评估模型的性能并调参。
用sklearn构建完整的回归项目
收集数据集并选择合适的特征
选用scikit-learn自带的数据集:Boston房价数据集,以避免在处理数据上花费较大精力,达到快速上手sklearn掌握相关操作的效果。
from sklearn import datasets
boston = datasets.load_boston() # 返回一个类似于字典的类
X = boston.data # 特征矩阵
y = boston.target # 因变量
features = boston.feature_names # 特征名称,之后作为列名
boston_data = pd.DataFrame(X, columns=features)
boston_data["Price"] = y # 将因变量加入数据表中
boston_data.head()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | Price | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 | 21.6 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2.0 | 242.0 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3.0 | 222.0 | 18.7 | 396.90 | 5.33 | 36.2 |
各个特征的相关解释:
CRIM:各城镇的人均犯罪率 DIS:到波士顿五个就业中心的加权距离 ZN:规划地段超过25,000平方英尺的住宅用地比例 RAD:放射状公路的可达性指数 INDUS:城镇非零售商业用地比例 TAX:全部价值的房产税率(每1万美元) CHAS:是否在查尔斯河边(=1是) PTRATIO:按城镇分配的学生与教师比例 NOX:一氧化氮浓度(/千万分之一) B:1000(Bk - 0.63)^2其中Bk是每个城镇的黑人比例 RM:每个住宅的平均房间数 LSTAT:较低地位人口 AGE:1940年以前建造的自住房屋的比例 Price:房价
选择度量模型性能的指标
-
MSE均方误差: MSE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ( y i − y ^ i ) 2 \text{MSE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum\limits_{i=0}^{n_\text{samples} - 1} (y_i - \hat{y}_i)^2 MSE(y,y^)=nsamples1i=0∑nsamples−1(yi−y^i)2,均方误差是一个与平方误差(或损失)期望值相应的的风险指标。
-
MAE平均绝对误差: MAE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ∣ y i − y ^ i ∣ \text{MAE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum\limits_{i=0}^{n_{\text{samples}}-1} \left| y_i - \hat{y}_i \right| MAE(y,y^)=nsamples1i=0∑nsamples−1∣yi−y^i∣,平均绝对误差是一个与绝对误差损失(或L1范数损失)期望值的相应的风险指标。
-
R 2 R^2 R2决定系数: R 2 ( y , y ^ ) = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ˉ ) 2 R^2(y, \hat{y}) = 1 - \frac{\sum\limits_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum\limits_{i=1}^{n} (y_i - \bar{y})^2} R2(y,y^)=1−i=1∑n(yi−yˉ)2i=1∑n(yi−y^i)2,
-
解释方差得分: e x p l a i n e d _ v a r i a n c e ( y , y ^ ) = 1 − V a r { y − y ^ } V a r { y } explained\_variance(y, \hat{y}) = 1 - \frac{Var\{ y - \hat{y}\}}{Var\{y\}} explained_variance(y,y^)=1−Var{y}Var{y−y^},解释方差得分最好的是1,值越低越差。
以上, y i ^ \hat{y_{i}} yi^ 是第 i i i 个样本的预测值, y i y_{i} yi 是相应的真实值; y ^ \hat{y} y^ 是估计的 target output, y y y 是相应的(correct) target output。
各指标含义及代码实现具体可参见:Regression metrics
选择具体的模型并进行训练
线性回归模型:
回归的具体概念可了解一下高尔顿关于父子身高的研究,并理解一下”向均值回归“的含义即可。
假设影响因变量(dependent variable)
Y
Y
Y 的自变量(independent variable)有
p
p
p 个:
X
1
,
X
2
,
⋅
⋅
⋅
,
X
p
X_1,X_2, · · · ,X_p
X1,X2,⋅⋅⋅,Xp , 并且设定它们之间有如下线性关系:
Y
=
β
0
+
β
1
X
1
+
β
2
X
2
+
⋅
⋅
⋅
+
β
p
X
p
+
e
,
Y = β_0 + β_1X_1 + β_2X_2 + · · · + β_pX_p + e,
Y=β0+β1X1+β2X2+⋅⋅⋅+βpXp+e,
其中
e
e
e 是误差项,
β
0
,
β
1
,
⋯
,
β
p
β_0, β_1, \cdots , β_p
β0,β1,⋯,βp 是待估计的未知参数。自变量也称为预测变量(predictor variables)或控制变量(control variables)。
假设我们获得了响应变量 Y Y Y 和预测变量 X 1 , X 2 , ⋅ ⋅ ⋅ , X p X_1,X_2, · · · ,X_p X1,X2,⋅⋅⋅,Xp 的 n n n 组观测值 ( x i 1 , ⋯ , x i p , y i ) , i = 1 , 2 , ⋯ , n (x_{i1}, \cdots , x_{ip}, y_i),i = 1, 2, \cdots , n (xi1,⋯,xip,yi),i=1,2,⋯,n,它们满足
y i = β 0 + β 1 x i 1 + β 2 x i 2 + ⋯ + β p x i p + e i . y_i = β_0 + β_1x_{i1} + β_2x_{i2} + \cdots + β_px_{ip} + e_i. yi=β0+β1xi1+β2xi2+⋯+βpxip+ei.
用矩阵形式表示为:
[ y 1 y 2 ⋮ y i ] = [ 1 x 11 x 12 ⋯ x 1 p 1 x 21 x 22 ⋯ x 2 p ⋮ ⋮ ⋮ ⋮ ⋮ 1 x n 1 x n 2 ⋯ x n p ] [ β 1 β 2 ⋮ β i ] + [ e 1 e 2 ⋮ e i ] \left[\begin{array}{ccc} y_1\\y_2\\ \vdots \\y_i \end{array}\right] = \left[\begin{array}{c} 1 & x_{11} & x_{12} & \cdots & x_{1p}\\1 & x_{21} & x_{22} & \cdots & x_{2p}\\ \vdots & \vdots & \vdots &\vdots &\vdots\\ 1 & x_{n1} & x_{n2} & \cdots & x_{np} \end{array}\right] \left[\begin{array}{c} β_1\\β_2\\ \vdots \\β_i \end{array}\right] + \left[\begin{array}{ccc} e_1\\e_2\\ \vdots \\e_i \end{array}\right] ⎣⎢⎢⎢⎡y1y2⋮yi⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡11⋮1x11x21⋮xn1x12x22⋮xn2⋯⋯⋮⋯x1px2p⋮xnp⎦⎥⎥⎥⎤⎣⎢⎢⎢⎡β1β2⋮βi⎦⎥⎥⎥⎤+⎣⎢⎢⎢⎡e1e2⋮ei⎦⎥⎥⎥⎤
即 y = X β + e \boldsymbol{y} = \boldsymbol{X}\boldsymbol{\beta} + \boldsymbol{e} y=Xβ+e。
模型的基本假定:
(1). 解释变量 X 1 , X 2 , ⋅ ⋅ ⋅ , X p X_1,X_2, · · · ,X_p X1,X2,⋅⋅⋅,Xp 是确定性变量,不是随机变量。且要求设计矩阵 X \boldsymbol{X} X 的秩为p+1,即满秩矩阵
(2). 随机误差项具有0均值和等方差,即
{ E ( e i ) = 0 , i = 1 , 2 , ⋯ , n c o v ( e i , e j ) = { e 2 , i = j 0 , i ≠ j i , j = 1 , 2 , ⋯ , n \left\{\begin{array}{l} E({e_i})=0, &i=1,2, \cdots,n\\ cov(e_i,e_j)=\left\{\begin{array}{l} e^2, &i=j\\ 0, &i≠j \end{array}\right. &i,j=1,2, \cdots,n \end{array}\right. ⎩⎨⎧E(ei)=0,cov(ei,ej)={e2,0,i=ji=ji=1,2,⋯,ni,j=1,2,⋯,n
这个假定又被称为高斯-马尔科夫(Gauss-Markov)条件。(3). 正态分布的假定条件:
{ e i ∼ N ( 0 , σ 2 ) , i = 1 , 2 , ⋯ , n e 1 , e 2 , ⋯ , e n 相 互 独 立 \left\{\begin{array}{l} e_i \sim {N(0, \sigma^2)}, i=1,2, \cdots,n\\ e_1, e_2, \cdots, e_n相互独立 \end{array}\right. {ei∼N(0,σ2),i=1,2,⋯,ne1,e2,⋯,en相互独立
即 e ∼ N ( 0 , σ 2 I n ) \boldsymbol{e} \sim {N(\boldsymbol0, \sigma^2 {\boldsymbol{\text{I}}_\text{n})}} e∼N(0,σ2In) 。
则线性回归模型中最小二乘法表述如下:
寻找参数 β 0 , β 1 , β 2 , ⋯ , β p \beta_{0},\beta_{1},\beta_{2}, \cdots,\beta_{p} β0,β1,β2,⋯,βp 的估计值 β ^ 0 , β ^ 1 , β ^ 2 , ⋯ , β ^ p \hat{\beta}_{0},\hat{\beta}_{1}, \hat{\beta}_{2}, \cdots, \hat{\beta}_{p} β^0,β^1,β^2,⋯,β^p 使离差平方和 Q ( β 0 , β 1 , β 2 , ⋯ , β p ) = ∑ i = 1 n ( y i − β 0 − β 1 x i 1 − β 2 x i 2 − ⋯ − β p x i p ) 2 Q(\beta_{0},\beta_{1},\beta_{2}, \cdots,\beta_{p})=\sum\limits_{i=1}^n(y_i-\beta_{0}-\beta_{1}x_{i1}-\beta_{2}x_{i2}- \cdots-\beta_{p}x_{ip})^{2} Q(β0,β1,β2,⋯,βp)=i=1∑n(yi−β0−β1xi1−β2xi2−⋯−βpxip)2 达到极小,写成矩阵形式为: Q ( β ) = ∑ i = 1 N ∣ ∣ β T x i − y i ∣ ∣ 2 2 = ∑ i = 1 N ( β T x i − y i ) 2 = ( Y − β X ) T ( Y − β X ) = e T e Q(\beta) = \sum\limits_{i=1}^{N}||\beta^Tx_i-y_i||_2^2=\sum\limits_{i=1}^{N}(\beta^Tx_i-y_i)^2 = (Y-\beta X)^T(Y-\beta X) = \boldsymbol{e^T e} Q(β)=i=1∑N∣∣βTxi−yi∣∣22=i=1∑N(βTxi−yi)2=(Y−βX)T(Y−βX)=eTe ,即为损失函数。
对 β i \beta_i βi 求偏导并令其为0,整理得: X T ( y − X β ^ ) = 0 \boldsymbol{X}^T(\boldsymbol{y}-\boldsymbol{X} \boldsymbol{\hat\beta}) = \boldsymbol{0} XT(y−Xβ^)=0 ,当 ( X X T ) − 1 (\boldsymbol{XX^T})^{-1} (XXT)−1 存在时,得参数的最小二乘估计 β = ( ( X X T ) − 1 X T y ) \beta = ((\boldsymbol{XX^T})^{-1}\boldsymbol{X^T}\boldsymbol{y}) β=((XXT)−1XTy)
该部分内容参考:何晓群、刘文卿《应用回归分析》(第5版) 第3章、林建忠《回归分析与线性统计模型》 第2章
关于“在线性回归模型中,极大似然估计与最小二乘估计有什么联系与区别?”,可参见:最大似然估计和最小二乘估计的区别与联系
另外,关于最小二乘的几何解释在林建忠《回归分析与线性统计模型》 第2章中也可找到,不明白者可翻阅查看。
from sklearn import linear_model # 引入线性回归方法
lin_reg = linear_model.LinearRegression() # 创建线性回归的类
lin_reg.fit(X,y) # 输入特征X和因变量y进行训练
print("模型系数:", lin_reg.coef_) # 输出模型的系数
print("模型得分:", lin_reg.score(X,y)) # 输出模型的决定系数R^2
'''
模型系数: [-1.08011358e-01 4.64204584e-02 2.05586264e-02 2.68673382e+00
-1.77666112e+01 3.80986521e+00 6.92224640e-04 -1.47556685e+00
3.06049479e-01 -1.23345939e-02 -9.52747232e-01 9.31168327e-03
-5.24758378e-01]
模型得分: 0.7406426641094095
'''
树模型与线性模型的区别 决策树分类和逻辑回归分类的区别 【总结】 回归决策树和线性回归代码对比
关于KKT条件:
具体参见:如何理解拉格朗日乘子法和KKT条件?
用线性回归模型拟合数据集,要求只使用numpy
注:这里仅就一元线性回归问题做代码实现
# 一元线性回归问题
# y = w * x + b,w与b是参数
import numpy as np
# 定义损失函数
def loss_function(w, b, points):
loss = 0
for i in range(0, len(points)):
x = points[i, 0] # x值
y = points[i, 1] # 相应的y值
loss += (y - (w * x + b)) ** 2 # MSE均方误差*样本量
loss = loss / float(len(points)) # 损失函数—MSE均方误差
return loss
# 实现一次对w 和 b 的更新
def step_gradient(w_current, b_current, points, learning_rate):
w_gradient = 0
b_gradient = 0
N = float(len(points)) # 样本量
for i in range(0, len(points)):
x = points[i, 0]
y = points[i, 1]
w_gradient += -(2 / N) * (y - (w_current * x + b_current)) * x # 计算w的梯度,即对w求导,最小二乘
b_gradient += -(2 / N) * (y - (w_current * x + b_current)) # 计算b的梯度,即对b求导,最小二乘
new_w = w_current - (learning_rate * w_gradient) # 最小二乘+一次梯度下降法得到的w的估计值
new_b = b_current - (learning_rate * b_gradient) # 最小二乘+一次梯度下降法得到的b的估计值
return [new_w, new_b]
# 调用step_gradient(),对w,b循环更新num_iterations次,返回w,b
def gradient_descent_runner(points, starting_w, starting_b, learning_rate, num_iterations):
w = starting_w
b = starting_b
for i in range(num_iterations):
w, b = step_gradient(w, b, np.array(points), learning_rate)
return [w, b]
def main():
points = np.genfromtxt("data.csv", delimiter=",") # 读入csv文件,成ndarray
learning_rate = 0.0001 # 初始化学习率
initial_w = 0 # 初始化带估参数w
initial_b = 0 # 初始化待估参数b
num_iterations = 1000 # 设置迭代次数
print("Starting gradient descent at w = {0},b = {1},loss = {2}".format(initial_w, initial_b,
loss_function(initial_w, initial_b, points)))
print("Running...")
w, b = gradient_descent_runner(points, initial_w, initial_b, learning_rate, num_iterations)
print("After {0} iterations w = {1},b = {2},loss = {3}".format(num_iterations, w, b, loss_function(w, b, points)))
if __name__ == '__main__':
main()
'''
Starting gradient descent at w = 0,b = 0,loss = 10.053342197544191
Running...
After 1000 iterations w = 1.4777440851894448,b = 0.08893651993741344,loss = 2.693563420287152
'''
多元回归的代码实现具体参见:纯python(numpy)实现多元线性回归 及 线性回归理解(附纯python实现)