線性回歸的一個問題可能是有可能出現欠擬合(如下圖所示樣本),因為它求的是具有最小均方誤差的無偏估計。如果模型欠擬合將不能取得最好的預測效果。所以有些方法允許在估計中引入一些偏差,從而降低預測的均方誤差。其中的一個方法是局部加權線性回歸。在該算法中,我們給待預測點附近的每一個點賦予一定的權重,在這個子集上基於最小均方差來進行普通的回歸。與KNN類似,這種算法每次預測均需要事先選取出對應的數據子集。該算法解出回歸系數w的形式如下:
$\hat{\omega}=(X^TWX)^{-1}X^TWy$
其中$\omega$是一個矩陣,用來給每個數據點賦予權重。
局部線性加權使用核(類似支持向量機中的核)來對附近的點賦予更高的權重。核的類型可以自由選擇,最常用的核就是高斯核,高斯核對應的權重如下:
$\omega(i,i)=exp\left(\frac{(x_i-x)^2}{-2k^2}\right)$
下圖可以看到對應不同$k$值,高斯核對應的樣本覆蓋范圍。
這樣就構建了一個只含有對角元素的權重矩陣$\omega$,並且點$x$與$x_i$越近,$w(i,i)$將會越大。上述公式包含一個需要用戶指定的參數k,它決定了對附近的點賦予多大的權重,這也是使用局部線性加權回歸時唯一需要考慮的參數,在下圖中可以看到參數$k$與權重的關系。(實際應用中k可以通過K折交叉驗證確定)
1 def lwlr(testPoint, xArr, yArr, k=1.0): 2 xMat = mat(xArr); yMat = mat(yArr).T 3 m = shape(xMat)[0] 4 weights = mat(eye((m))) 5 for j in range(m): 6 diffMat = testPoint - xMat[j, :] 7 weights[j, j] = exp(diffMat * diffMat.T / (-2.0 * k ** 2.0)) 8 xTx = xMat.T * (weights * xMat) 9 if linalg.det(xTx) == 0.0: 10 print("This matrix is singular, cannot do inverse") 11 return 12 ws = xTx.I * (xMat.T * (weights * yMat)) 13 return testPoint * ws 14 15 def lwlrTest(testArr, xArr, yArr, k=1.0): 16 m = shape(testArr)[0] 17 yHat = zeros(m) 18 for i in range(m): 19 yHat[i] = lwlr(testArr[i], xArr, yArr, k) 20 return yHat