線性模型-區域性加權線性迴歸 機器學習實戰
區域性加權線性迴歸
線性迴歸的一個問題是有可能出現欠擬合,因為它求的是具有最小均方誤差的無偏估計,顯然模型欠擬合將無法做出很好的迴歸預測,所以有些方法允許在估計中引入一些偏差,從而降低預測的均方誤差。區域性線性加權的思想是對待預測點附近的每個點賦予一個權重,然後在帶權的樣本上基於最小均方誤差來進行迴歸.
普通線性迴歸:
區域性加權線性迴歸:
這裡唯一的區別是加入了權重θ,採用之前的最小二乘法求解權數w:
求偏導數:
令導數為0:
加權形式
其中加權的θ是一個矩陣,用來給每個資料點賦予權重,LWLR(Locally Weighted Linear Regression)使用‘核’來對資料點賦予權重,核的型別可以自由選擇,但一般是與距離成反比的函式,常見的是高斯核:
這樣就構造了一個只含對角元素的權重矩陣w,並且點xi與x越接近,θ(i,i)的值越大,當xi與x非常接近時,θ(i,i)的值趨於1,我們再回頭看之前的優化式:
對於一個數據點,與其靠近的點,權重大,與其相距較遠的點,權重小,從而優化問題會有所偏倚,靠近的點對該資料點的迴歸擬合起較大作用,而相距較遠的點由於權數很小,造成的影響基本可以忽略不計,這樣就等同於每個點的迴歸都是基於與其相距較近的點為基礎,而忽略了較遠的點,這也就是區域性加權線性迴歸區域性的由來,因為它著重考慮目標點區域性的資料點為迴歸基礎.
可以看到,加權函式只有一個係數,那就是分母上的K,當K取很小時,exp得到的很多值均趨於0,此時只有很少一部分樣本用於訓練,而當K取很大時,exp的值不會很快趨於0,從而會有一大部分點用於訓練,我們可以通過調整K的值,決定這個‘區域性’的大小究竟是多大.
動手看一下K對資料劃分的影響:
#畫出權數的因素k
def plot_w(k,t_p=0.5):
x = arange(0,1,0.01)
y = exp((x-t_p)**2/(-2*k**2))
plt.plot(x,y)
plt.show()
可以看到,k=0.5時,大部分資料用於迴歸模型,而當k=0.01時,只有非常靠近資料點的資料才會被迴歸模型所採用.
區域性加權迴歸實現
1)讀取資料
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
2)根據加權樣本計算權數W
#區域性加權線性迴歸
def lwlr(testPoint,xArr,yArr,k=1.0):
xMat = mat(xArr); yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye((m)))#初始化一個單位矩陣
for j in range(m):
diffMat = testPoint - xMat[j,:]
weights[j,j] = 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))#根據公式求出權數W
return testPoint * ws
3)得到所有樣本的迴歸預測
#對所有點計算迴歸值
def lwlrTest(testArr,xArr,yArr,k=1.0): #計算所有資料點的預測迴歸值,預設k=1,即完全線性迴歸
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
return yHat
4)迴歸視覺化
#畫出迴歸方程
def plot_w_figure(xArr,yArr,k=1):
yHat = lwlrTest(xArr,xArr,yArr,k)
xMat = mat(xArr)
srtInd = xMat[:,1].argsort(0)#將輸入值x從大到小排序並返回索引
xSort = xMat[srtInd][:,0,:]
# print(xSort.shape)
# print(xSort)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(xSort[:,1],yHat[srtInd])#繪製預測點
ax.scatter(xMat[:,1].flatten().A[0],mat(yArr).T.flatten().A[0],s=2,c='red')#繪製初始資料點
plt.show()
5)主函式
#主函式
if __name__ == '__main__':
xArr,yArr=loadDataSet('ex0.txt')
plot_w_figure(xArr,yArr,k=0.01)
通過設定不同的k值,看看回歸的效果:
可以看到,K=1.0時,加權對樣本基本沒有影響,結果類似於之前的普通線性迴歸,k=0.01時,該模型挖掘出資料的潛在規律,而K=0.003時,引數太小導致模型考慮太多的噪聲,從而過擬合,雖然對樣本資料預測正確率很高,但對於迴歸預測而言,泛化錯誤率會非常大.
總結
可以看到,區域性加權迴歸在選擇到合適的k時,迴歸擬合的效果比普通線性迴歸好很多,但是有一點需要注意,就是區域性線性加權迴歸的計算量很大,因為對於每個資料點,都需要計算與其他資料點的距離矩陣θ,即遍歷整個資料集,因此我們還需要探索更加高效簡介的演算法,減小時間空間開銷.