回歸(二):局部加權線性回歸


前言


回顧一下 回歸(一)中的 標准線性回歸:
step1: 對於訓練集,求系數w,使得
最小
step2: 對於新輸入x,其預測輸出為w*x
從中我們知道,標准線性回歸可能表達能力比較差,出現如圖所示的欠擬合的情況(underfitting):
我們可以通過添加諸如x 2 或sin(x)等特征重新擬合函數來解決這個問題,但是這里討論另一種方法:局部加權回歸(Locally Weighted Linear Regression)

數學表達


它的思想是賦予待預測點附近的點更高的權重,權重隨着距離的增大而縮減——這也就是“局部”和“加權”的由來。
既然要加權,誤差准則就變成了

其中W(大寫)是訓練樣本點的權重。按照這個准則解出的回歸系數w的矩陣表達如下:

現在再考慮“局部”。要實現局部,就要讓權值為關於相距預測點x距離的某個遞減函數。LWLR用“核函數”來實現這一點。高斯核是最常用的核函數:

其中x是查詢點,xi是第i個訓練數據,k是一個需要調節的參數,它控制了訓練點距離查詢點衰減速率,越小,衰減速率越快。


代碼實現


下面參考《機器學習實戰》代碼實現以下這個算法:
     
     
     
             
  1. # -*- coding: utf-8 -*-
  2. """
  3. author: Alan
  4. date:2016/4/3
  5. 局部加權線性回歸,參考《機器學習實戰》
  6. """
  7. from numpy import *
  8. def loadDataSet():
  9. fileName = 'D:\Files\python\Ch08\ex0.txt'
  10. numFeat = len(open(fileName).readline().split('\t'))-1
  11. dataMat = []; labelMat = []
  12. fr = open(fileName)
  13. for line in fr.readlines():
  14. lineArr = []
  15. curLine = line.strip().split('\t')
  16. for i in range(numFeat):
  17. lineArr.append(float(curLine[i]))
  18. dataMat.append(lineArr)
  19. labelMat.append(float(curLine[-1]))
  20. return dataMat, labelMat
  21. def lwlr(testPoint, xArr, yArr, k = 1.0):
  22. '''
  23. the algorithm of lwlr
  24. '''
  25. xMat = mat(xArr); yMat = mat(yArr).T
  26. m = shape(xMat)[0]#樣本個數
  27. weights = mat(eye(m))#單位矩陣,用於存儲權重
  28. for j in range(m):
  29. diffMat = testPoint - xMat[j]
  30. weights[j, j] = exp(diffMat * diffMat.T/(-2.0*k**2))#用高斯核求權重
  31. xTx = xMat.T * (weights * xMat) #括號里面是把樣本乘以對應的權重
  32. if linalg.det(xTx) == 0.0:#計算行列式
  33. print 'This matrix is singular, cannot do inverse!'
  34. return
  35. ws = xTx.I * (xMat.T * (weights * yMat))
  36. return testPoint * ws
  37. def lwlrTest(testArr, xArr, yArr,k):
  38. num = shape(testArr)[0]
  39. yHat = zeros(num)#存儲預測的label
  40. for i in range(num):
  41. yHat[i] = lwlr(testArr[i], xArr, yArr, k)
  42. return yHat
  43. #繪制估計的點和原始點的對比圖
  44. #k控制訓練點距離查詢點的衰減速率,越小,衰減越快
  45. def plotData(k):
  46. xArr, yArr = loadDataSet()
  47. #用lwlr對整個數據集進行估計
  48. yHat = lwlrTest(xArr, xArr, yArr, k )
  49. import matplotlib.pyplot as plt
  50. xMat = mat(xArr)
  51. srtInd = xMat[:, 1].argsort(0)#從小到大排序
  52. xSort = xMat[srtInd][:, 0, :]
  53. #繪制估計出的點構成的曲線
  54. fig = plt.figure()
  55. ax = fig.add_subplot(111)
  56. ax.plot(xSort[:, 1], yHat[srtInd])
  57. #繪制原始點的散點圖
  58. ax.scatter(xMat[:, 1], mat(yArr), s = 2, c = 'red')
  59. plt.show()
其中lwlr()函數是算法的核心實現,plotData()函數是綜合了幾個函數的功能的一個整合函數,並且把原始數據和擬合后的曲線用圖形化顯示,能夠更加直觀的看到算法的擬合效果。傳入 plotData() 三種不同的K值得到的效果如下:
 
 
上圖中的k=1,中圖k=0.01,下圖k=0.003,可以看到圖一依然是欠擬合的;圖二模型已經能夠很好地表達原始數據的變化趨勢和潛在規律;而圖三已經把噪聲點考慮在內了,造成了一定程度上過擬合。

總結


至此,局部加權線性回歸的基本原理和實現方式已經理清楚了,總結一下步驟:
step1:對於需要查詢的輸入x,找到其領域的訓練樣本
step2:對於領域的訓練集賦予更大的權重,求取回歸系數w使得

最小,其中W(i)為權重值

step3:預測輸出:wx

step4:對於新的輸入,重復1-3


從步驟中可以看出,這個算法是一個非參數學習算法 non-parametric learning algorithm),非參數學習算法每次預測值的時候都要重新訓練數據得到新的參數值才能計算預測輸出。算法所需要的計算量根據需要查詢的輸入的數量呈線性增加。


與之對應地,標准線性回歸是一種參數學習算法(parametric learning algorithm), 有固定的(指的是:值的大小是固定)、有限的參數,通過訓練樣本,找到合適的參數后,對於之后未知的輸入,我們可以直接利用這組參數得出其相應的預測輸出。


上面的推導和代碼實現中的LWLR還存在一個很明顯的問題,每次對數據集重新訓練都要使用整個數據集。而事實上,隨着K的變小,遠離查詢點的數據的權重趨近於0。如果可以避免這些重復且對結果沒有影響的計算將會大大減少計算量。所以這里可以像KNN一樣只考慮領域中有限的N個訓練點,實現真正的“局部”,那么誤差准則可以變為:



參考文獻


http://blog.csdn.net/allenalex/article/details/16370245

http://www.cnblogs.com/JiePro/p/MachineLearning_2.html

《機器學習實戰》

《機器學習》Tom M. Mitchell  




 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM