Machine Learning In Action-Chapter8 線性迴歸

Chapter8 - regression

線性迴歸

找到一個迴歸係數向量w,用y = xw來計算預測結果,問題就是如何運用現有的數據集找到最合適的w,一個常用的方法就是找出誤差最小的w,如果簡單地將誤差加減,則正值和負值會抵消,因此選用平方誤差。


i=1m(yixTiw)2

用矩陣替換掉求和符號即爲
(YXw)T(YXw)

對w求導並令其爲0,得到
2X(YXw)=0Y=Xw

兩邊同時乘以(XTX)1XT ,得到w=(XTX)1XTy

代碼實現

def standRegres(xArr,yArr):
    xMat = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T*xMat
    print xMat.T.shape,xMat.shape
    print xTx.shape
    # 計算行列式,行列式爲0,則逆矩陣不存在
    if linalg.det(xTx) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = xTx.I * (xMat.T*yMat)
    return ws

局部加權線性迴歸

http://blog.csdn.net/hujingshuang/article/details/46274723

目前計算x的預測值,用的是全局的數據,且每個數據的權值一樣,但實際是與x越接近的數據參考價值越大,所以有了局部加權,體現在誤差公式上就是對訓練集中的每個點都乘上一個權值係數,然後求和。權值係數用一個m*m的矩陣來表示,對角線上不爲0.

誤差公式爲

1mw(i,i)(yθTx)2

用矩陣表示爲

J(θ)=[W(YXθ)]T(YXθ)=(YXθ)TWT(YXθ)=(YTθTXT)WT(YXθ)=YTWTYθTXTWTYYTWTXθ+θTXTWTXθ

θ 求偏導並令其爲0:
2XTWTY+2XTWTXθ=0XTWY=XTWXθθ=(XTWX)1XTWY

流程:

1.計算每個訓練點的m*m權值矩陣(只有對角線上不爲0),常用的權值計算公式有高斯核,離點越近的點權值越大,高斯核如下:

w(i,i)=exp(|x(i)x|2k2)

2.對每個需要預測的點都用上述的求θ 公式計算出權值向量,然後與預測的點的特徵向量相乘即可得到預測值,這樣的一個缺點就是對每個預測點都要用到全部數據集來計算一次。
# 對單個點的預測
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


最小二乘法( OLS,ordinary least square)有解的條件是X列滿秩。

https://www.zhihu.com/question/28221429

(其實有時候會看到是不滿足列滿秩或者特徵的相關比較強時,不適合用最小二乘法,不滿足列滿秩就是逆矩陣不存在,那爲什麼相關性較強也不適用呢?相關性較強意味着XTX 很小,甚至趨向於0,那麼逆矩陣就會很大,那麼得到的權值就會很不穩定。簡單地可以理解爲相關性強時,數據就不能提供足夠的信息)

爲什麼?

假設X的大小爲m*n

θ=(XTX)1XTY

有解也就是X^TX有逆矩陣,也就是X^TX滿秩,X^TX的大小爲n*n,如果滿秩的話就是秩爲n。

有以下定理:

嶺迴歸

用最小二乘法最誤差有什麼問題?在計算(XTX)1 的時候,可能不存在,比如特徵數大於樣例數,即列數大於行數,是不可能行滿秩的,也就是上式不可逆。

  • 因此從計算的角度可以加上一個λI 使w=(XTX+λI)1XTY 可以計算。
  • 上面是從運算的角度,有沒有更自然的理解方式呢?

知乎上有個回答介紹了三種理解方式

1.從上述計算的角度回答
2. 從優化問題的角度。

誤差的公式爲mi=1(yixTiw)2+λpj=1w2j ,與普通的最小二乘法計算的誤差不同之處在於後面多了平方和。用矩陣表示爲(YXw)2+λw2 ,對w求導並令爲0得:2(XT(YXw))+2λw=0 ,求得w=(XTX+λI)1XTY .

通過確定λ 的值可以使得在方差和偏差之間達到平衡:隨着λ 的增大,模型方差減小而偏差增大。

方差指的是模型之間的差異,而偏差指的是模型預測值和數據之間的差異。我們需要找到方差和偏差的折中。方差,是形容數據分散程度的,算是“無監督的”,客觀的指標,偏差,形容數據跟我們期望的中心差得有多遠,算是“有監督的”,有人的知識參與的指標。

3.從多變量回歸的變量選擇來說,普通的多元線性迴歸要做的是變量的剔除和篩選,而嶺迴歸是一種shrinkage的方法,就是收縮。

嶺迴歸的迴歸參數有先驗分佈,而最小二乘對參數沒有限制。對參數進行先驗分佈限制,會使得得到的迴歸參數取值不會很病態.

求w的代碼實現:

def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat
    denom = xTx + eye(shape(xMat)[1])*lam
    if linalg.det(denom) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = denom.I * (xMat.T*yMat)
    return ws

#### 在預處理數據的時候要對數據集進行標準化
def ridgeTest(xArr,yArr):
    xMat = mat(xArr); yMat=mat(yArr).T
    yMean = mean(yMat,0)
    yMat = yMat - yMean
    xMeans = mean(xMat,0) # 均值,對每一列求均值
    xVar = var(xMat,0) # 方差
    xMat = (xMat - xMeans)/xVar # 隨機變量標準化
    numTestPts = 30
    wMat = zeros((numTestPts,shape(xMat)[1]))
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat

ridgeTest求了30個不同λ 時的權值向量,每個權值向量有八個值,對應8個特徵的重要性,做出的圖展現的是八條曲線,每條曲線表明當前特徵隨lambda的變化,權值的變化。

Lasso

lasso算法在普通最小二乘法的基礎上增加了一個條件,完整寫的話就是

i=1m(yixTiw)2s.t.j=1p|wj|λ

嶺迴歸可以改寫成
i=1m(yixTiw)2s.t.j=1pw2jλ

可以看出嶺迴歸與lasso只是一個是平方和受限,一個是絕對值和受限。

不同之處就在於當lambda足夠小時,有些權值係數會被迫減到0,有些特徵直接被忽略掉,因此能更好的展示出數據的特點。

但求解上述式子的解時,需要二次規劃,計算複雜,用一種更簡單的算法得到差不多的效果。

前向逐步迴歸

前向逐步算法是一種貪心算法,每一步都儘可能較小誤差,一開始所有的權重設爲1,每一步的決策時對某個權重增加或減小一個很小的值。

流程:

數據標準化,使其分佈滿足0均值和單位方差
在每輪迭代過程中:
    設置當前最小誤差lowestError爲正無窮
    對每個特徵:
        增大或縮小:
            改變一個係數得到一個新的w
            計算新w下的誤差
            如果誤差Error小於當前最小誤差lowestError:設置Wbest等於當前的w
        將w設置爲新的Wbest

python實現:

def stageWise(xArr,yArr,eps=0.01,numIt=100):
    xMat = mat(xArr); yMat=mat(yArr).T
    yMean = mean(yMat,0)
    yMat = yMat - yMean
    xMat = regularize(xMat)
    m,n=shape(xMat)
    ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()
    returnMat = zeros((numIt,n))
    for i in range(numIt):
        #print ws.T
        lowestError = inf;
        for j in range(n):
            for sign in [-1,1]:
                wsTest = ws.copy()
                wsTest[j] += eps*sign
                yTest = xMat*wsTest
                rssE = rssError(yMat.A,yTest.A)
                if rssE < lowestError:
                    lowestError = rssE
                    wsMax = wsTest
        ws = wsMax.copy()
        returnMat[i,:]=ws.T
    return returnMat
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章