1.线性回归(LinearRegression)
回归模型可以使用一个回归方程(regressionequation)来描述,其中求解回归系数(regression weights)的过程即称为回归。
线性回归使用最小二乘法(ordinaryleast squares),即基于均方误差最小化模型的求解:
用矩阵表示可以写成
对sita求偏导可得
令偏导等于零,解出sita的最优估计解为:
则预测输出为:
然而,现实任务中XTX往往不满秩,如样例的特征数目大,甚至超过样例数时,此时可解出多组sita使得均方误差最小化。当XTX不满秩时,常见的做法是引入正则化(regularization)项,将不适定的问题转化为适定问题,如岭回归(ridge regression)和lasso算法等。
参数学习算法(Parametriclearning algorithm)是指有固定数目的参数用于进行数据拟合的算法,如线性回归有固定参数集合sita;非参数学习算法(Non-parametric learning algorithm)是指没有固定数目的参数用于进行数据拟合的算法,其参数随着样本集合的增大而线性正变化,如局部加权线性回归有非固定的权重参数W。
2.局部加权线性回归(LocallyWeighted Linear Regression,LWLR)
线性回归求的是具有最小均方误差的无偏估计,因而可能出现欠拟合现象;有些方法允许在估计中引入一些偏差,从而降低预测的均方误差,比如局部加权线性回归(Locally Weighted Linear Regression,LWLR),如典型的住房价格预测(housingprice prediction)问题。
局部加权线性回归根据预测样例与训练样例的距离给予权重,距离越近权重越大,然后应用最小二乘法拟合,即基于加权的均方误差最小化模型的求解:
用矩阵表示可以写成
其中权重使用核函数来赋予,核的类型可以自由选择,常用高斯核:
权重矩阵W则是对角矩阵
对sita求偏导可得
令偏导等于零,解出sita的最优估计解为:
则预测输出为:
局部加权线性回归使用高斯核函数时,可调的参数只有波长参数k;当k越大时,表示各个实例具有相近的权重,得出的最佳拟合直线与标准回归一致,有可能出现欠拟合现象;当k越小时,表示与预测值相近的实例具有较大的权重,导致对噪声点敏感,拟合的直线与数据点过于贴近,可能出现过拟合现象。
局部加权线性是典型的非参数学习算法,每计算一个预测值都要遍历一遍训练集或其局部样本。而对于样本非常大时,则存在计算量大的问题,算法应该进行调整,如使用kNN算法的kd树获取预设的若干个最近邻,并赋予合适的权重,如此减少计算量。
'''
Created on 2017年2月17日
线性回归LR和局部加权线性回归LWLR算法
@author: Administrator
'''
import numpy as np
import matplotlib.pyplot as plt
# 数据载入函数
def loadDataSet(filename):
numFeat = len(open(filename).readline().split('\t')) - 1
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 = np.mat(xArr); yMat = np.mat(yArr).T
xTx = xMat.T * xMat
# 判断行列式是否可以求逆
if abs(np.linalg.det(xTx)) < 1e-10:
print('This matrix is singular, cannot do inverse')
return
# 求回归系数向量
ws = xTx.I * (xMat.T * yMat)
return ws
# 局部加权线性回归函数
def lwlr(testPoint, xArr, yArr, k=1.0):
xMat = np.mat(xArr); yMat = np.mat(yArr).T
m = np.shape(xMat)[0]
weights = np.mat(np.eye((m)))
# 根据高斯核函数构造权重矩阵
for j in range(m):
diffMat = testPoint - xMat[j,:]
weights[j,j] = np.exp(diffMat * diffMat.T / (-2.0 * k ** 2))
# 判断行列式是否可以求逆
xTx = xMat.T * (weights * xMat)
if abs(np.linalg.det(xTx)) < 1e-10:
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):
m = np.shape(testArr)[0]
yHat = np.zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i], xArr, yArr, k)
return yHat
# 计算样本实际值序列和预测值序列的均方误差
def rssError(yArr, yHatArr):
return ((yArr - yHatArr) ** 2).sum()
# 绘制原始数据散点图和回归线
def scatterPlot(xArr, yArr, yHat):
# 预处理数据,yMat和yHatMat为列向量
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
yHatMat = np.mat(yHat).T
fig = plt.figure()
ax = fig.add_subplot(111)
# 根据输入数据的特征选取xMat的下标为1的列和yMat绘制散点图
ax.scatter(xMat[:,1], yMat, s=30, c='blue', marker='o')
# 对xMat递增排序,绘制回归线
srtInd = xMat[:,1].argsort(0)
xSort = xMat[srtInd][:,0,:]
ax.plot(xSort[:,1], yHatMat[srtInd][:,0])
# 计算模型的均方差
print('模型的均方误差:\n', np.sum((yArr - yHatMat.A) ** 2))
# 计算实际序列和预测序列的相关系数
print('实际值和预测值的相关系数:\n', np.corrcoef(yHatMat.T, yMat.T))
plt.show()
if __name__ == '__main__':
xArr,yArr = loadDataSet('Datas/ex0.txt')
print(xArr[0:10])
# 标准回归
ws = standRegres(xArr, yArr)
print(ws)
yHat = (np.mat(xArr) * ws).T
scatterPlot(xArr, yArr, yHat)
# 局部加权线性回归
k = 0.01
yHat = lwlrTest(xArr, xArr, yArr, k).T
scatterPlot(xArr, yArr, yHat)
# 预测鲍鱼的年龄
xArr,yArr = loadDataSet('Datas/abalone.txt')
print(xArr[0], yArr[0])
yHat01 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 0.1)
yHat1 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 1)
yHat10 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 10)
print(rssError(yArr[0:99], yHat01.T))
print(rssError(yArr[0:99], yHat1.T))
print(rssError(yArr[0:99], yHat10.T))
scatterPlot(xArr[0:99], yArr[0:99], yHat10)
yHat01 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 0.1)
yHat1 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 1)
yHat10 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 10)
print(rssError(yArr[100:199], yHat01.T))
print(rssError(yArr[100:199], yHat1.T))
print(rssError(yArr[100:199], yHat10.T))
scatterPlot(xArr[100:199], yArr[100:199], yHat10)
代码参考《机器学习实战》