常用算法一 多元线性回归详解2(解析解求解多元线性回归)
上一篇讲到什么是多元线性回归以及多元线性回归的推导过程详解,本章我们一起来看如何求得最优解,就是我们得到了多元线性回归到损失函数就是最小二乘公式,那么如何利用最小二乘公式求得最优解。对多元线性回归到推导过程没有概念的同学欢迎查看上一篇文章::常用算法一 多元线性回归详解1(推导过程)
求解多元线性回归
多元线性回归常用的求解方法有两种:
1-解析解求解法
2-梯度下降法求解
本章我们来看多元线性回归的解析解求解法。
解析解求解法
说到解析解求解,很多同学都已经忘记了什么事解析解。解析解就是指通过公式就可以求得到方程的解。我们只需要方程的参数带入到公式中,计算公式结果就可以得到方程的解,而不用一步一步化简求解。比如我们初中学的一元二次方程的解细节是。是不是豁然开朗,原来就是你小子。
想要用解析解来求解最小二乘函数,那我们首先得知道他的解析解是啥。
a.求得最小二乘公式的解析解。
这里要用到上一章讲到的知识点,求一个函数在某一点上的导数,就是求在这个函数的图像上,过这一点所做切线的斜率。这一点的导函数就是切线的函数。一个二次函数的图像是一个抛物线,那想想一下,通过图像的顶点所做的切线是一条怎样的直线。应该是一条与x轴平行的直线,此时这条直线的斜率为0.函数图像的顶点就是函数的解,也就是说,我们通过函数的解这一点来做切线,切线的斜率就是0.
那我们反过来利用一下刚刚总结出的结论。如果我找到了函数图像上切线为0的点,是不是找到了函数的解?切线是什么?对函数上某一点求导就等于通过这一点在函数图像上做切线,作出的切线就是求导得到的导函数的图像,切线的函数就是对函数求导所得到的导函数,那我们只要找到导函数为0对点,是不是就得到了图像的解?(这一段一定要理解。多读几遍)
所以,我们可以通过对最小二乘函数求导,让导函数为0时的结果,就是最小二乘的解。求导过程如下:
首先对最小二乘进行变形,变为矩阵表达形式:
展开矩阵函数:
展开之后我们对J(θ)求导并令导数等于0:
最终求的解析解为:θ=
2-解析解的代码实现
手动实现:
import numpy as np
import matplotlib.pyplot as plt
from bz2 import __author__
#设置随机种子
seed = np.random.seed(100)
#构造一个100行1列到矩阵。矩阵数值生成用rand,得到到数字是0-1到均匀分布到小数。
X = 2 * np.random.rand(100,1) #最终得到到是0-2均匀分布到小数组成到100行1列到矩阵。这一步构建列X1(训练集数据)
#构建y和x的关系。 np.random.randn(100,1)是构建的符合高斯分布(正态分布)的100行一列的随机数。相当于给每个y增加列一个波动值。
y= 4 + 3 * X + np.random.randn(100,1)
#将两个矩阵组合成一个矩阵。得到的X_b是100行2列的矩阵。其中第一列全都是1.
X_b = np.c_[np.ones((100,1)),X]
#解析解求theta到最优解
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
# print(theta_best)
# 生成两个新的数据点,得到的是两个x1的值
X_new = np.array([[0],[2]])
# 填充x0的值,两个1
X_new_b = np.c_[(np.ones((2,1))),X_new]
print (X_new_b)
# 用求得的theata和构建的预测点X_new_b相乘,得到yhat
y_predice = X_new_b.dot(theta_best)
print(y_predice)
# 画出预测函数的图像,r-表示为用红色的线
plt.plot(X_new,y_predice,'r-')
# 画出已知数据X和掺杂了误差的y,用蓝色的点表示
plt.plot(X,y,'b.')
# 建立坐标轴
plt.axis([0,2,0,15,])
plt.show()
利用sklearn包实现
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
# 解析解求线性回归
# 手动构建数据集和y与x的对应关系
x = 2 * np.random.rand(100,1)
y= 4 + 3*x + np.random.randn(100,1)
line_reg = LinearRegression()
# 训练数据集,训练完成后,参数会保存在对象line_reg中。
line_reg.fit(x,y)
# line_reg.intercept为截距,就是w0,line_reg.coef_为其他参数,coef的全拼为coefficient
print(line_reg.intercept_,line_reg.coef_)
x_new = np.array([[0],[2]])
# line_reg.predict(x_new) 为预测结果
print(line_reg.predict(x_new))
plt.plot(x_new,line_reg.predict(x_new),'r-')
# 画出已知数据X和掺杂了误差的y,用蓝色的点表示
plt.plot(x,y,'b.')
# 建立坐标轴
plt.axis([0,2,0,15,])
plt.show()
运行结果如下:
如果有的同学想要运行代码,需要安装pycharm和anaconda,将python的interrupt设置为anaconda的bin目录下的python就可以了。网上有很多教程,请原谅这里不再赘述了。
此处需要说明,因为在使用解析解求解最小二乘的过程中,出现了矩阵求逆的步骤。因为有些矩阵没有逆矩阵,只能使用近似矩阵来代替,所以结果的精度会降低。二则矩阵求逆随着维度的增加,计算量也大大增加,求解速度变慢。所以一般情况下我们都会使用第二种求解办法:梯度下降。
文章链接:梯度下降和随机梯度下降