算法描述
线性回归
最小二乘法
算法作用
用于做预测等
输入
训练集:{(x_i,y_i )}, 样本个数为m, X∈R^n,即X一共有n个属性,
输出
练出回归参数向量θ
算法推导
回归类的数学基础是最小二乘法,最小二乘法的一般解释是找到一组参数θ=(θ_0,θ_1,…,θ_n )使训练样本中各数据函数值y_i与拟合出来的方程算出来的函数值f(x_i)平方差的和最小化,即下式:
通常的做法是通过训练样本构造出上式,并对θ求偏导并等于0,就可以求出θ。过程比较繁琐,可以利用线性代数中的投影理论,通过矩阵变换求出θ,推导如下:
为了可视化,在二维空间作图:
图中的平面是一矩阵A构成的列空间,即col(A), A有两个分量,即a ⃗_1 ,a ⃗_2均列向量,b ⃗是一个不在a ⃗_1 a ⃗_2 张成的平面的一个向量,现在又想用a ⃗_1,a ⃗_2 来线性表示b ⃗,是无解的,即Ax ⃗=b ⃗是一个无解的方程,但是b ⃗平面上的投影是可以用a ⃗_1,a ⃗_2来表示的,设投影矩阵为P,即Ax ⃗=Pb ⃗,且向量b ⃗与平面内所有的向量距离最短的向量就是它的投影向量(OA) ⃗=Pb ⃗ ,而(OA) ⃗可以用a ⃗_1,a ⃗_2线性表示:
由于向量(AC) ⃗ ⊥平面,且(AC) ⃗=b ⃗-(OA) ⃗
所a ⃗_1∙(b ⃗-(OA) ⃗)=0 ⃗,a ⃗_2 ∙(b ⃗-(OA) ⃗)=0 ⃗,注意这里是向量内积的方式,改写成矩阵相乘,需要将a ⃗_1,a ⃗_2转置:
(以上前提是A^T A是可逆矩阵,一般情况下是可逆的,可以通过计算行列式是否为0判断是否是可逆)
所以就可以通过矩阵运算的方式求出来θ ⃗,即回归参数,这种通过投影理论,避免了复杂的代数运算,直接求出结果。该方法中可以从二维空间推广到多维空间。
代码实现
这里的A矩阵每一行就是样本里的一和数据的各个特征值,行数为样本个数,还是以《机器学习实战》一书中的CH08例子并参考源程序,编程
数据集
X0 | X1 | X2 |
---|---|---|
1.000000 | 0.067732 | 3.176513 |
1.000000 | 0.427810 | 3.816464 |
1.000000 | 0.995731 | 4.550095 |
1.000000 | 0.738336 | 4.256571 |
1.000000 | 0.981083 | 4.560815 |
1.000000 | 0.526171 | 3.929515 |
1.000000 | 0.378887 | 3.526170 |
1.000000 | 0.033859 | 3.156393 |
1.000000 | 0.132791 | 3.110301 |
1.000000 | 0.138306 | 3.149813 |
1.000000 | 0.247809 | 3.476346 |
Python代码
from numpy import mat,linalg
import matplotlib.pyplot as plt
def loadDataSet(fineName):
dataArray=[] #相当于矩阵A
labelArray=[] #y值,也就是结果值
fr=open(fineName)
for line in fr.readlines():
lineArr =[]
curlLine=line.strip().split('\t')
lineArr.append(float(curlLine[0]))
lineArr.append(float(curlLine[1]))
dataArray.append(lineArr)
labelArray.append(float(curlLine[2]))
fr.close()
return dataArray,labelArray
#
def trian(dataArray,labelArray):
dataMat=mat(dataArray) #mXn矩阵
labelMat=mat(labelArray).transpose()#为一列向量 mX1
weights=linalg.inv(dataMat.transpose()*dataMat)*dataMat.transpose()*labelMat
return weights;
#画图
def showPicture(dataArray,labelArray,weights):
xMat=mat(dataArray)
yMat=mat(labelArray)
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])
plt.subplot(111)
xCopy=xMat.copy()
xCopy.sort(0)
yHat=xCopy*weights
ax.plot(xCopy[:,1],yHat)
plt.show()
return
主程序
import train
if __name__ == '__main__':
dataArray,labelArray = train.loadDataSet("ex0.txt")
weights = train.trian(dataArray, labelArray)
print weights #即θ值
train.showPicture(dataArray, labelArray, weights)
结果