機(jī)器學(xué)習(xí)之局部加權(quán)線性回歸

機(jī)器學(xué)習(xí)之局部加權(quán)線性回歸(Locally Weighted Linear Regression)

原文地址:blog.csdn.net/tianse12/article/details/70161591

算法背景:

現(xiàn)實(shí)生活中很多數(shù)據(jù)采用線性模型不能很好的描述,比如說房價(jià)預(yù)測的問題,直線不能很好的擬合所有的數(shù)據(jù)點(diǎn),甚至存在較大的誤差,我們可能采用一條類似于二次函數(shù)的曲線可以擬合的更好。但是為了解決在非線性模型里建立線性模組的問題,我們預(yù)測一點(diǎn)的值時(shí),選擇與這個(gè)點(diǎn)相近的點(diǎn)而不是所有的點(diǎn)做線性回歸。基于此,產(chǎn)生了局部加權(quán)回歸算法。

算法思想:

局部加權(quán)回歸是基于非參數(shù)學(xué)習(xí)算法的思想,使得特征的選擇更好。賦予預(yù)測點(diǎn)附近每一個(gè)點(diǎn)以一定的權(quán)值,在這上面基于波長函數(shù)來進(jìn)行普通的線性回歸.可以實(shí)現(xiàn)對(duì)臨近點(diǎn)的精確擬合同時(shí)忽略那些距離較遠(yuǎn)的點(diǎn)的貢獻(xiàn),即近點(diǎn)的權(quán)值大,遠(yuǎn)點(diǎn)的權(quán)值小,k為波長參數(shù),控制了權(quán)值隨距離下降的速度,越大下降的越快。越小越精確并且太小可能出現(xiàn)過擬合的問題。

普通的線性回歸函數(shù)使用的最小二乘法,即cost函數(shù)是

要使得J(Θ)最小化,求得線性回歸參數(shù)

加入局部加權(quán)算法,cost函數(shù)變成了加權(quán)的cost函數(shù),如下面的形式

其中w(i)是權(quán)重

同樣可以求得線性回歸參數(shù)Θ為下面的形式

在使用這個(gè)算法訓(xùn)練數(shù)據(jù)時(shí),我們需要學(xué)習(xí)兩類參數(shù),線性回歸的參數(shù)以及波長參數(shù)。

算法的缺點(diǎn)主要在于對(duì)于每一個(gè)需要預(yù)測的點(diǎn),都要重新依據(jù)整個(gè)數(shù)據(jù)集模擬出一個(gè)線性回歸模型出來,使得算法的代價(jià)極高。

代碼實(shí)現(xiàn)Python

#coding=utf-8

#LocallyWeightedLinearRegression.py

#局部加權(quán)線性回歸算法的實(shí)現(xiàn)

#其中線性回歸使用的最小二乘法,因此回歸系數(shù)是 theta = (X.T* W * X).I * X.T *W * Y

from numpy import *

#加載數(shù)據(jù)

def load_data(fileName):

numFeat = len(open(fileName).readline().split(',')) - 1

dataMat = []; labelMat = []

fr = open(fileName)

for line in fr.readlines():

lineArr =[]

curLine = line.strip().split(',')

for i in range(numFeat):

lineArr.append(float(curLine[i]))

dataMat.append(lineArr) #實(shí)際數(shù)據(jù)集

labelMat.append(float(curLine[-1]))#實(shí)際數(shù)據(jù)標(biāo)簽值

return dataMat,labelMat

# 對(duì)某一點(diǎn)計(jì)算估計(jì)值

def lwlr(testPoint, xArr, yArr, k = 1.0):

xMat = mat(xArr); yMat = mat(yArr).T#矩陣化

m = shape(xMat)[0]#取得維度25

weights = mat(eye((m)))#eye生成對(duì)角矩陣,m*m

for i in range(m):

diffMat = testPoint - xMat[i, :]#計(jì)算測試點(diǎn)坐標(biāo)和所有數(shù)據(jù)坐標(biāo)的差值

#計(jì)算權(quán)值 w =exp((-(xi-X)^2)/(2*k*k))

weights[i, i] = exp(diffMat * diffMat.T/(-2.0 * k**2))? ? ? # 計(jì)算權(quán)重對(duì)角矩陣

xTx = xMat.T * (weights * xMat)? ? #對(duì)x值進(jìn)行加權(quán)計(jì)算? ? ? ? ? # 奇異矩陣不能計(jì)算

if linalg.det(xTx) == 0.0:

print('This Matrix is singular, cannot do inverse')

return

#theta = (X.T* W * X).I * X.T *W * Y

theta = xTx.I * (xMat.T * (weights * yMat))? ? ? ? ? ? ? ? ? ? # 計(jì)算回歸系數(shù) ,對(duì)y加權(quán)

return testPoint * theta

# 對(duì)所有點(diǎn)計(jì)算估計(jì)值

def lwlrTest(testArr, xArr, yArr, k = 1.0):

m = shape(testArr)[0]

yHat = zeros(m)#初始化預(yù)測值列表

for i in range(m):

yHat[i] = lwlr(testArr[i], xArr, yArr, k)

return yHat

#coding=utf-8

#測試局部加權(quán)線性回歸算法

import matplotlib.pyplot as plt

import LocallyWeightedLinearRegression as lwlr

from numpy import *

xArr, yArr = lwlr.load_data('ex2.txt')

yHat = lwlr.lwlrTest(xArr, xArr, yArr, 0.1)

xMat = mat(xArr)

strInd = xMat[:, 1].argsort(0)#返回?cái)?shù)據(jù)第二列從小到大的索引值

#xSort = xMat[strInd][:, 0, :]#返回第一列和第二列,根據(jù)上面索引順序取出

xSort = xMat[strInd][:]#返回第一列和第二列,根據(jù)上面索引順序取出,xSort為Xmat的另一個(gè)拷貝

fig = plt.figure()

ax = fig.add_subplot(1, 1, 1)

ax.plot(xSort[:, 1], yHat[strInd])#畫出擬合的線

ax.scatter(xMat[:, 1].flatten().A[0], mat(yArr).T.flatten().A[0], s = 2, c = 'red')#畫出實(shí)際點(diǎn)

plt.show()

結(jié)果演示:

使用k=0.1,數(shù)據(jù)擬合的最好:

使用k=0.01,數(shù)據(jù)存在過擬合的問題:

使用k=1.0,數(shù)據(jù)出現(xiàn)欠擬合的問題:

結(jié)論:當(dāng)K=1.0時(shí),出現(xiàn)了欠擬合的問題,根據(jù)公式,此時(shí)權(quán)重過大,下降太快,計(jì)算點(diǎn)太少,相當(dāng)于所有的數(shù)據(jù)視為等權(quán)重,相當(dāng)于普通的線性回歸模型,當(dāng)k=0.1時(shí)得到了很好的效果,當(dāng)k=0.01時(shí),出現(xiàn)了過擬合的問題,納入了較多的噪音點(diǎn),因此也不屬于好的結(jié)果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容