机器学习(回归五)——线性回归-局部加权线性回归

前面博客有讲到,样本如果不是线性的可以通过多项式扩展,映射到多维空间来拟合。如此之外,还可以做一个局部加权线性回归(Locally Weighted Linear Regression,LWLR)。
直观图:
在这里插入图片描述

图1

在这里插入图片描述

图2

公式

在该算法中,我们给待预测点附近的每个点赋予一定的权重。与kNN一样,这种算法每次预测均需要事先选取出对应的数据子集。

该算法解出回归系数 w 的形式如下:
w ^ = ( X T W X ) − 1 X T W y \hat{w}=(X^T W X)^{-1}X^T W y w^=(XTWX)1XTWy
其中 w 是一个矩阵,用来给每个数据点赋予权重。

LWLR使用“核”(与支持向量机中的核类似)来对附近的点赋予更高的权重 。核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:
w ( i , i ) = e x p ( ∣ x ( i ) − x ∣ − 2 k 2 ) w(i,i)=exp \left( \frac{|x^{(i)}-x|}{-2k^2} \right) w(i,i)=exp(2k2x(i)x)
这样就构建了一个只含对角元素的权重矩阵 w w w ,该函数称为指数衰减函数。它根据要预测的点与数据集中的点的距离来为数据集中的点赋权值,并且点 x x x x ( i ) x^{(i)} x(i) 越近, w ( i , i ) w(i,i) w(i,i) 将会越大,也就是说,当某点离要预测的点越远,其权重越小,否则越大。上述公式包含一个需要用户指定的参数 k(也叫波长参数) ,它决定了对附近的点赋予多大的权重,可以说是控制了权重值随距离下降的速度,这也是使用LWLR时唯一需要考虑的参数,在下图中可以看到参数 k 与权重的关系:
在这里插入图片描述

图3

每个点的权重图(假定我们正预测的点是 x = 0.5 ),最上面的图是原始数据集,第二个图显示了当 k = 0.5 时,大部分的数据都用于训练回归模型;而最下面的图显示当 k = 0.01 时,仅有很少的局部点被用于训练回归模型

注意:使用该方式主要应用到样本之间的相似性考虑,主要内容在SVM中再考虑(核函数)。

除引之外还有另外一种常用的指数衰减函数:
w ( i , i ) = e x p ( ( x ( i ) − x ) 2 − 2 k 2 ) w(i,i)=exp \left( \frac{ \left(x^{(i)}-x \right)^2 }{-2k^2} \right) w(i,i)=exp(2k2(x(i)x)2)
当然这两种是类似,只不过一个是绝对值,一个是平方的形式。

损失函数

局部加权线性回归的损失函数,与普通线性回归的损失函数平方和损失函数

  • 普通线性回归损失函数
    J ( θ ) = ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(θ)=\sum_{i=1}^m \left( h_θ (x^{(i)})−y^{(i)} \right)^2 J(θ)=i=1m(hθ(x(i))y(i))2
  • 局部加权线性回归损失函数:
    J ( θ ) = ∑ i = 1 m w ( i ) ( h θ ( x ( i ) ) − y ( i ) ) 2 J(θ)=\sum_{i=1}^m w^{(i)} \left( h_θ (x^{(i)})−y^{(i)} \right)^2 J(θ)=i=1mw(i)(hθ(x(i))y(i))2

:以上两个式子同样可以加上正则项

代码实现

from numpy import *
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 = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T * xMat  # 公式步骤
    if linalg.det(xTx) == 0.0:
        print("行列式为0,奇异矩阵,不能做逆")
        return
    ws = xTx.I * (xMat.T * yMat)  # 解线性方程组
    # ws = linalg.solve(xTx,xMat.T*yMat)  # 也可以使用函数来计算 线性方程组
    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)))  # 创建为单位矩阵,再mat转换数据格式     因为后面是与原数据矩阵运算,所以这里是为了后面运算且不带来其他影响
    for j in range(m):  # 利用高斯公式创建权重W     遍历所有数据,给它们一个权重
        diffMat = testPoint - xMat[j, :]  # 高斯核公式1
        weights[j, j] = exp(diffMat * diffMat.T / (-2.0 * k ** 2))  # 高斯核公式2    矩阵*矩阵.T 转行向量为一个值    权重值以指数级衰减
    xTx = xMat.T * (weights * xMat)  # 求回归系数公式1
    if linalg.det(xTx) == 0.0:  # 判断是否有逆矩阵
        print("行列式为0,奇异矩阵,不能做逆")
        return
    ws = xTx.I * (xMat.T * (weights * yMat))  # 求回归系数公式2
    return testPoint * ws

 
# 循环所有点求出所有的预测值
def lwlrTest(testArr, xArr, yArr, k=1.0):  # 传入的k值决定了样本的权重,1和原来一样一条直线,0.01拟合程度不错,0.003纳入太多噪声点过拟合了
    m = shape(testArr)[0]
    yHat = zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i], xArr, yArr, k)  # 返回该条样本的预测目标值
    return yHat


if __name__ == '__main__':
    xArr, yArr = loadDataSet('ex0.txt')
    # 求所有预测值
    yHat = lwlrTest(xArr, xArr, yArr, 0.01)
    print(yHat)
    # 绘制数据点和拟合线(局部加权线性回归)
    xMat = mat(xArr)
    srtInd = xMat[:, 1].argsort(0)  # 画拟合线 需要获得所有横坐标从小到大的下标
    xSort = xMat[srtInd][:, 0, :]  # 获得排序后的数据
     
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(xSort[:, 1], yHat[srtInd], color='red')
    ax.scatter(xMat[:, 1].flatten().A[0], mat(yArr).T.flatten().A[0])
    plt.show()

代码中写的是K=0.01。下图中给出了k在三种不同取值下的结果图。当k = 1.0时权重很大,如同将所有的数据视为等权重,得出的最佳拟合直线与标准的回归一致。使用k = 0.01得到了非常好的效果,抓住了数据的潜在模式。下图使用k = 0.003纳入了太多的噪声点,拟合的直线与数据点过于贴近。所以,图中的最下图是过拟合的一个例子,而最上图则是欠拟合的一个例子。
在这里插入图片描述

图4

使用3种不同平滑值绘出的局部加权线性回归结果。上图中的平滑参数k =1.0,中图k = 0.01,下图k = 0.003。可以看到,k = 1.0时的模型效果与最小二乘法差不多,k = 0.01时该模型可以挖出数据的潜在规律,而k = 0.003时则考虑了太多的噪声,进而导致了过拟合现象

总结

局部加权线性回归也存在一个问题,即增加了计算量,因为它对每个点做预测时都必须使用整个数据集。从上图可以看出,k = 0.01时可以得到很好的估计,但是同时看一下图3中k = 0.01的情况,就会发现大多数据点的权重都接近零。如果避免这些计算将可以减少程序运行时间,从而缓解因计算量增加带来的问题。

最后,把代码中用到的ex0.txt中的数据也放在下面

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
1.000000	0.648270	4.119688
1.000000	0.731209	4.282233
1.000000	0.236833	3.486582
1.000000	0.969788	4.655492
1.000000	0.607492	3.965162
1.000000	0.358622	3.514900
1.000000	0.147846	3.125947
1.000000	0.637820	4.094115
1.000000	0.230372	3.476039
1.000000	0.070237	3.210610
1.000000	0.067154	3.190612
1.000000	0.925577	4.631504
1.000000	0.717733	4.295890
1.000000	0.015371	3.085028
1.000000	0.335070	3.448080
1.000000	0.040486	3.167440
1.000000	0.212575	3.364266
1.000000	0.617218	3.993482
1.000000	0.541196	3.891471
1.000000	0.045353	3.143259
1.000000	0.126762	3.114204
1.000000	0.556486	3.851484
1.000000	0.901144	4.621899
1.000000	0.958476	4.580768
1.000000	0.274561	3.620992
1.000000	0.394396	3.580501
1.000000	0.872480	4.618706
1.000000	0.409932	3.676867
1.000000	0.908969	4.641845
1.000000	0.166819	3.175939
1.000000	0.665016	4.264980
1.000000	0.263727	3.558448
1.000000	0.231214	3.436632
1.000000	0.552928	3.831052
1.000000	0.047744	3.182853
1.000000	0.365746	3.498906
1.000000	0.495002	3.946833
1.000000	0.493466	3.900583
1.000000	0.792101	4.238522
1.000000	0.769660	4.233080
1.000000	0.251821	3.521557
1.000000	0.181951	3.203344
1.000000	0.808177	4.278105
1.000000	0.334116	3.555705
1.000000	0.338630	3.502661
1.000000	0.452584	3.859776
1.000000	0.694770	4.275956
1.000000	0.590902	3.916191
1.000000	0.307928	3.587961
1.000000	0.148364	3.183004
1.000000	0.702180	4.225236
1.000000	0.721544	4.231083
1.000000	0.666886	4.240544
1.000000	0.124931	3.222372
1.000000	0.618286	4.021445
1.000000	0.381086	3.567479
1.000000	0.385643	3.562580
1.000000	0.777175	4.262059
1.000000	0.116089	3.208813
1.000000	0.115487	3.169825
1.000000	0.663510	4.193949
1.000000	0.254884	3.491678
1.000000	0.993888	4.533306
1.000000	0.295434	3.550108
1.000000	0.952523	4.636427
1.000000	0.307047	3.557078
1.000000	0.277261	3.552874
1.000000	0.279101	3.494159
1.000000	0.175724	3.206828
1.000000	0.156383	3.195266
1.000000	0.733165	4.221292
1.000000	0.848142	4.413372
1.000000	0.771184	4.184347
1.000000	0.429492	3.742878
1.000000	0.162176	3.201878
1.000000	0.917064	4.648964
1.000000	0.315044	3.510117
1.000000	0.201473	3.274434
1.000000	0.297038	3.579622
1.000000	0.336647	3.489244
1.000000	0.666109	4.237386
1.000000	0.583888	3.913749
1.000000	0.085031	3.228990
1.000000	0.687006	4.286286
1.000000	0.949655	4.628614
1.000000	0.189912	3.239536
1.000000	0.844027	4.457997
1.000000	0.333288	3.513384
1.000000	0.427035	3.729674
1.000000	0.466369	3.834274
1.000000	0.550659	3.811155
1.000000	0.278213	3.598316
1.000000	0.918769	4.692514
1.000000	0.886555	4.604859
1.000000	0.569488	3.864912
1.000000	0.066379	3.184236
1.000000	0.335751	3.500796
1.000000	0.426863	3.743365
1.000000	0.395746	3.622905
1.000000	0.694221	4.310796
1.000000	0.272760	3.583357
1.000000	0.503495	3.901852
1.000000	0.067119	3.233521
1.000000	0.038326	3.105266
1.000000	0.599122	3.865544
1.000000	0.947054	4.628625
1.000000	0.671279	4.231213
1.000000	0.434811	3.791149
1.000000	0.509381	3.968271
1.000000	0.749442	4.253910
1.000000	0.058014	3.194710
1.000000	0.482978	3.996503
1.000000	0.466776	3.904358
1.000000	0.357767	3.503976
1.000000	0.949123	4.557545
1.000000	0.417320	3.699876
1.000000	0.920461	4.613614
1.000000	0.156433	3.140401
1.000000	0.656662	4.206717
1.000000	0.616418	3.969524
1.000000	0.853428	4.476096
1.000000	0.133295	3.136528
1.000000	0.693007	4.279071
1.000000	0.178449	3.200603
1.000000	0.199526	3.299012
1.000000	0.073224	3.209873
1.000000	0.286515	3.632942
1.000000	0.182026	3.248361
1.000000	0.621523	3.995783
1.000000	0.344584	3.563262
1.000000	0.398556	3.649712
1.000000	0.480369	3.951845
1.000000	0.153350	3.145031
1.000000	0.171846	3.181577
1.000000	0.867082	4.637087
1.000000	0.223855	3.404964
1.000000	0.528301	3.873188
1.000000	0.890192	4.633648
1.000000	0.106352	3.154768
1.000000	0.917886	4.623637
1.000000	0.014855	3.078132
1.000000	0.567682	3.913596
1.000000	0.068854	3.221817
1.000000	0.603535	3.938071
1.000000	0.532050	3.880822
1.000000	0.651362	4.176436
1.000000	0.901225	4.648161
1.000000	0.204337	3.332312
1.000000	0.696081	4.240614
1.000000	0.963924	4.532224
1.000000	0.981390	4.557105
1.000000	0.987911	4.610072
1.000000	0.990947	4.636569
1.000000	0.736021	4.229813
1.000000	0.253574	3.500860
1.000000	0.674722	4.245514
1.000000	0.939368	4.605182
1.000000	0.235419	3.454340
1.000000	0.110521	3.180775
1.000000	0.218023	3.380820
1.000000	0.869778	4.565020
1.000000	0.196830	3.279973
1.000000	0.958178	4.554241
1.000000	0.972673	4.633520
1.000000	0.745797	4.281037
1.000000	0.445674	3.844426
1.000000	0.470557	3.891601
1.000000	0.549236	3.849728
1.000000	0.335691	3.492215
1.000000	0.884739	4.592374
1.000000	0.918916	4.632025
1.000000	0.441815	3.756750
1.000000	0.116598	3.133555
1.000000	0.359274	3.567919
1.000000	0.814811	4.363382
1.000000	0.387125	3.560165
1.000000	0.982243	4.564305
1.000000	0.780880	4.215055
1.000000	0.652565	4.174999
1.000000	0.870030	4.586640
1.000000	0.604755	3.960008
1.000000	0.255212	3.529963
1.000000	0.730546	4.213412
1.000000	0.493829	3.908685
1.000000	0.257017	3.585821
1.000000	0.833735	4.374394
1.000000	0.070095	3.213817
1.000000	0.527070	3.952681
1.000000	0.116163	3.129283

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值