数据挖掘之线性回归原理(附代码)

1.什么是线性回归

这里引用百度百科的解释:利用数理统计中的回归分析,来确定变量间相互依赖的定量关系的一种统计分析方法,其表达形式为 y ( i ) = w T x ( i ) + e ( i ) y^{(i)} = w^Tx^{(i)}+e^{(i)} y(i)=wTx(i)+e(i) e e e为误差(用来代替统计误差或者抽样误差),它服从均值为0的标准正态分布。例如成年人的月收入与月消费的关系,二者之间肯定存在某种关系。
在求解之前,通常会给定几个假设:

  • (1)自变量 ( X i , X j ) (X_i, X_j) (Xi,Xj) 之间应相互独立;
  • (2)误差项 ( e i , e j ) (e_i,e_j) (eiej) 之间应相互独立;
  • (3)模型线性可加。假设因变量为Y,自变量为X1,X2,则回归分析的默认假设为 Y = b + a 1 X 1 + a 2 X 2 + e Y=b+a1X1+a2X2+e Y=b+a1X1+a2X2+e
    线性性 :X1每变动一个单位,Y相应变动a1个单位,与X1的绝对数值大小无关。
    可加性:X1对Y的影响是独立于其他自变量(如X2)的。

使用python生成模拟数据,具体代码与注释如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

font = {'family': 'Microsoft YaHei',
        'weight': 'bold',
        'size': 10}
plt.rc('font', **font) 
# 设置字体

''' 1.模拟数据x, y'''
x1 = np.arange(1, 5, 0.1)  # 0.1为步长
y = x1 * 4 + 3 + 2 * np.random.randn(len(x1))

# 2.通过API实现参数估计
model_lr = LinearRegression()
model_lr.fit(x1.reshape(-1, 1), y.reshape(-1, 1))  # 转换为列向量形
# model_lr.coef_ (1,1), model_lr.intercept_(1,)都是ndarray类型
print('API模型求解的w={}, b={}'.format(round(model_lr.coef_[0][0], 4), round(model_lr.intercept_[0], 4)))

下图是通过python接口求解到的W和b,绘制出原始数据和拟合线。
在这里插入图片描述

2.最大似然估计(MLE)

假设 y = X ∗ W + e y = X*W+e y=XW+e,最后的 J ( w ) J(w) J(w)就是我们要优化的目标函数也称为损失函数。
y ( i ) = w ⋅ x ( i ) + e ( i ) y^{(i)} = w · x^{(i)} +e^{(i)} y(i)=wx(i)+e(i)

概 率 密 度 : p ( e ( i ) ) = 1 2 π σ ⋅ e x p ( − e ( i ) 2 2 σ 2 ) 概率密度:p(e^{(i)}) = \frac{1}{\sqrt {2\pi}\sigma} · exp(-\frac{{e^{(i)}}^2}{2\sigma^2}) p(e(i))=2π σ1exp(2σ2e(i)2)

p ( y ( i ) ∣ w , x ( i ) ) = 1 2 π σ ⋅ e x p ( − [ y ( i ) − w ⋅ x ( i ) ] 2 2 σ 2 ) p(y^{(i)}|w, x^{(i)}) = \frac{1}{\sqrt {2\pi}\sigma} · exp(-\frac{ { [y^{(i)}-w·x^{(i)} }]^2 } {2\sigma^2}) p(y(i)w,x(i))=2π σ1exp(2σ2[y(i)wx(i)]2)

对上式求极大似然估计MLE
M L E = ∏ i = 1 n 1 2 π σ ⋅ e x p ( − [ y ( i ) − w ⋅ x ( i ) ] 2 2 σ 2 ) MLE=\quad \prod_{i=1}^n \frac{1}{\sqrt {2\pi}\sigma} · exp(-\frac{ { [y^{(i)}-w·x^{(i)} }]^2 } {2\sigma^2}) MLE=i=1n2π σ1exp(2σ2[y(i)wx(i)]2)
对上式左右两边求对数
l n ( M L E ) = ∑ i = 1 n − [ y ( i ) − w ⋅ x ( i ) ] 2 2 σ 2 + c o n s t a n t ln(MLE)=\sum_{i=1}^n-\frac{ { [y^{(i)}-w·x^{(i)} }]^2 } {2\sigma^2}+constant ln(MLE)=i=1n2σ2[y(i)wx(i)]2+constant
由于是想对上式求最大值,因此负号去掉等价于求它的最小值,而方差虽然未知,但是是一个定值。得到下式
m i n J ( W ) = ∑ i = 1 n − [ y ( i ) − w ⋅ x ( i ) ] 2 2 minJ(W)=\sum_{i=1}^n-\frac{ { [y^{(i)}-w·x^{(i)} }]^2 } {2} minJ(W)=i=1n2[y(i)wx(i)]2

3.利用正规方程求解(矩阵求导)

J ( w ) J(w) J(w)写成矩阵方程后,表达式和计算过程更加简洁,其中 X T X X^TX XTX 是半正定矩阵,半正定矩阵在现实数据下,多数情况是存在逆矩阵的,如果不存在可以给它加一个 λ I λI λI矩阵,可以避免无逆。推导过程如下:

J ( W ) = 1 2 ( y − X w ) T ( y − X w ) , w 为 列 向 量 J(W)=\frac{1}{2}{(y-Xw)}^T(y-Xw), w为列向量 J(W)=21(yXw)T(yXw)w
J ( W ) = 1 2 ( w T X T X w − w T X T y − y T X w + y T y ) J(W)=\frac{1}{2}(w^TX^TXw-w^TX^Ty-y^TXw+y^Ty) J(W)=21(wTXTXwwTXTyyTXw+yTy)

对化简后的 J ( W ) J(W) J(W)进行求导

∇ J ( W ) = 1 2 ( 2 X T X w − X T y − ( y T x ) T ) \nabla J(W) = \frac{1}{2}(2X^TXw-X^Ty-{(y^Tx)^T)} J(W)=21(2XTXwXTy(yTx)T)
∇ J ( W ) = X T X w − X T y \nabla J(W) = X^TXw-X^Ty J(W)=XTXwXTy
求 驻 点 : X T X w − X T y = 0 求驻点: X^TXw-X^Ty = 0 XTXwXTy=0

得 出 : w = ( X T X ) − 1 X T y 得出:w = {(X^TX)}^{-1}X^Ty w=(XTX)1XTy

if you 不太了解矩阵求导,这边给出一种情况的简单推导过程,其他的可以自己尝试。
矩阵、向量求导
更多求导知识大家可以参考—>矩阵求导简介
附上正规方程求解方式的代码

''' 3.通过线性代数矩阵求导,也叫正规方程 X*W=y'''
X = np.array([x1])
X = np.insert(X, 1, values=[1] * len(X), axis=0)  
# 给array插入一行为1的元素 2xn矩阵, 为了最后把b也看成一个w
X = X.T  ''' X = nx2矩阵, 我们运算所需要的'''
inverse = np.linalg.inv(np.dot(X.T, X))
# 计算$X^TX的逆矩阵$
W = np.dot(np.dot(inverse, X.T), y)
print('正规方程求解的w={},b={}'.format(round(W[0], 4), round(W[1], 4)))

上面的代码亲测有效管用,可以直接运行,求解过程或最后推导的一样,事实上API也是这样求解的。

4.梯度下降

梯度下降,顾名思义是根据梯度来不断逼近全局最小值(针对于凸函数),只不过是按照负梯度来的,因为正梯度是增大的方向。首先需要求出它的梯度。用原来的参数,减去它的梯度,为了防止学习步长过长,会跳过极小值点,因此通常会加一个小于1的学习率。

g r a d = ∇ J ( W ) = X T ( X W − y ) grad = \nabla J(W) =X^T(XW-y) grad=J(W)=XT(XWy)

w = w − λ ∗ g r a d w = w-λ*grad w=wλgrad

建议大家在做线性回归时,可以把损失函数写成均方误差 l o s s = ( y p r e d i c t − y ) 2 / m loss=(y_predict-y)^2/m loss=(ypredicty)2/m,原因是降低它的梯度,可以减少迭代,可以从学习率和迭代次数上调整。最后付代码

# 4.通过梯度下降求解参数w,b  y=w*x+b
def grad(y):
    w = np.random.randn()
    # 随机生成一个w, b
    b = np.random.randn()
    iteration = 10000
    learn_rating = 0.0001
    for i in range(iteration):
        y_hat = w * x1 + b
        gradient_b = 2 / len(x1) * np.sum(y_hat - y)
        gradient_w = 2 / len(x1) * np.sum((y_hat - y) * x1)  # 每一个残差与x的积再作和
        w = w - learn_rating * gradient_w
        b = b - learn_rating * gradient_b
    # return round(w,4), round(b,4)

    # 下面是通过矩阵梯度下降,更简洁一点
    weight = np.random.randn(2, 1)  # 生成一个2x1的列向量w和b
    for i in range(iteration):
        gradient = X.T.dot(X.dot(weight) - y.reshape(-1, 1))
        weight -= learn_rating * gradient
    return weight[0][0], weight[1][0]


print('梯度下降求解的w={}, b={}'.format(grad(y)[0], grad(y)[1]))
# 和API求解的参数是一样的
MSE = np.mean((W[0] * x1 + W[1] - y) ** 2)
RSS = np.sum((W[0] * x1 + W[1] - y) ** 2)  # Residual Sum of Square! y_hat-y
ESS = np.sum((W[0] * x1 + W[1] - np.mean(y)) ** 2)  # Explain Sum of Square!
TSS = np.sum((y - np.mean(y)) ** 2)  # yi-y_bar
print('R-Square:', ESS / TSS)
plt.scatter(x1.reshape(-1, 1), y.reshape(-1, 1))
plt.plot(x1, W[0] * x1 + W[1], color='r', linestyle='--', label='一元一次线性拟合')
plt.legend()
plt.show()

好了,到此简易的线性回归原理就告一段落了,觉的有帮助的读者可以点个赞,有错误的地方也欢迎批评指正,never too late to learn。
资料参考:机器学习之线性回归

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值