線性迴歸與嶺迴歸python程式碼實現
阿新 • • 發佈:2019-01-02
一、標準線性迴歸
線上性迴歸中我們要求的引數為:
所以程式碼實現主要就是實現上式,python程式碼如下:
import numpy as np import pandas as pd import matplotlib.pyplot as plt # implement stand regress def standRegress(xArr,yArr): # 將陣列轉換為矩陣 xMat = np.mat(xArr) yMat = np.mat(yArr) xTx = xMat.T * xMat # 計算xTx的 if np.linalg.det(xTx) == 0.0: print('xTx不能求逆矩陣') return theta = xTx.I * (xMat.T * yMat) yHat = xMat*theta return yHat # import data ex0 = np.loadtxt('ex0.txt',delimiter='\t') # deal with data xArr = [] yArr = [] for data in ex0: # print(data) xTmp = [] yTmp = [] xTmp.append(data[0]) xTmp.append(data[1]) yTmp.append(data[2]) xArr.append(xTmp) yArr.append(yTmp) # print(ex0) # print(xArr[0:2]) print(yArr) # ws = standRegress(xArr,yArr) # print(ws) yHat = standRegress(xArr,yArr) xMat = np.mat(xArr) yMat = np.mat(yArr) # print(yMat.T[0,:].flatten().A[0]) plt.scatter(xMat[:,1].flatten().A[0],yMat.T[0,:].flatten().A[0]) # real data plt.plot(xMat[:,1],yHat,'r-') # predict data plt.show()
執行結果如下:
二、區域性加權線性迴歸
使用區域性加權解出的迴歸係數為:
python程式碼如下:
執行結果如下:import numpy as np import matplotlib.pyplot as plt def lwlr(testPoint,xArr,yArr,k=1.0): xMat = np.mat(xArr) yMat = np.mat(yArr) m = np.shape(xMat)[0] #shape 讀取矩陣的長度 shape[0]獲得矩陣第一維的長度 # print(m) weights = np.mat(np.eye(m)) # 建立對角矩陣 # print(weights) for j in range(m): #next 2 lines create weights matrix diffMat = testPoint - xMat[j,:] #矩陣每行的差 weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2)) # 計算權重 xTx = xMat.T * (weights * xMat) if np.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 = np.shape(testArr)[0] yHat = np.zeros(m) for i in range(m): yHat[i] = lwlr(testArr[i],xArr,yArr,k) return yHat # import data ex0 = np.loadtxt('ex0.txt',delimiter='\t') # deal with data xArr = [] yArr = [] for data in ex0: # print(data) xTmp = [] yTmp = [] xTmp.append(data[0]) xTmp.append(data[1]) yTmp.append(data[2]) xArr.append(xTmp) yArr.append(yTmp) # 對單點估計 # yHat = lwlr(xArr[0],xArr,yArr,1.0) # print(yHat) # 得到所有點的估計 yHat = lwlrTest(xArr,xArr,yArr,0.02) xMat = np.mat(xArr) yMat = np.mat(yArr) # print(xMat) strInd = xMat[:,1].argsort(0) # argsort返回陣列值從小到大排列後各元素對應的索引值 # print(strInd) xSort = xMat[strInd][:,0,:] # 排序 # print(xSort) plt.scatter(xMat[:,1].flatten().A[0],yMat.T[0,:].flatten().A[0]) # real data plt.plot(xSort[:,1],yHat[strInd],'r-') # predict data plt.show()
更改k的值會獲得不同的曲線,k越小,對真實資料擬合的越好(但可能過擬合),k越大,越趨向於標準的線性迴歸。
三、嶺迴歸
嶺迴歸就是在矩陣xTx上增加一項使得矩陣非奇異,從而能夠對其求逆。從上面兩端程式碼我們可以看到,在之前對xTx求逆時都需要先判斷xTx是否可以求逆,而嶺迴歸就是解決這個問題的。嶺迴歸的迴歸係數計算公式為:
實現程式碼如下:
執行結果如圖:import numpy as np import matplotlib.pyplot as plt def ridgeRegres(xMat,yMat,lam=0.2): xTx = xMat.T*xMat denom = xTx + np.eye(np.shape(xMat)[1])*lam if np.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 = np.mat(xArr); yMat=np.mat(yArr).T yMean = np.mean(yMat) # 資料標準化 # print(yMean) yMat = yMat - yMean # print(xMat) #regularize X's xMeans = np.mean(xMat,0) xVar = np.var(xMat,0) xMat = (xMat - xMeans) / xVar #(特徵-均值)/方差 numTestPts = 30 wMat = np.zeros((numTestPts,np.shape(xMat)[1])) for i in range(numTestPts): # 測試不同的lambda取值,獲得係數 ws = ridgeRegres(xMat,yMat,np.exp(i-10)) wMat[i,:]=ws.T return wMat # import data ex0 = np.loadtxt('abalone.txt',delimiter='\t') xArr = ex0[:,0:-1] yArr = ex0[:,-1] # print(xArr,yArr) ridgeWeights = ridgeTest(xArr,yArr) # print(ridgeWeights) plt.plot(ridgeWeights) plt.show()
縱座標為迴歸係數,橫座標為log(lambda),在最左邊,迴歸係數與線性迴歸一致,最右邊係數全部縮減為0.
其中間某部分可以得到最好的預測結果,為了定量進行尋找最佳引數,還需要進行交叉驗證。
以上程式碼python環境均為python3.6
程式碼參考:
《機器學習實戰》
資料取自《機器學習實戰》附帶資料