遞進式講解線性迴歸、區域性加權、嶺迴歸和逐步線性迴歸
一、多變數線性迴歸模型
標準線性迴歸的理論知識很簡單,我們既可以寫出它的標量表達式也可以寫成矩陣的形式,其中矩陣的形式也可以通過投影矩陣進行推到得到。本部分就對標準線性迴歸的表示式進行下簡單的推導。
給定一組資料其中包括特徵矩陣, 目標變數向量:
其中第一列為截距項,我們做線性迴歸是為了得到一個最優迴歸係數向量使得當我們給定一個能夠通過預測的值。其中.
最小二乘法獲取迴歸係數
那麼怎樣的才是最優的呢?在標準線性迴歸中我們需要找到是誤差最小的, 即預測的值與真實的值之間的差值,為了避免簡單累加造成的正負差值相互抵消,這裡採用了平方誤差:
對於上述式子可以通過梯度下降等方法得到最優解。但是使用矩陣表示將會是的求解和程式更為簡單:
將對求導可得:
使其等於0,便可得到:
通過投影矩陣獲取迴歸係數
除了通過最小平方差的方法推導得到的表示式,我們還可以通過投影矩陣(Projection Matrix)來得到。
我們知道如果我們能夠求得一個使得肯定是最好的,但是實際情況中一般並不在矩陣的列空間中,也就是此方程無解,於是我們希望通過將向量投影到的列空間中得到投影矩陣, 然後求解來獲取一個最接近的一個解, 矩陣的投影矩陣形式為
於是得到在列空間的投影為
此時方程是有解的,得到最接近的解為:
這就是傳統意義上的迴歸,簡單明瞭,最小二乘法求解,程式碼求解也是相當簡單
from numpy import* import matplotlib.pyplot as plt def loadDataSet(fileName): #general function to parse tab -delimited floats numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields 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
fileName='E:/ml/machinelearninginaction/Ch08/ex0.txt' dataMat,labelMat=loadDataSet(fileName) ws=standRegres(dataMat,labelMat) xMat=mat(dataMat);yMat=mat(labelMat) fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0]) xcopy=xMat.copy() xcopy.sort(0)#先將x排序,否則畫圖將出現問題 yhat=xcopy*ws ax.plot(xcopy[:,1],yhat) plt.show() corrcoef(yhat.T,yMat)#計算相關係數,求匹配程度
二、多變數區域性加權線性迴歸模型
線性迴歸的一個問題就是欠擬合,將不能取得很好的預測效果。因為它是具有最小均方誤差的無偏估計。解決這個問題的方法就是允許在估計中一些偏差。其中一個非常有效的方法就是區域性加權線性迴歸(LWLR)。
上面的資料點是通過公式新增噪聲生成的資料,而標準的線性迴歸是一種無偏差估計,在計算所有點的時候都是無偏差的計算誤差並通過優化方法優化誤差,如果針對不同的點能夠對誤差進行調整便可以一定程度上避免標準線性迴歸帶來的欠擬合現象。
也就是引入偏差來降低預測的均方誤差,本部分總結下區域性加權線性迴歸的方法。當我們獲取某個的預測值的時候,我們需要計算迴歸係數,但是如果針對樣本中的資料,距離越近我們就給個越大的權重,如果距離越遠就給一個小的權重,這樣就會使得針對的預測值能夠更貼合樣本資料。
當我們需要對資料點相應的目標值進行預測的時候,我們需要給樣本中的每個點賦予一個權重值(為了區分權重和迴歸係數,在這裡用表示迴歸係數,表示權重), 那麼平方誤差的表示式就變成:
通過矩陣可以表示成:
對求導等於0得到:
通過上面的公式,對於任意給定的未知資料可以計算出對應的迴歸係數,並得到相應的預測值, 其中是一個對角矩陣,對角線上的元素對應樣本點的權重值。
使用高斯核來賦值權重
那麼權重的表示式又是怎樣的呢,我們需要距離給定的樣本點的權重越高,LWRL使用核來對附近的點賦予更高的權重,最常用的是高斯核函式,對應表示式如下:
通過公式可以看到如果距離
使用高斯核來賦值權重
那麼權重的表示式又是怎樣的呢,我們需要距離給定的樣本點的權重越高,LWRL使用核來對附近的點賦予更高的權重,最常用的是高斯核函式,對應表示式如下:
通過公式可以看到如果距離的距離越小,就會越大,其中引數決定了權重的大小。越大權重的差距就越小,越小權重的差距就越大,僅有區域性的點參與進迴歸係數的求取,其他距離較遠的權重都趨近於零。如果去進入無窮大,所有的權重都趨近於1,也就近似等於單位矩陣,區域性加權線性迴歸變成標準的無偏差線性迴歸,會造成欠擬合的現象;當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): #next 2 lines create weights matrix 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): #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) return yHat yhat=lwlrTest(xMat,xMat,yMat,k=1.0) strInd=xMat[:,1].argsort(0) xsort=xMat[strInd][:,0,:] fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0]) ax.plot(xsort[:,1],yhat[strInd]) plt.show()