1. 程式人生 > >【機器學習實戰-python3】線性迴歸

【機器學習實戰-python3】線性迴歸

本篇將介紹機器學習中的迴歸演算法(主要是線性迴歸)。分類輸出的結果是標稱型的數值(類別值),而回歸預測是結果是一組連續值。簡而言之,迴歸與分類的不同在於其目標變數是連續數值型。
本篇的資料和程式碼參見:https://github.com/stonycat/ML-in-Action

一、線性迴歸擬合直線
迴歸的目的是預測數值型的目標值,最簡單的辦法就是根據輸入的資料返回一個計算目標值的公式,所求的公式即所謂的迴歸方程。如返回一條直線方程,y=wx+b,那麼引數w與b就是迴歸係數,求迴歸係數的過程就是迴歸。迴歸也分線性和非線性,這裡只涉及線性迴歸。
那麼現在給定資料 x,返回迴歸方程 y=wx

y表示預測結果,那麼如何求迴歸係數 w呢?常用的方法就是找出預測y與真實值y的誤差,並最小化誤差,從而求得w。這裡採用的是平方誤差。

i=1m(yixTiw)2用矩陣表示寫做:yXwTyXww求導,令導數等於0,得到w的最優解:w=xT(YXw)=(XTX)1XTy
其中矩陣計算通過python的numpy庫的方法可以解決,X矩陣涉及到一個判斷是否存在逆矩陣的問題。
#coding=utf-8
from numpy import *

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 def standRegres(xArr,yArr): xMat=mat(xArr); yMat=mat(yArr).T xTx=xMat.T*xMat if linalg.det(xTx)==0.0: #矩陣行列式|A|=0,則矩陣不可逆 print("This matrix is singular, cannot do inverse") return ws=xTx.I*(xMat.T*yMat)

這裡寫圖片描述
繪製最佳擬合直線:
這裡寫圖片描述

這裡寫圖片描述
擬合數據點的直線如下圖所示:
這裡寫圖片描述

二、區域性加權線性迴歸(Local Weighted Linear Regression,LWLR)
線性迴歸因為用的是最小均方誤差無偏估計,有可能會出現欠擬合的現象(所以這裡允許在估計中引入一些偏差,降低預測的均方誤差)
其中的一個方法叫做區域性加權線性迴歸,在這個演算法中,我們給待預測點附近的每個點都賦予權重,然後再基於最小均方誤差進行普通迴歸。類似kNN演算法,每計算一點,都需要取出相應的資料子集。與之前的w計算公式不同,這裡引入了kernel函式,採用高斯核。

W=w(i,i)=exp[|x(i)x|2k2]
迴歸係數的計算公式為:w=XTWX1XTWy 資料點x與x(i)越近,W將越大,其中k為使用者指定的引數。
程式碼實現:
#區域性加權線性迴歸 LWLR
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)) #計算高斯核函式W
    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)

k取0.003
這裡寫圖片描述
可以看出繪製的曲線有點過擬合
這裡寫圖片描述

修改k取值為0.01,得到了較好的擬合效果。
這裡寫圖片描述

示例:預測鮑魚年齡

在前面程式碼的基礎上,新增如下程式碼,計算預測的誤差大小。採用區域性加權線性迴歸預測鮑魚年齡。資料儲存在adalone.txt


def rssError(yArr,yHatArr):
    return((yArr-yHatArr)**2).sum()

核函式k取不同值(0.1,1,10)的測試結果
這裡寫圖片描述
可以看出訓練時:這裡較小的核能夠取得最小的誤差。
下面測試不同k值的表現如何:
這裡寫圖片描述
測試結果表明,k=10的時候測試誤差最小,正好和訓練相反。
下面採用普通線性迴歸方法進行測試:
這裡寫圖片描述
發現測試的結果和區域性加權結果類似。這裡表明,只有在未知資料上比較測試效果才能確定最佳模型,目前來看 最佳效果或許就是k=10時,如果想取得更好的效果,應該用10個不同的樣本進行10次測試來比較結果。最後,區域性加權線性迴歸問題在於每次預測必須在整個資料集上執行,(計算距離和權值),因此效率不高。