机器学习 - 线性回归(Linear Regression)

1. 目标

线性回归是希望通过对样本集进行有监督的学习之后,找出特征属性与标签属性之间的线性关系 Θ \Theta Θ。从而在获取没有标签值的新数据时,根据特征值和线性关系,对标签值进行预测。
散点图

2. 算法原理

2.1 线性模型(Linear Model)

在二维平面坐标系中,一条直线可表示为: f ( x ) = θ 1 x + θ 0 f(x) = \theta_1x + \theta_0 f(x)=θ1x+θ0
扩展到n维空间中,则表示为: f ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n f(x) = \theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n f(x)=θ0+θ1x1+θ2x2+...+θnxn
同时可写成向量的形式: f ( x ) = Θ T X f(x) = \Theta^TX f(x)=ΘTX
其中 X = [ x 0 , x 1 , x 2 , . . . , x n ] T ( x 0 = 1 ) ; Θ = [ θ 0 , θ 1 , θ 2 , . . . , θ n ] T X = [x_0,x_1,x_2,...,x_n]^T(x_0=1);\Theta = [\theta_0,\theta_1,\theta_2,...,\theta_n]^T X=[x0,x1,x2,...,xn]T(x0=1);Θ=[θ0,θ1,θ2,...,θn]T

2.2 损失函数(Loss Function)

当有了样本集 D = { ( X i , y i ) } i = 1 n D = \{(X_i,y_i)\}^n_{i=1} D={(Xi,yi)}i=1n,即视作空间中的n个离散点之后,如何对这些点进行拟合,形成一个曲面方程,则成为需要解决的问题。
根据线性模型可知,想要改变曲面拟合的形状,我们可以调整的是特征属性前的系数 Θ \Theta Θ
为了使曲面与样本集中的点拟合的更好,需要设定一个评判标准,即损失函数:
J ( θ 0 , θ 1 , . . . , θ m ) = 1 2 n ∑ i = 1 n ( h θ ( X i ) − y i ) 2 J(\theta_0,\theta_1,...,\theta_m) = \frac{1}{2n}\sum^n_{i=1}(h_\theta(X_i)-y_i)^2 J(θ0,θ1,...,θm)=2n1i=1n(hθ(Xi)yi)2
其中: h θ ( X ) = f ( X ) h_\theta(X) = f(X) hθ(X)=f(X),只不过 h θ ( X ) h_\theta(X) hθ(X)是根据变量 θ \theta θ变化的。
损失函数的意思是,在 Θ \Theta Θ 确定时,每组属性 X i X_i Xi均能根据线性函数获取到相应的 f ( X i ) f(X_i) f(Xi) h θ ( X i ) h_\theta(X_i) hθ(Xi),而 y i y_i yi是样本集中给出的标签值,将二者相减再取平方,获取到某一组特征拟合结果与标签值的差异。然后对每组求得得差异求和后除以 2 n 2n 2n计算出数值,作为当前 Θ \Theta Θ 前提下得损失值。
而损失函数本身如果画出来是一条关于 Θ \Theta Θ 的曲线。
损失函数曲线
问题就转化成了求损失函数的最小值

2.3 梯度下降

梯度下降是一种求凸函数极值的方法,这种方法是求取函数在某一个点的斜率,并根据设定的学习率 α \alpha α,调整 Θ \Theta Θ ,迭代的向损失函数的极小值靠近,最终求得 Θ \Theta Θ。公式如下:
θ j = θ j − α d d θ j J ( θ j ) \theta_j = \theta_j - \alpha\frac{d}{d\theta_j}J(\theta_j) θj=θjαdθjdJ(θj)
其中 d d θ j J ( θ j ) \frac{d}{d\theta_j}J(\theta_j) dθjdJ(θj)是损失函数关于 θ j \theta_j θj的斜率,乘上设定的系数后,迭代递减。

至此 Θ \Theta Θ 可求,问题也得以解决,但其实还存在两个问题

  • 引入的 α \alpha α 如何给值,太小会导致收敛速度慢,太大又会导致震荡或者不收敛?
  • 当模型复杂的时候, J ( Θ ) J(\Theta) J(Θ)是一个高阶函数,会把样本中的噪声特性也学习下来,虽然能完美的拟合样本集,却泛化能力差,即过拟合

2.4 通过正则化减小过拟合风险

损失函数变为:
J ( Θ ) = 1 2 n [ ∑ i = 1 n ( h θ ( X i ) − y i ) 2 + λ ∑ j = 1 m θ j 2 ] J(\Theta) = \frac{1}{2n}[\sum^n_{i=1}(h_\theta(X_i)-y_i)^2+\lambda\sum^m_{j=1}\theta_j^2] J(Θ)=2n1[i=1n(hθ(Xi)yi)2+λj=1mθj2]
其中 λ ∑ j = 1 m θ j 2 \lambda\sum^m_{j=1}\theta_j^2 λj=1mθj2是正则项,用于控制大量参数对拟合的影响。

2.5 学习率的选取

结论是通常会尝试一系列学习率的取值:0.001, 0.003,0.01, 0.03,0.1, 0.3,1,
初始值0.001, 如此循环直至找到最合适的 α \alpha α。然后对于这些不同的 α \alpha α 值,绘制 J ( Θ ) J(\Theta) J(Θ) 随迭代步数变化的曲线,然后选择看上去使其快速下降的值。

3. Python实例 - 波士顿房价

sklearn库中提供了几种数据集,load_boston是波士顿房价的数据集,以此进行实验。

3.1 双变量拟合 - 模拟算法原理

import numpy as np
from sklearn.datasets import load_boston
import matplotlib.pyplot as plt
# 解决中文乱码问题
import matplotlib.font_manager as fm
chinesefont = fm.FontProperties(fname='C:/Windows/Fonts/msyh.ttc')

# 获取数据
boston = load_boston()

# 仅以LSTAT属性作为特征的散点图
# 人口中低下人群所占比例
# x = [x1,x2,...,xn]; y = [y1,y2,...,yn]
x = boston.data[:,12]
y = boston.target
plt.scatter(x,y,s=10, c='r')
plt.xlabel('人口中地下人群所占比例',fontproperties=chinesefont)
plt.ylabel('房价,单位$1000',fontproperties=chinesefont)
plt.show()

散点图

# 转换X向量和Y向量
# X = [[1,x1],[1,x2],...,[1,xn]]
# Y = [[y1],[y2],...,[yn]]
X = np.c_[np.ones(x.shape[0]),x]
Y = y.reshape(y.shape[0],1)

# 定义以上损失函数cost
# cost = theta0 + theta1 * x
def cost(X, Y, theta=[[0],[0]]):
    J = 0
    m = Y.size
    h = X.dot(theta)    
    J = 1.0/(2*m)*(np.sum(np.square(h-y)))
    
    # 加入正则项 lambda = 1 时
    # J = 1.0/(2*m)*((np.sum(np.square(h-y)))+ 1 * np.sum(np.square(theta)))
    return J

# 定义梯度下降函数
# 此处用的是最大迭代次数限制进行循环,也可以使用下降判断进行循环
def gradientDescent(X, Y, theta=[[0],[0]], alpha=0.009, num_iters=1500):
    m = Y.size
    J_history = np.zeros(num_iters)
    
    for iter in np.arange(num_iters):
        h = X.dot(theta)
        theta = theta - alpha*(1.0/m)*(X.T.dot(h-Y))
        J_history[iter] = cost(X, Y, theta)
    return(theta, J_history)

# 执行梯度下降函数获得最终theta以及损失值列表CostJ
theta, CostJ = gradientDescent(X,Y)

# 绘制损失值列表,即损失函数
plt.plot(CostJ)
plt.xlabel('迭代次数',fontproperties=chinesefont)
plt.ylabel('损失函数值',fontproperties=chinesefont)
plt.show()

损失函数

# 根据求得得theta,得到线性方程,进行拟合显示
y_predict = theta[0] + theta[1] * x
plt.scatter(x,y,s=10, c='r')
plt.xlabel('人口中地下人群所占比例',fontproperties=chinesefont)
plt.ylabel('房价,单位$1000',fontproperties=chinesefont)
plt.plot(x,y_predict )

拟合直线

3.2 sklearn中的LinearRegression 与 多变量拟合

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import sklearn.metrics

# 按照30%的比例对样本集进行拆分
X_train,X_test,y_train,y_test = train_test_split(boston.data,boston.target,test_size=0.3)

# 利用 sklearn 库 进行线性拟合
regr = LinearRegression()
regr.fit(X_train, y_train)
print(regr.intercept_,regr.coef_)
'''
> 37.160773310177426 [-1.07867550e-01  3.97141277e-02  1.99087321e-02  2.97904968e+00
 -1.46457678e+01  3.47666820e+00  7.33405297e-05 -1.34668768e+00
  2.85031315e-01 -1.16980362e-02 -9.81568374e-01  8.75851883e-03
 -5.37797404e-01]
'''

# 对训练集和测试集进行预测
y_train_pred = regr.predict(X_train)
y_test_pred = regr.predict(X_test)
# 计算相应的MAE和RMSE,填入计算需要的值到括号中
print("Train MAE: ", sklearn.metrics.mean_absolute_error(y_train,y_train_pred))
print("Train RMSE: ", np.sqrt(sklearn.metrics.mean_squared_error(y_train,y_train_pred )))
print("Test MAE: ", sklearn.metrics.mean_absolute_error(y_test,y_test_pred ))
print("Test RMSE: ", np.sqrt(sklearn.metrics.mean_squared_error(y_test,y_test_pred )))
'''
> Train MAE:  3.141770205845444
  Train RMSE:  4.575911160428769
  Test MAE:  3.514234225409807
  Test RMSE:  4.959841655342295
'''

学习不易,贵在坚持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值