從 Linear regression (1) 我們知道可以透過 Linear regression 幫我們去預測一個連續的值, 但這樣的 Model 往往會因為 underfit 造成失真. 例如請參考下面兩個 data set, 經過 Linear regression 得到的 weight 會是相同的 [0, 2.0] :
Locally weighted linear regression :
因此我們需要一些額外的訊息來幫我們解決失真的問題, 這邊引入的方法是 "locally weighted linear regression (LWLR)". 其實說白了就是透過左右鄰點來提供資訊, 針對每一點的 weighting 作一些微調. 因此我們計算出來的 weighting 不在是單一值; 原先的公式也稍微變更成下面式子 :
而引入的紅色 W 即是由臨點帶入參考的 weighting, 讓建立出來的 weight matrix 能更貼近 data set 的分布. 下面的函數 lwlr() 可以根據測試點自動建立紅色的 W 矩陣 (weights) 並將計算後預測的連續值返回 :
- 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): #next 2 lines create weights matrix
- 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))
- return testPoint * ws
如果你要一次預測一堆點, 則可以利用下面的方法 :
- def lwlrTest(testArr,xArr,yArr,k=1.0): #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 lwlrWeight(xArr,yArr,k=1.0):
- xMat = mat(xArr); yMat = mat(yArr).T
- def _w(testPoint):
- m = shape(xMat)[0]
- weights = mat(eye((m)))
- for j in range(m): #next 2 lines create weights matrix
- 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))
- return testPoint * ws
- return _w
如果你想觀察預測值形成的線型與 data set 的分布狀況, 可以使用下面函數 :
- def drawLWLRChart(xArr, yArr, lwlrWS):
- xMat = mat(xArr)
- yMat = mat(yArr)
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- ax.scatter(xMat[:,1].flatten().A[0], yMat.T[:,0].flatten().A[0])
- xCopy = xMat.copy()
- xCopy.sort(0)
- yHat = zeros([200,1])
- m = shape(xMat)[0]
- for i in range(m):
- yHat[i][0] = lwlrWS(xCopy[i])
- ax.plot(xCopy[:,1], yHat)
- plt.show()
可以發現跟 Linear regression (1) 得到的結果差不多, 不過你可以藉由調小 k 值得到更貼近 data set 分布的線形 :
沒有留言:
張貼留言