機器學習筆記(7)-迴歸模型

迴歸(Regression)原理

迴歸的目的是預測數值型的目標值。最直接的辦法是依據輸入寫出一個目標值的計算公式。我們應該怎樣從一大堆數據裏求出線性迴歸方程呢? 假定輸入數據存放在矩陣 x 中,而回歸係數存放在向量 w 中。那麼對於給定的數據 X1,預測結果將會通過 Y = X1^T w 給出。現在的問題是,手裏有一些 X 和對應的 y,怎樣才能找到 w 呢?一個常用的方法就是找出使誤差最小的 w 。這裏的誤差是指預測 y 值和真實 y 值之間的差值,使用該誤差的簡單累加將使得正差值和負差值相互抵消,所以我們採用平方誤差。我們需要判斷矩陣X.T*X是否可逆,判斷矩陣的行列式是否爲 0,若爲 0 ,矩陣就不存在逆矩陣,不爲 0 的話,矩陣才存在逆矩陣。
這裏寫圖片描述
最小二乘法(又稱最小平方法):通過最小化誤差的平方和尋找數據的最佳函數匹配。

迴歸代碼實現

數據處理
這裏寫圖片描述

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:
        print "This matrix is singular, cannot do inverse"
        return
    ws = xTx.I * (xMat.T * yMat)
    return ws

畫圖

xArr, yArr = loadDataSet("ex0.txt")
xArr = mat(xArr)          # 第一注意不要傳入列表,第二注意要.A轉換成數組用[0]獲取一維
yArr = mat(yArr)
ws = standRegres(xArr, yArr)
fig = plt.figure()
ax = fig.add_subplot(111)               # add_subplot(349)函數的參數的意思是,將畫布分成3行4列圖像畫在從左到右從上到下第9塊
ax.scatter(xArr[:, 1].flatten().A[0], yArr.T[:, 0].flatten().A[0]) # scatter 的x是xMat中的第二列,y是yMat的第一列
xCopy = xArr.copy()
xCopy.sort(0)  # 注意sort(0)的使用
yHat = xCopy * ws
ax.plot(xCopy[:, 1], yHat)
plt.show()
# 計算預算值和真實值的相關性
>>> corrcoef(yHat.T,yMat)

這裏寫圖片描述

局部加權線性迴歸

線性迴歸的一個問題是有可能出現欠擬合現象,因爲它求的是具有最小均方差的無偏估計。顯而易見,如果模型欠擬合將不能取得最好的預測效果。所以有些方法允許在估計中引入一些偏差,從而降低預測的均方誤差。
一個方法是局部加權線性迴歸(Locally Weighted Linear Regression,LWLR)。在這個算法中,我們給待預測點附近的每個點賦予一定的權重,然後與 線性迴歸 類似,在這個子集上基於最小均方誤差來進行普通的迴歸。
這裏寫圖片描述
LWLR 使用 “核”(與支持向量機中的核類似)來對附近的點賦予更高的權重。核的類型可以自由選擇,最常用的核就是高斯核,高斯覈對應的權重如下:
這裏寫圖片描述
這樣就構建了一個只含對角元素的權重矩陣 w,並且點 x 與 x(i) 越近,w(i, i) 將會越大。上述公式中包含一個需要用戶指定的參數 k,它決定了對附近的點賦予多大的權重。

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))
    return testPoint * ws
def lwlrTest(testArr, xArr, yArr, k=1.0):
    m = shape(testArr)[0]
    yHat = zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i],xArr,yArr,k)
    return yHat
# 可以對單點進行估計
>>> lwlr(xArr(0),xArr,yArr,1.0)
# 得到數據集裏所有點的估計
>>> lwlrTest(xArr,xArr,yArr,0.003)

這裏寫圖片描述

嶺迴歸

如果特徵比樣本點還多(n > m),也就是說輸入數據的矩陣 x 不是滿秩矩陣。非滿秩矩陣求逆時會出現問題。嶺迴歸最先用來處理特徵數多於樣本數的情況,現在也用於在估計中加入偏差,從而得到更好的估計。這裏通過引入 λ 來限制了所有 w 之和,通過引入該懲罰項,能夠減少不重要的參數,這個技術在統計學中也叫作 縮減(shrinkage)。縮減方法可以去掉不重要的參數,因此能更好地理解數據。此外,與簡單的線性迴歸相比,縮減法能取得更好的預測效果。這裏通過預測誤差最小化得到 λ: 數據獲取之後,首先抽一部分數據用於測試,剩餘的作爲訓練集用於訓練參數 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))
    return testPoint * ws
def lwlrTest(testArr, xArr, yArr, k=1.0):
    m = shape(testArr)[0]
    yHat = zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i],xArr,yArr,k)
    return yHat
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章