局部加权线性回归(LWLR)

2019-08-14 17:22:11 浏览数 (1)

线性回归的一个问题是很可能出现欠拟合现象。局部加权线性回归可以解决线性回归中的欠拟合现象。在该算法中,我们对更靠近待预测点的点赋予更高的权重。权重类型可以自由选择,最常用的是使用高斯核:W是一个对角矩阵,其中第i项表达式为

则预测y值的回归系数θ如下:

其中k是需要用户给定的参数,k越小,则远离待预测点的点的权重衰减的越厉害。

绘制上述图表的代码如下:

代码语言:javascript复制
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(0,1,100)
plt.title("不同的k值下的权重分布n假设正预测的点是 x=0.5",fontsize =16)
kList = [0.5, 0.1, 0.01]
for i, k in enumerate(kList):
    plt.subplot(len(kList),1, i 1)
    w = np.exp((0.5-X)**2 /(-2 * k*k))
    plt.plot(X,w, label = "k = %f" % k)
    plt.xlabel("x")
    plt.ylabel("w")
    plt.legend()
    if i ==0:
        plt.title("不同的k值下的权重分布n假设正预测的点是 x=0.5",fontsize =16)
plt.show()

我们还是使用上一篇中用的训练集,预测结果相当好:

局部加权线性回归的完整代码如下:

代码语言:javascript复制
#@author: Peter
from numpy import *
import matplotlib.pyplot as plt
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 lwlr(testPoint,xArr,yArr,k):
    xMat = mat(xArr); yMat = mat(yArr).T
    m = shape(xMat)[0]
    weights = mat(eye((m)))#用单位矩阵初始化对角线矩阵
    for i in range(m):   #next 2 lines create weights matrix
        diffMat = testPoint - xMat[i,:]     #
        weights[i,i] = 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)) #weight
    return testPoint * ws
    
def lwlrTest(testArr,xArr,yArr,k):
    #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)
    return yHat

def rssError(yArr,yHatArr):#平方误差
    #yArr and yHatArr both need to be arrays
    return ((yArr-yHatArr)**2).sum()
    
    
xArr,yArr = loadDataSet("ex0.txt") #训练集
X=mat(xArr)
Y=mat(yArr)
print("Y.shape: ", Y.shape)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(array(xArr)[:,1], yArr,label="raw data")

#虚拟的测试集
n=200
B = linspace(array(xArr)[:,1].min(),array(xArr)[:,1].max(),n).reshape(n,1)
A = ones((n,1))
XTest = bmat("A B")
#print(XTest)
k= 0.02
yHat = lwlrTest(XTest, X, Y ,k) #Y的预测值
ax.plot(array(XTest)[:,1], yHat,color ="r", label="预测值")
plt.xlabel("X")
plt.ylabel("Y")
plt.legend(loc="lower right")
plt.title("局部加权线性回归  k= %fn(Locally Weighted Linear Regression)" % k,fontsize =16)
plt.show()

如果参数k取1.0,则和上一篇的结果类似,欠拟合:

如果参数k取0.005,则会出现过拟合现象——过于贴合原始数据,不能提取有效信息,泛化能力差:

0 人点赞