理论部分
回归是统计学中最有力的工具之一。监督学习算法分为分类算法和回归算法两种,其实就是根据类别标签分布类型为离散型、连续性而定义的。顾名思义,分类算法用于离散型分布预测,如KNN、决策树、朴素贝叶斯、adaboost、SVM、Logistic回归都是分类算法;回归算法用于连续型分布预测,针对的是数值型的样本,使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。
回归的目的就是建立一个回归方程用来预测目标值,回归的求解就是求这个回归方程的回归系数。预测的方法当然十分简单,回归系数乘以输入值再全部相加就得到了预测值。
1、回归的定义
回归最简单的定义是,给出一个点集D,用一个函数去拟合这个点集,并且使得点集与拟合函数间的误差最小,如果这个函数曲线是一条直线,那就被称为线性回归,如果曲线是一条二次曲线,就被称为二次回归。
2、多元线性回归
假定预测值与样本特征间的函数关系是线性的,回归分析的任务,就在于根据样本X和Y的观察值,去估计函数h,寻求变量之间近似的函数关系。定义:
其中,n=特征数目;
xj=每个训练样本第j个特征的值,可以认为是特征向量中的第j个值。
为了方便,记x0=1,则多变量线性回归可以记为:
,(θ、x都表示(n+1,1)维列向量)
3、广义线性回归
用广义的线性函数:
wj是系数,w就是这个系数组成的向量,它影响着不同维度的Φj(x)在回归函数中的影响度,Φ(x)是可以换成不同的函数,这样的模型我们认为是广义线性模型,Φ(x)=x时就是多元线性回归模型。
线性回归的求解
说到回归,常常指的也就是线性回归。假设有连续型值标签(标签值分布为Y)的样本,有X={x1,x2,...,xn}个特征,回归就是求解回归系数θ=θ0,θ1,…,θn。那么,手里有一些X和对应的Y,怎样才能找到θ呢? 在回归方程里,求得特征对应的最佳回归系数的方法是最小化误差的平方和。这里的误差是指预测y值和真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以采用平方误差(最小二乘法)。平方误差可以写做:
在数学上,求解过程就转化为求一组θ值使求上式取到最小值,那么求解方法有梯度下降法、NormalEquation等等。梯度下降有如下特点:需要预先选定步长a、需要多次迭代、特征值需要Scaling(统一到同一个尺度范围)。因此比较复杂,还有一种不需要迭代的求解方式--Normal
Equation,简单、方便、不需要Feature Scaling。NormalEquation方法中需要计算X的转置与逆矩阵,计算量很大,因此特征个数多时计算会很慢,只适用于特征个数小于100000时使用;当特征数量大于100000时使用梯度法。另外,当X不可逆时就有岭回归算法的用武之地了。
下面就概括一下常用的几种求解算法。
1、梯度下降法
根据平方误差,定义该线性回归模型的损耗函数(Cost Function)为:
,(系数是为了方便求导展示,此处的系数也可以只是1/2,没有m。)线性回归的损耗函数的值与回归系数θ的关系是碗状的,只有一个最小点。
2、普通最小二乘法
Normal Equation算法也叫做普通最小二乘法(ordinary least squares),其特点是:给定输人矩阵X,如果XTX的逆存在并可以求得的话,就可以直接采用该方法求解。其求解理论也十分简单:既然是是求最小误差平方和,另其导数为0即可得出回归系数。
矩阵X为(m,n+1)矩阵(m表示样本数、n表示一个样本的特征数),y为(m,1)列向量。
上述公式中包含XTX, 也就是需要对矩阵求逆,因此这个方程只在逆矩阵存在的时候适用。然而,矩阵的逆可能并不存在,后面会讨论处理方法。
3、局部加权线性回归
线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有最小均方误差的无偏估计。显而易见,如果模型欠拟合将不能取得最好的预测效果。所以有些方法允许在估计中引人一些偏差,从而降低预测的均方误差。其中的一个方法是局部加权线性回归(LocallyWeightedLinearRegression,LWLR )。在该算法中,我们给待预测点附近的每个点赋予一定的权重.于是公式变为:
,W是(m,m)矩阵,m表示样本数。
LWLR使用 “核”(与支持向量机中的核类似)来对附近的点赋予更高的权重。核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:
,k需要优化选择。
局部加权线性回归也存在一个问题,即增加了计算量,因为它对每个点做预测时都必须使用整个数据集,而不是计算出回归系数得到回归方程后代入计算即可。因此该算法不被推荐。
标准回归与局部加权回归python2实现
from numpy import *
#该函数打开一个用tab键分割的文本文件
def loadDataSet(fileName): #general function to parse tab -delimited floats
numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields
dataMat = []; labelMat = []
fr = open(fileName)
for line in fr.readlines():
lineArr =[]
curLine = line.strip().split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)
labelMat.append(float(curLine[-1]))
return dataMat,labelMat
def standRegres(xArr,yArr):#该函数用来计算最佳拟合直线
xMat = mat(xArr); yMat = mat(yArr).T#读入x和y并将它们保存到矩阵中
xTx = xMat.T*xMat
if linalg.det(xTx) == 0.0:#判断行列式是否为0,直接调用numpy的linalg线性代数的库来计算行列式
print "This matrix is singular, cannot do inverse"
return
ws = xTx.I * (xMat.T*yMat)#行列式非0,计算系数并返回
return ws
def lwlr(testPoint,xArr,yArr,k=1.0):#局部加权线性回归函数
xMat = mat(xArr); yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye((m)))#创建对角权重矩阵
for j in range(m): #next 2 lines create weights matrix遍历数据集
diffMat = testPoint - xMat[j,:] #
weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))#计算每个样本点对应的权重值
xTx = xMat.T * (weights * xMat)
if linalg.det(xTx) == 0.0:
print "This matrix is singular, cannot do inverse"
return
ws = xTx.I * (xMat.T * (weights * yMat))#估计最优回归系数
return testPoint * ws
def lwlrTest(testArr,xArr,yArr,k=1.0): #loops over all the data points and applies lwlr to each one
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)#lwlrtest函数主要用于调用lwlr函数
return yHat
def lwlrTestPlot(xArr,yArr,k=1.0): #same thing as lwlrTest except it sorts X first
yHat = zeros(shape(yArr)) #easier for plotting
xCopy = mat(xArr)
xCopy.sort(0)
for i in range(shape(xArr)[0]):
yHat[i] = lwlr(xCopy[i],xArr,yArr,k)
return yHat,xCopy
if __name__=="__main__":
dataMat,labelMat=loadDataSet('C:\Users\HZF\Desktop\machinelearninginaction\Ch08\ex0.txt')
#print (mat(dataMat[0:2]))[:,1]
#print (mat(labelMat[0:2])).T[:,0]
import matplotlib.pyplot as plt#导入matplotlib库用于画散点图进行比较
fig=plt.figure()
ax=fig.add_subplot(111)#add_subplot(111)函数也可写成add_subplot(1,1,1),意思是将画布分布在1行1列从左到右从上到下的第一个模块
ws=standRegres(dataMat,labelMat)#计算系数向量
#print ws
yHat=(mat(dataMat))*ws#计算最优回归值
#以下代码是标准线性回归的散点图与最佳拟合的图像
#ax.scatter((mat(dataMat))[:,1].flatten().A[0],(mat(labelMat)).T[:,0].flatten().A[0])#数据集散点图
#xCopy=(mat(dataMat)).copy()
#xCopy.sort(0)#对点按照升序排序
#yHat=xCopy*ws#画最佳拟合直线
#ax.plot(xCopy[:,1],yHat)
#plt.show()
pc=corrcoef(yHat.T,labelMat)#计算yHat与labelMat的相关系数,即相关矩阵
#print pc
#ws=lwlr(dataMat[0],dataMat,labelMat,k=1.0)
yHat=lwlrTest(dataMat,dataMat,labelMat,0.02)
print yHat
#以下代码是局部线性回归的散点图与最佳拟合的图像
srtInd=(mat(dataMat))[:,1].argsort(0)
xSort=(mat(dataMat))[srtInd][:,0,:]
ax.plot(xSort[:,1],yHat[srtInd])
ax.scatter((mat(dataMat))[:,1].flatten().A[0],(mat(labelMat)).T.flatten().A[0],s=2,c='red')
plt.show()
以上就是标准回归(线性回归)与局部加权回归算法的理论与python2实现过程(主要是针对最小二乘与局部加权的实现),会尽快补充这两种算法的应用与其他回归算法!
参考文献
1、机器学习经典算法详解及Python实现--线性回归(Linear Regression)算法
2、《机器学习实战》(书)