(一)线性回归(LinearRegression)原理和代码实现


线性回归
本系列重点在浅显易懂,快速上手。不进行过多的理论讲解:也就是不去深究what,而是关注how。全文围绕以下三个问题展开:

1)长什么样?

2)解决什么问题?

3)怎么实现?

3.1)从数学讲,原理

3.2)从代码上讲,如何掉包实现

长什么样
通俗的说就是解方程,先来回忆初中的二元一次方程组:

{ a ∗ x 11 + b ∗ x 21 = y 1 a ∗ x 12 + b ∗ x 22 = y 2 \begin{cases} a*x_{11} + b*x_{21} = y_1 \\ a*x_{12} + b*x_{22} = y_2 \end{cases} {ax11+bx21=y1ax12+bx22=y2

已知两组数

( x 11 = 1   x 21 = 2   y 1 = 3 ) , ( x 12 = 3   x 22 = 1   y 2 = 4 ) (x_{11}=1\ x_{21}=2\ y_1=3),(x_{12}=3\ x_{22}=1\ y_2=4) (x11=1 x21=2 y1=3),(x12=3 x22=1 y2=4)

求解a和b,很容易求的a=1,b=1。

上面是一个二元一次方程的例子,只不过线性回归的方程更加复杂,是m元n次(一般都是一次,效果不好的可以考虑多项式融合,就是多次方的)的方程:

{ a ∗ x 11 + b ∗ x 21 + . . . + z ∗ x m 1 + c = y 1 a ∗ x 12 + b ∗ x 22 + . . . + z ∗ x m 2 + c = y 2                    .                    .                    . a ∗ x 1 n + b ∗ x 2 n + . . . + z ∗ x m n + c = y n \begin{cases} a*x_{11} + b*x_{21} + ... + z*x_{m1} + c = y_1 \\ a*x_{12} + b*x_{22} + ... + z*x_{m2} + c = y_2\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ .\\ a*x_{1n} + b*x_{2n} + ... + z*x_{mn} + c = y_n\\ \end{cases} ax11+bx21+...+zxm1+c=y1ax12+bx22+...+zxm2+c=y2                  .                  .                  .ax1n+bx2n+...+zxmn+c=yn

解决什么问题
先看一组数据(一组sklearn中公开的数据集,波士顿的房价预测,共有13个特征,最后一列y是房价,这里只展示了5条数据,实际数据有506条):

采用线性回归建模,最终的目的就是为了找到一组θ_1,θ_2,…,θ_{13},θ_0(除了13个系数,还包含一个常数项θ_0),使得下式成立。

θ 1 ∗ x 1 + θ 2 ∗ x 2 + . . . . . . + θ 13 ∗ x 13 + θ 0 = y θ_1*x1+θ_2*x2+......+θ_{13}*x13+θ_0=y θ1x1+θ2x2+......+θ13x13+θ0=y

怎么实现
其实就是如何求解 θ 1 , θ 2 , . . . , θ 13 , θ 0 θ_1,θ_2,...,θ_{13},θ_0 θ1,θ2,...,θ13,θ0,有两种方法:

1)最小二乘法(有缺陷,一般都是梯度下降法,具体看下文)

2)梯度下降法

最小二乘法

y i = θ T ∗ x i + ξ i y^i = θ^T*x^i+ξ^i yi=θTxi+ξi

python默认一个一维的向量,时列向量, x i x^i xi的格式是(13,1), θ T θ^T θT的格式是(1,13),(先不考虑常熟项), ξ i ξ^i ξi表示 y i y^i yi θ T ∗ x i θ^T*x^i θTxi之间的误差(机器学习不能求解到百分百准确的θ值,只能使得ξ^i值不断减小,也就是让预测值不断的逼近真实值y。

ξ i ξ^i ξi,假设是独立同分布的,服从均值为0,方差为 σ 2 σ^2 σ2的高斯分布,即:

他的联合分布概率是:

L ( θ ) L(θ) L(θ)就是样本的似然函数,转化为数学中求解θ最大似然估计值的问题,即:最大似然估计法(这里有兴趣的可以去补习数学上这块的知识,不想学习,可以只看下面的求解过程能看懂就行)

首先向将似然函数 L ( θ ) L(θ) L(θ)转换为对数似然函数 l o g ( L ( θ ) ) log(L(θ)) log(L(θ))

要求 l ( θ ) l(θ) l(θ)的最大值,转化为求
1 2 ∑ i = 1 m ( y i − θ T x i ) 2 \frac{1}{2}\sum_{i=1}^{m}(y^i-θ^Tx^i)^2 21i=1m(yiθTxi)2
的最小值,这就是目标函数(或者叫损失函数):

这就是最小二乘法的结果是一样的。

求解J(θ)的最小值,可以采用求解导函数,并使导函数为0的方式实现。

先将J(θ)转换为矩阵的形式:

具体的求解过程如下(这里需要用到矩阵求导的知识)直接维基百科有公式套用就行了,千万不要去过多的引入(学习一项新技能,最忌讳的就是,遇到一点不会的就恨不得把它祖宗三代都抛出来学习一边,一次性进行过于深入的学习,而深陷其中不能自拔,慢慢消磨殆尽学习的兴趣,应该是,就先学到会用的地步能解决当下的问题就赶紧停止,先学how怎么用,有机会了再去学what具体原理是怎么样的):

再求解:

X T X θ − X T Y = 0 X^TXθ-X^TY=0 XTXTY=0 得: θ = ( X T X ) − 1 X T Y θ=(X^TX)^{-1}X^TY θ=(XTX)1XTY

到此最小二乘法,求解θ得过程讲解完毕,最小二乘法得缺陷也很明显了,首先要求X^TX是可逆的,为了防止不可逆,做如下更改,

θ = ( X T X + λ I ) − 1 X T Y θ=(X^TX+λI)^{-1}X^TY θ=(XTX+λI)1XTY

最小二乘法直接求解的难处在于,逆矩阵的求解是个难点。

梯度下降法
1)确定目标函数,

2)初始化θ,(随机初始化或者初始化为0),

3)求解J(θ)的梯度,

∂ J ( θ ) ∂ θ = X T X θ − X T Y \frac{\partial J(θ)}{\partial θ} = X^TXθ-X^TY θJ(θ)=XTXTY

4)沿着负梯度的方向更显θ,

θ = θ − α ∗ ∂ J ( θ ) ∂ θ , α 是学利率 θ = θ -α*\frac{\partial J(θ)}{\partial θ},α是学利率 θ=θαθJ(θ)α是学利率

迭代一定的轮次,直到损失函数的值不在下降为止。

手动代码实现


#coding=utf8
import numpy as np
import pandas as pd
from sklearn import datasets
from tqdm import tqdm, trange
import matplotlib.pyplot as plt

'''原函数'''
def F(theta,X):
    return np.dot(X, theta)

'''损失函数'''
def J(theta, X, Y):
    return float(1/2*np.dot((np.dot(X,theta)-Y).T, (np.dot(X,theta)-Y))[0][0])/len(X)

'''偏导数'''
def H(theta, X, Y):
    return np.dot(X.T, np.dot(X,theta)-Y)/X.shape[0]

'''标准化'''
def standard_scaler(X):
    #mean_ = np.mean(X,axis=0)
    #std_ = np.std(X,axis=0)
    #X = (X-mean_)/std_
    max_ = np.max(X,axis=0)
    min_ = np.min(X,axis=0)
    X = (X-min_)/(max_-min_)
    return X
    
if __name__ == "__main__":
    data = datasets.load_boston()
    X = data.data
    X = standard_scaler(X)
    Y = data.target.reshape(-1,1)
     
    loss_list = []
    theta = np.random.rand(X.shape[1], 1) # 初始化参数
    eta = 0.01
    with trange(100000) as T:
        for i in T:
            loss = J(theta, X, Y) 
            loss_list.append(loss)
            theta = theta - eta*H(theta, X, Y)
            T.set_postfix(loss=loss)
    print(theta)  
    plt.plot(loss_list)
    plt.show()

sklearn调包实现
这里直接讲解,如何调用sklearn实现。

from sklearn.linear_model import LinearRegression #sklearn中,线性回归模型在linear_model模块中
# 调取sklearn中自带的数据集
from sklearn.datasets import load_boston #调用上文一开始提到大波士顿房价数据集

X, y = load_boston(return_X_y=True) #获取X,y数据
LR = LinearRegression() #初始化一个线性回归模型
LR.fit(X,y) #fit函数用于训练

LR.predict(X) #predict函数用于预测
LR.coef_ #coef_用于返回θ的值
LR.intercept_ #intercept_用于返回常数项的值(截距)


更多内容可以参考sklearn的官方文档

sklearn.linear_model.LinearRegression — scikit-learn 1.3.0 documentation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值