线性回归的数学原理以及代码实现

线性回归的数学原理以及代码实现

首先要说的是线性模型想要得到的是一个线性组合。狭义的线性回归是想要把所有的点(或者叫特征)用一条直线来拟合,也就是图像上的点要尽可能地落到直线上。而广义的线性回归就不一定非要是直线了,例如在逻辑回归中用的就是一条对数几率的曲线,也就是图像上的点要尽可能的落到那条曲线上面。

在这篇文章中主要对线性回归作讨论:
首先呈上线性模型

f(x)=wTx+b

【优点】

每个x前面的w,也就是系数很直观,他们就是权重系数,当我们拟合出一个模型的时候,对于每一个x我们都能通过w知道它到底重要不重要。

【缺点】

线性模型,顾名思义,他只对线性的数据点拟合的好,而现实中存在着大量的非线性特征,拟合效果就大打折扣了。


线性回归是用梯度下降法对最小二乘误差进行优化

我们既然已经确定了任务是找到这样一条直线, f(x)=wTx+b ,使得这条直线能很好地拟合我们的样本点。那我们最理想的情况就是所有的样本点都在这条直线上,Perfect!也就是说,在这个时候,所有样本点到直线的距离为0,同时他们的距离之和也肯定为0了。

但是总归要回到现实中来,不可能有那么完美的例子,那我们只能力求他们的距离之和接近0了。或者再退一步,接近不了0也行,距离之和越小总还是越好的吧!那么就有了下面的数学表述:

yi 代表第i个点的真实值;
f(xi) 代表通过模型(函数 f )的预测值,也就是我们的直线;
于是就有了距离的表达式:

distance=(yif(xi))2

这里用到了平方,是一种数学的技巧,为了达成下面两个目的:
+ 距离有正有负,我们这个加和的思想可不是为了抵消正负值的,所以我们必须要去掉他们的符号
+ 去掉符号也可以用绝对值,但是平方之后有一个放大的效应:如果距离不是很大,平方之后就还好,如果距离很大,平方之后就会被放的更大。(这里可以想象一下 y=x2 的函数图像,x越大,y就跟着变得更大)

【简单讲两句】:
上面这个距离表达式,学名叫做“欧式距离”,是计算距离的一种常用的数学方法,今后在机器学习其他算法中也会经常遇到。

我们继续之前的思路,就是要最小化这个距离值,由于直线由w和b决定,那么我们需要优化的参数就是w和b,换成数学语言,就是:

我们希望要距离平方和最小化的方法,称为最小二乘法

如果从损失函数(loss function)的角度看,这个叫做“平方损失”。如果我们用 J(θ) 来表达损失函数,然后再做下面几个数学变换:
+ 令 J(θ)=12(yif(xi))2

argmin(w,b)i=1mJ(θ)=
argmin(w,b)i=1m12(yif(xi))2

在这里前面有了一个1/2的操作,纯粹了为了数学上的方便,反正在最小化的计算中,数倍的缩放没有什么影响


线性回归是残差高斯分布的最大似然估计

残差
残差就是预测值和真实值之间的差,也就是上面的 (yif(xi)) 这一项。

我们通常认为线性回归的残差应该满足均值为0,方差为 σ2 的正态分布的假设。误差为0最好,越往两边走应该越少。

正态分布x概率表达式:
p(x)=12πσexp[x22σ2]

上式中的x即是线性回归的误差/残差,那么就把x替换成 (yif(xi)) 得到;

p((yif(xi)),(w,b))=12πσexp[(yif(xi))22σ2]

接下来,我们想要达成,或者说最大限度地达成我们之间关于残差的假设,我们就必须让这个概率最大,也就是用极大似然法来求解,也就是最大化样本中每一个点分布的乘积。

L(w,b)=i=1m12πσexp[(yif(xi))22σ2]

由于连乘计算难度大,我们两边都取对数,这样就变成连加:

l(w,b)=i=1mlog12πσexp[(yif(xi))22σ2]

进一步化简:

l(w,b)=mlog12πσ1σ212i=1m(yif(xi))2

去掉一些常数项,得到我们要最大化的目标:

12i=1m(yif(xi))2

殊途同归啊!


下面开始求解:
+ 向量化w、x和y,在这里统统用大写字母表示向量
+ 把b吸入向量w中,他们两个组合其他就是我们的参数 θ

向量化的表达方式可以让我们在接下来的运算中取消加和符号,看上去更加简便一些

argmin12(YθX)2

J(θ) 经过向量运算得到:

12(YθX)T(YθX)
= 12(YTθTXT)(YθX)
= 12(θTXTXθθTXTYYTXθYTY)

结果对 θ 求偏导:

【矩阵求偏导】

ABB=ATYTXθ

ATBA=BθTXTY

ATBAA=2ABθTXTXθ

J(θ)θ=12(2XTXθXTYXTY0)=(XTXθXTY)

令偏导等于0:

XTXθXTY=0
这里暂时默认 XTX 是可逆的

得出参数 θ=(XTX)1XTY 我们利用计算出来的参数,可以直接写出线性回归的代码来:

import numpy as np

def train(X,y):
    """训练数据"""
    # 如果X^T·X是可逆的话:
    if np.linalg.det(X.T * X) != 0:
    # 计算参数theta
        theta =  ((X.T.dot(X).I).dot.(X.T).dot(y))
        return theta

def test(x,theta):
    """拟合数据"""
    return x.T.dot(theta)

*在本篇文章中涉及但是没有深入的概念会在后续的文章中陆续讲解,包括但不限于:
+ 极大似然法及其概率背景
+ 正则化

你可能感兴趣的:(机器学习,回归模型)