求解回归模型的最小二乘法(代数方法和数值方法)

对于回归模型,最小二乘法是通过最小化残差平方和来估计回归系数的方法。残差平方和就是预测值跟样本之间的差的平方和,残差平方和除以样本量n就是均方误差,即通常所说的损失函数。回归模型的损失函数不宜直接用残差平方和而要用均方误差是因为残差平方和是所有样本点残差平方的总和,会随着样本量增大而增加,不能体现样本点残差的平均水平。以一元回归模型为例,损失函数为

\[loss=\frac{1}{2n}\sum_{i=1}^{n}\left ( y_{i} -y\right )^{2}=\frac{1}{2n}\sum_{i=1}^{n}\left ( y_{i} -\beta _{1}x-\beta _{0}\right )^{2}\]

上式中系数1/2是为了将来求导时方便约去。为了求未知参数β1和β0的取值使得这个损失函数达到最小值,通常有两种解法:代数方法和数值方法。

(1)代数方法

代数方法就是假定损失函数在其驻点上取得最小值,然后令偏导数为0解线性方程组求出β1和β0的解析解,也称为直接法。这个思想跟用最大似然法进行参数估计是一样的。对于凸函数而言,可以认为其驻点就是极值点。对于多元回归分析,通常要求样本矩阵X列满秩而且非病态,才能采用代数方法求解。上式中损失函数loss对β1和β0求偏导,约去系数后可得

\[\left\{\begin{matrix} \sum_{i=1}^{n}\left ( y_{i}-\hat{\beta _{0}}-\hat{\beta _{1}}x_{i} \right )=0\\ \sum_{i=1}^{n}x_{i} \left (y_{i}-\hat{\beta _{0}}-\hat{\beta _{1}}x_{i} \right )=0 \end{matrix}\right.\]

整理之后得到

\[\left\{\begin{matrix} n\hat{\beta _{0}}+\hat{\beta _{1}}\sum_{i=1}^{n}x_{i}=\sum_{i=1}^{n}y_{i}\\ \hat{\beta _{0}}\sum_{i=1}^{n}x_{i}+\hat{\beta _{1}}\sum_{i=1}^{n}x_{i}^{2}=\sum_{i=1}^{n}x_{i}y_{i} \end{matrix}\right.\]

这是一个关于β1和β0的二元一次线性方程组,称为规范方程,用常规的解方程方法即可求出

\[\left\{\begin{matrix} \hat{\beta _{1}}=\frac{\sum_{i=1}^{n}\left ( x_{i}-\bar{x} \right )\left ( y_{i}-\bar{y} \right )}{\sum_{i=1}^{n}\left ( x_{i}-\bar{x} \right )^{2}}\\ \hat{\beta _{0}}=\bar{y}-\hat{\beta _{1}}\bar{x} \end{matrix}\right.\]
其中
\[\bar{x}=\frac{1}{n}\sum_{i=1}^{n}x_{i}\]\[\bar{y}=\frac{1}{n}\sum_{i=1}^{n}y_{i}\]
表示样本在x和y坐标上的平均值。从上面的结果也可以看出样本的均值一定落在拟合直线上。

(2)数值方法

数值方法就是采用数值分析的方法设定初始值和步长,按照一定规则逐步迭代求解,通常所说的梯度下降和牛顿法就是数值方法,其本质是状态空间搜索问题。

梯度下降法的迭代公式为:
\[x^{\left (k+1 \right )}=x^{\left (k \right )}-\alpha \cdot loss'\left ( x^{\left ( k \right )} \right )\]

牛顿法的迭代公式为:

\[x^{\left (k+1 \right )}=x^{\left (k \right )}-\frac{loss'{\left (x^{(k)} \right )}}{loss''{\left ( x^{(k)} \right )}}\]

需要说明的是,牛顿法一般是用于求解方程f(x)=0的根,而不是求f(x)的最小值,我们这里将求凸函数loss(x)最小值问题转化为求方程loss'(x)=0的根,对loss(x)先求了一阶导数。因此一般数值分析教科书上关于牛顿法的公式是如下形式,请注意这里分母中导函数是一阶的而不是像上面二阶的,上面式子中的loss'(x)相当于下面式子中的f(x)。

\[x^{\left (k+1 \right )}=x^{\left (k \right )}-\frac{f{\left (x^{(k)} \right )}}{f'{\left ( x^{(k)} \right )}}\]

对于多元的情形,上式中的导数可写成偏导数的形式,按各个变量分别求偏导然后迭代。例如在人工神经网络中通常用w表示权重即自变量的系数,用b表示偏置项即常数项。上面的梯度下降法迭代公式就写成

\[w_{ij}^{(k+1)}=w_{ij}^{(k)}-\alpha \cdot \frac{\partial }{\partial w_{ij}}loss(w_{ij}^{(k)},b)\]

\[b_{i}^{(k+1)}=b_{i}^{(k)}-\alpha \cdot \frac{\partial }{\partial b}loss(w,b_{i}^{(k)})\]

下面分别用梯度下降法和牛顿法求函数

\[f(x,y)=\left ( x-10 \right )^{2}+\left ( y-10 \right )^{2}\]

的最小值,用python程序实现。

import matplotlib.pyplot as plt
%matplotlib inline

#先用梯度下降法

def f(x,y):  #定义函数
    return (x-10)**2+(y-10)**2

def f_der1(x,y):  #定义一阶导函数
    return [2*(x-10), 2*(y-10)]

point=[]
lossG=[]

for i in range(30):
    if i==0:
        point.append([20,20])
    else:
        point.append([point[i-1][0]-0.1*f_der1(point[i-1][0],point[i-1][1])[0],\
                      point[i-1][1]-0.1*f_der1(point[i-1][0],point[i-1][1])[1]])
       
    lossG.append(f(point[i][0],point[i][1]))
    print('x=',point[i][0],'y=',point[i][1], 'loss=', lossG[i])

输出结果:

x= 20 y= 20 loss= 200
x= 18.0 y= 18.0 loss= 128.0
x= 16.4 y= 16.4 loss= 81.91999999999996
x= 15.12 y= 15.12 loss= 52.42879999999998
x= 14.096 y= 14.096 loss= 33.554432

......

x= 10.037778931862956 y= 10.037778931862956 loss= 0.002854495385411744
x= 10.030223145490364 y= 10.030223145490364 loss= 0.0018268770466634305
x= 10.024178516392292 y= 10.024178516392292 loss= 0.0011692013098646298
x= 10.019342813113834 y= 10.019342813113834 loss= 0.0007482888383134181
x= 10.015474250491067 y= 10.015474250491067 loss= 0.0004789048565205876

#下面用牛顿法实现

def f(x,y):
    return (x-10)**2+(y-10)**2

def f_der1(x,y):
    return [2*(x-10), 2*(y-10)]

point=[]
lossN=[]

for i in range(30):
    if i==0:
        point.append([20,20])
    else:
        point.append([point[i-1][0]-f_der1(point[i-1][0],point[i-1][1])[0]/2, point[i-1][1]-f_der1(point[i-1][0],point[i-1][1])[1]/2])
       
    lossN.append(f(point[i][0],point[i][1]))
    print('x=',point[i][0],'y=',point[i][1], 'loss=', lossN[i])

plt.plot(range(len(lossG)),lossG,c='b')
plt.plot(range(len(lossN)),lossN,c='r')
plt.ylabel('loss')
plt.xlabel('iterations')

输出结果:

x= 20 y= 20 loss= 200
x= 10.0 y= 10.0 loss= 0.0
x= 10.0 y= 10.0 loss= 0.0
x= 10.0 y= 10.0 loss= 0.0
x= 10.0 y= 10.0 loss= 0.0
x= 10.0 y= 10.0 loss= 0.0
x= 10.0 y= 10.0 loss= 0.0

下面两条曲线分别是梯度下降法(蓝色)和牛顿法(红色)的损失函数,可见牛顿法收敛速度更快。但牛顿法并不是处处都优于梯度下降法,网上已有很多博客讨论二者各自的优缺点。

下面用梯度下降法求一元线性回归模型的系数,按照机器学习的习惯用w和b表示自变量系数(权重)和常数项(偏置项):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

x_data=[]
y_data=[]
vect=[]
num=1000

for i in range(num):
    x=np.random.normal(2, 3)
    y=2*x+3+np.random.normal(0,3)
    vect.append([x,y])
x_data=[v[0] for v in vect]

y_data=[v[1] for v in vect] #用正态分布的随机数模拟噪声,叠加在y=2*x+3上,生成样本数据集

iteration=50
learning_rate=0.1
loss=[]
w=np.random.randn(1)
b=0
def residual(X,y,beta1,beta0):
    residual=np.subtract(np.add(np.multiply(beta1,X),beta0),y)
    return residual
#设定迭代次数、学习率和计算残差的函数,初始化w和b

for i in range(iteration):
    loss.append(np.sum(np.square(residual(x_data,y_data,w,b)))/(2*num)) #求损失
    loss_d=np.multiply(x_data,residual(x_data,y_data,w,b)) #求损失函数的导函数
    w=w-learning_rate*np.sum(loss_d)/num #用梯度下降法更新w值
    b=b-learning_rate*np.sum(residual(x_data,y_data,w,b))/num #用梯度下降法更新b值

    print('w=',w,'loss=',loss[-1],'b=',b)

plt.plot(range(len(loss)),loss)
plt.xlabel('iterations')
plt.ylabel('loss')
plt.scatter(x_data, y_data, alpha=0.3)

plt.plot([np.min(x_data),np.max(x_data)],[np.min(x_data),np.max(x_data)]*w+b,c='red')

运行结果如下:

w= [3.72936329] b= -0.03236914140040016 loss= 130.58205144894814

w= [2.13106005] b= 0.2571815757307898 loss= 17.69469571893334

w= [2.52963021] b= 0.4383069982559178 loss= 7.7719073727376164

w= [2.37972723] b= 0.6312087771929674 loss= 6.892719391319409

w= [2.38406102] b= 0.803956272325264 loss= 6.458935800765466

......

w= [2.01324307] b= 3.022184104661439 loss= 4.29899872608602

w= [2.01195693] b= 3.0300272625161333 loss= 4.298316833507587

w= [2.01076028] b= 3.037324702788515 loss= 4.297726530290476

w= [2.00964689] b= 3.04411439585801 loss= 4.297215514480728

猜你喜欢

转载自blog.csdn.net/sigtem/article/details/80546082