预测数值型数据:回归源码分析(1)
回歸模型比較簡單,這里先簡單介紹下,后面遇到難點再具體分析。
回歸的一般方法:
(1)收集數據:采用任意方法收集數據。
(2)準備數據:回歸需要數值型數據,標稱型數據將被轉成二值型數據。
(3)分析數據:繪出數據的可視化二維圖將有助于對數據做出理解和分析,在采用縮減法
求得新回歸系數之后,可以將新擬合線繪在圖上作為對比。
(4)訓練算法:找到回歸系數。
(5)測試算法:使用幻或者預測值和數據的擬合度,來分析模型的效果。
(6)使用算法:使用回歸,可以在給定輸入的時候預測出一個數值,這是對分類方法的提
升,因為這樣可以預測連續型數據而不僅僅是離散的類別標簽。
1. 用簡單線性回歸找到最佳擬合直線
# -*- coding: utf-8 -*- """ Created on Wed Oct 25 16:49:50 2017 """ from numpy import * import matplotlib.pyplot as plt# 數據導入函數 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).TxTx = xMat.T*xMat # 計算X'Xif linalg.det(xTx) == 0.0: # 判斷xTX行列式是否為0print "This matrix is singular, cannot do inverse"returnws = xTx.I * (xMat.T*yMat) # 求得當前w的最優估計值return ws# 局部加權線性回歸函數 def lwlr(testPoint,xArr,yArr,k=1.0):xMat = mat(xArr); yMat = mat(yArr).Tm = 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"returnws = xTx.I * (xMat.T * (weights * yMat))return testPoint * ws# 為數據集每個點調用lwlr() def lwlrTest(testArr,xArr,yArr,k=1.0): # testArr,xArr是同一數據列m = shape(testArr)[0] # 得到數據樣本的個數yHat = zeros(m) # 0矩陣用于存儲預測值for i in range(m): # yHat[i] = lwlr(testArr[i],xArr,yArr,k)return yHat# 主函數xArr,yArr=loadDataSet('ex0.txt') ws=standRegres(xArr,yArr) # ws是回歸系數 xMat=mat(xArr) # 是前兩維的數據 yMat=mat(yArr) # 第三維的數據,就是真實值 yHat=xMat*ws # 得到預測輸出的值yHat fig=plt.figure() ax=fig.add_subplot(111) # xMat[:,1].flatten().A[0]得到xMat第二維的數據,yMat.T[:,0].flatten().A[0]是真實值 ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0]) # 創建出原始的數據圖像 xCopy=xMat.copy() # 拷貝 xCopy.sort(0) # 升排序 yHat=xCopy*ws # 得到預測值 ax.plot(xCopy[:,1],yHat,'r') # 畫出擬合直線 plt.show() # 計算相關系數 yHat=xMat*ws print 'Correlation coefficient:',corrcoef(yHat.T,yMat) #numpy庫提供了相關系數的計算方法注意:
這里的回歸系數是用最小化平方誤差得到的,即
w^=(XTX)?1XTy
和代碼中的ws = xTx.I * (xMat.T*yMat)相對應。通過計算兩個序列的相關系數, 可以計算預測值和真實值之間的匹配程度。Numpy庫提供了相關系數的計算方法:通過命令corrcoef(yEstimate,yActual)來計算預測和真實值的相關性。
線性回歸是得到最佳的回歸系數后,再對原始輸入樣本進行預測,此處的回歸系數對于所有的樣本都是一樣的(yHat=xMat*ws),這點不同于局部線性回歸,然后畫出原始數據的散點圖和回歸線。
運行結果:
相關系數:
Correlation coefficient: [[ 1. 0.98647356][ 0.98647356 1. ]]2. 局部加權線性回歸
線性回歸的一個問題是有可能出現欠擬合現象,因為它求的是具有最小均方誤差的無偏估計。顯而易見,如果模型欠擬合將不能取得最好的預測效果。所以有些方法允許在估計中引人一些偏差,從而降低預測的均方誤差。
其中的一個方法是局部加權線性回歸(LWLR)。在該算法中,我們給待預測點附近的每個點賦予一定的權重;然后在這個子集上基于最小均方差來進行普通的回歸。與KNN一樣,這種算法每次預測均需要事先選取出對應的數據子集。該算法解出回歸系數w的形式如下:
w^=(XTWX)?1XTWy
其中W是一個矩陣,用來給每個數據點賦予權重。
LWLR使用“核”(與支持向量機中的核類似)來對附近的點賦予更高的權重。最常用的核就是高斯核,高斯核對應的權重如下:
w(i,j)=exp(|xi?x|?2k2)
這樣就可以得到要預測的點x(i)附近的點的權重值。
把上述的代碼中的主函數改為如下:
# 主函數 xArr,yArr=loadDataSet('ex0.txt') #print 'Weighted prediction:',lwlr(xArr[0],xArr,yArr,1.0) yHat_1=lwlrTest(xArr,xArr,yArr,1.0) yHat_2=lwlrTest(xArr,xArr,yArr,0.01) yHat_3=lwlrTest(xArr,xArr,yArr,0.003) # 對xArr排序 xMat=mat(xArr) # 轉化為矩陣 srtInd=xMat[:,1].argsort(0) # 按升序排列,并返回對應的索引值 xSort=xMat[srtInd][:,0,:] # 得到二維的矩陣,重新升序后得到的矩陣 #xx=xMat[srtInd] # 三維的矩陣 fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xSort[:,1],yHat_1[srtInd]) # 預測值也按相應的坐標 ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0],s=2,c='r') plt.show()fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xSort[:,1],yHat_2[srtInd]) # 預測值也按相應的坐標 ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0],s=2,c='r') plt.show()fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xSort[:,1],yHat_3[srtInd]) # 預測值也按相應的坐標 ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0],s=2,c='r') plt.show()運行結果:
可以看到從左到右的系數k分別為:1.0,0.01,0.003 的擬合效果。
參數k決定了對待測點附近的點賦予多大的權重,控制著權重衰減的速度。
分析:
其中待預測點附近點的權重的代碼:
diffMat*diffMat.T:是每個待測點與樣本的每個點的距離。
weights:是基于每個待測點與全部樣本點進行計算得到的權重對角陣。
return testPoint * ws :返回待測點的預測值,而每個待測點的權重都要基于全部樣本進行計算。
ax.plot(xSort[:,1],yHat_1[srtInd]) :畫出回歸線
ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0],s=2,c='r'):畫出原始數據的散點圖。
要注意的語法:
srtInd=xMat[:,1].argsort(0) # 按升序排列,并返回對應的索引值 xx=xMat[srtInd] # 三維的矩陣 xSort=xMat[srtInd][:,0,:] # 得到二維的矩陣,重新升序后得到的矩陣xMat[索引值][:,0,;]其得到的是:二維的矩陣,而xMat[索引值]得到的是三維的形式,效果如下:
In [21]: xSort Out[21]: matrix([[ 1. , 0.014855],[ 1. , 0.015371],[ 1. , 0.033859],..., [ 1. , 0.990947],[ 1. , 0.993888],[ 1. , 0.995731]])In [22]: xx Out[22]: matrix([[[ 1. , 0.014855]],[[ 1. , 0.015371]],[[ 1. , 0.033859]],..., [[ 1. , 0.990947]],[[ 1. , 0.993888]],[[ 1. , 0.995731]]])In [23]: shape(xx) Out[23]: (200L, 1L, 2L)In [24]: shape(xSort) Out[24]: (200L, 2L)In [25]:3. 預測鮑魚的年齡
添加計算誤差大小的函數,并改變主函數如下:
# 計算預測誤差的大小 def rssError(yArr,yHatArr): # yArr和yHatArr都需要是數組return ((yArr-yHatArr)**2).sum()# 主函數abX,abY=loadDataSet('abalone.txt') yHat01=lwlrTest(abX[0:99],abX[0:99],abY[0:99],0.1) yHat1=lwlrTest(abX[0:99],abX[0:99],abY[0:99],1) yHat10=lwlrTest(abX[0:99],abX[0:99],abY[0:99],10) print 'k=0.1 :',rssError(abY[0:99],yHat01.T) # 不同的核的預測預測誤差結果 print 'k=1 :',rssError(abY[0:99],yHat1.T) print 'k=10 :',rssError(abY[0:99],yHat10.T) # 測試新數據的表現 print 'Forecast new data....' yHat01=lwlrTest(abX[100:199],abX[0:99],abY[0:99],0.1) # 此處的權重計算是基于前100個樣本的,但預測的是另100個 yHat1=lwlrTest(abX[100:199],abX[0:99],abY[0:99],1) yHat10=lwlrTest(abX[100:199],abX[0:99],abY[0:99],10) print 'k=0.1 :',rssError(abY[100:199],yHat01.T) print 'k=1 :',rssError(abY[100:199],yHat1.T) print 'k=10 :',rssError(abY[100:199],yHat10.T) # 和簡單的線性回歸對比 print 'compare to Simple regression:....' ws=standRegres(abX[0:99],abY[0:99]) yHat=mat(abX[100:199])*ws print 'Simple regression:',rssError(abY[100:199],yHat.T.A)運行結果:
k=0.1 : 56.7836322443 k=1 : 429.89056187 k=10 : 549.118170883 Forecast new data.... k=0.1 : 14651.309989 k=1 : 573.52614419 k=10 : 517.571190538 compare to Simple regression.... Simple regression: 518.636315325分析:
- 使用較小的核將得到較低的誤差。那么,為什么不在所有數據集上都使用最小的核呢?這是因為使用最小的核將造成過擬合,對新數據不一定能達到最好的預測效果
- 簡單線性回歸達到了與局部加權線性回歸類似的效果。這也表明一點,必須在未知數據上比較效果才能選取到最佳模型。那么最佳的核大小是10嗎?或許是,但如果想得到更好的效果,應該用10個不同的樣本集做10次測試來比較結果。
- 預測鮑魚的年齡的例子展示了如何使用局部加權線性回歸來構建模型,可以得到比普通線性回歸更好的效果。局部加權線性回歸的問題在于,每次必須在整個數據集上運行。也就是說為了做出預測,必須保存所有的訓練數據。這是其劣勢所在。
總結
以上是生活随笔為你收集整理的预测数值型数据:回归源码分析(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玩具手枪哪里最容易坏
- 下一篇: 地砖(说一说地砖的简介)