接上篇
5.局部加权线性回归
局部加权线性回归(LWLR),在该算法中,我们给待预测点附近的每个点赋予一定的权重,在这个自己上基于最小均方差进行普通的回归,每次预测均需要先选取出对应数据子集。该算法接触回归系数w的形式如下:
普通线性回归:
加权(weight)线性回归:,w是一个矩阵,用来给每个数据点赋予权重。
LWLR使用“核”对附近的点赋予更高的权重。核的类型可以自由选择,最常用的就是高斯核,其对应的权重:(与支持向量机中的核一致)。w是只含有对角线元素的矩阵w,点x与x(i)越近,则w(i,i)机会越大,也就是说距离中心点越近的权重越大,对拟合曲线的影响也就越大,所以也有了局部加权这一名词。公式中的k为超参数,需要自行指定,他决定了对附近的点赋予多大的权重。
LWLR方法对待预测的每个点赋予一定的权重,在这样的一个子集上基于最小均方差来进行普通的回归。因此,会增加计算量,它对每个点做预测时都必须使用整个数据集,实际预测结果一般。
代码如下(代码参考自《机器学习实战》第8章):
def linearRegLwlr(x,y,k=1.0):
#局部加权线性回归,k为高斯核函数的参数
# hat{w} = (X^TWX)^{-1}·X^TWy
xMat = np.mat(x)
yMat = np.mat(y).T # 传入数据是1*m的矩阵,将其转置成m*1维矩阵
m = np.shape(x)[0] # 数据条数
yHat = np.zeros(m) # 初始化预测值y矩阵
for i in range(m): #遍历x,从1到m,使用解析解求每一个yhat
weights = np.mat(np.eye((m))) # 需要根据每条数据,计算权重,每条的权重都不相同
for j in range(m): # 遍历所有数据求解一条数据对应的权重
diffMat = x[i] - xMat[j,:]
weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2)) # 高斯核函数
xTx = xMat.T * (weights * xMat) # x转置*x
if np.linalg.det(xTx) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
print("This matrix is singular, cannot do inverse")
ws = xTx.I * (xMat.T * (weights * yMat)) # 求得这一条数据的解析解
yHat[i]=x[i] * ws # x[i]为1,将值赋值给yHat矩阵
return yHat
print('')
print('3.5、局部加权线性回归,linearRegLwlr函数,无theta解析式!')
print('局部加权线性回归拟合结果图,使用第一列TV数据展示!')
yHat=linearRegLwlr(x,y.T,k=1)
# 绘图
xMat = np.mat(x)
srtIndex = xMat[:,0].argsort(axis=0)
xSort = xMat[srtIndex][:,0,:]
# 绘制散点图
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(xSort[:,0],yHat[srtIndex])
ax.scatter(xMat[:,0].flatten().A[0],np.mat(yHat).flatten().A[0],s=2,c='red') #必须是数组的形式
plt.show()
6.岭回归
岭回归实际上相当于有约束条件情况的最小二乘法回归,即回归系数为:,另一种写法:。惩罚λ的引入能够减少不重要的参数,从而更好滴理解数据。参数λ的选择,需要将原训练数据分成训练数据和测试数据,在训练数据上训练回归系数,然后在测试数据上测试性能,通过选取不同的λ来重复上述过程,最终选取使得预测误差最小的λ。
岭回归缺陷:
1.主要靠目测选择岭参数
2.计算岭参数时,各种方法结果差异较大
所以一般认为,岭迹图只能看多重共线性,却很难做变量筛选。
代码如下(代码参考自《机器学习实战》第8章):
def linearRegRidge(x,y,k=1.0,lam=0.2):
xMat = np.mat(x)
yMat = np.mat(y)
yMat = yMat - np.mean(y,0) # 数据归一化
xMat = (xMat - np.mean(xMat,0))/np.var(xMat,0) # 数据归一化,因为lambda*I在数值很大时,系数w平方会非常大
numTestPts = 30 # N组lanba值
wMat = np.zeros((numTestPts,np.shape(xMat)[1]))# 30组lanba值
for i in range(numTestPts): # 求每组的w系数
#ws = ridgeRegres(xMat,yMat,np.exp(i-10))
# i=0
print(i,np.exp(i-10))
lam=np.exp(i-10) # 使用指数级递增,效果更有效
xTx = xMat.T*xMat # x转置*x
denom = xTx + np.eye(np.shape(xMat)[1])*lam # x转置*x 加上单位阵
if np.linalg.det(denom) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
print("This matrix is singular, cannot do inverse")
#return
ws = denom.I * (np.dot(xMat.T,yMat)) # 求得一组w系数
wMat[i,:]=ws.T
print('30组wMat,不同lam下参数情况:',wMat)
return wMat
theta6=linearRegRidge(x,y)
print('')
print('3.6、岭回归,linearRegRidge函数,多组theta解析式!',theta6)
7.lasso回归
lasso回归通过构造一个一阶惩罚函数获得一个精炼的模型;通过最终确定一些指标(变量)癿系数为零(岭回归估计系数等于0癿机会微乎其微,造成筛选变量困难),解释力很强。
擅长处理具有多重共线性的数据,筛选变量,与岭回归一样是有偏估计。lasso回归则是与岭回归略有不同,使用了L1正则:
lasso回归代码如下:
待补充,!!!∑(゚Д゚ノ)ノ,有点复杂,以后再弄了,先去弄逻辑回归了!!
以上算法完整代码如下
# -*- coding: utf-8 -*-
"""
@Time : 2018/10/24 10:23
@Author : hanzi5
@Email : **@163.com
@File : linear_regression.py
@Software: PyCharm
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
def linearRegLwlr(x,y,k=1.0):
#局部加权线性回归,k为高斯核函数的参数
# hat{w} = (X^TWX)^{-1}·X^TWy
xMat = np.mat(x)
yMat = np.mat(y).T # 传入数据是1*m的矩阵,将其转职成m*1维矩阵
m = np.shape(x)[0] # 数据条数
yHat = np.zeros(m) # 初始化预测值y矩阵
for i in range(m): #遍历x,从1到m,使用解析解求每一个yhat
weights = np.mat(np.eye((m))) # 需要根据每条数据,计算权重,每条的权重都不相同
for j in range(m): # 遍历所有数据求解一条数据对应的权重
diffMat = x[i] - xMat[j,:]
weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2)) # 高斯核函数
xTx = xMat.T * (weights * xMat) # 求解析解
if np.linalg.det(xTx) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
print("This matrix is singular, cannot do inverse")
ws = xTx.I * (xMat.T * (weights * yMat)) # 求得这一条数据的解析解
yHat[i]=x[i] * ws # x[i]为1,将值赋值给yHat矩阵
return yHat
def linearRegRidge(x,y,k=1.0,lam=0.2):
xMat = np.mat(x)
yMat = np.mat(y)
yMat = yMat - np.mean(y,0) # 数据归一化
xMat = (xMat - np.mean(xMat,0))/np.var(xMat,0) # 数据归一化,因为lambda*I在数值很大时,系数w平方会非常大
numTestPts = 30 # N组lanba值
wMat = np.zeros((numTestPts,np.shape(xMat)[1]))# 30组lanba值
for i in range(numTestPts): # 求每组的w系数
#ws = ridgeRegres(xMat,yMat,np.exp(i-10))
# i=0
print(i,np.exp(i-10))
lam=np.exp(i-10) # 使用指数级递增,效果更有效
xTx = xMat.T*xMat # x转置*x
denom = xTx + np.eye(np.shape(xMat)[1])*lam # x转置*x 加上单位阵
if np.linalg.det(denom) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
print("This matrix is singular, cannot do inverse")
#return
ws = denom.I * (np.dot(xMat.T,yMat)) # 求得一组w系数
wMat[i,:]=ws.T
print('30组wMat,不同lam下参数情况:',wMat)
return wMat
if __name__ == "__main__":
path = 'D:/python_data/8.Advertising.csv'
data = pd.read_csv(path) # TV、Radio、Newspaper、Sales
#data_matrix = data.as_matrix(columns=['TV', 'Radio', 'Newspaper', 'Sales']) # 转换数据类型
data_array = data.values[:,1:] # 转换数据类型,去除第一列序号列
x = data_array[:, :-1] #去除y对应列的数据,其他列作为x
y = data_array[:, -1].reshape((-1,1))
print('')
print('3.5、局部加权线性回归,linearRegLwlr函数,无theta解析式!')
print('局部加权线性回归拟合结果图,使用第一列TV数据展示!')
yHat=linearRegLwlr(x,y.T,k=1)
# 绘图
xMat = np.mat(x)
srtIndex = xMat[:,0].argsort(axis=0)
xSort = xMat[srtIndex][:,0,:]
# 绘制散点图
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(xSort[:,0],yHat[srtIndex])
ax.scatter(xMat[:,0].flatten().A[0],np.mat(yHat).flatten().A[0],s=2,c='red') #必须是数组的形式
plt.show()
theta6=linearRegRidge(x,y)
print('')
print('3.6、岭回归,linearRegRidge函数,多组theta解析式!',theta6)
数据见以下链接,复制到txt文档中,另存为CSV格式即可。
数据
参考资料:
1、python实现线性回归
2、机器学习:线性回归与Python代码实现
3、python实现简单线性回归
4、Machine-Learning-With-Python
5、《机器学习》西瓜书,周志华著
6、机器学习视频,邹博
7、 斯坦福大学公开课 :机器学习课程
8、马同学高等数学 如何直观形象的理解方向导数与梯度以及它们之间的关系?
9、【机器学习】线性回归的梯度下降法
10、机器学习 线性回归 梯度下降 python实现
11、《机器学习实战》Peter Harrington著
12、Lasso Regression 作者:Duanxx