機器學習實戰之迴歸

一,引言  python

  前面講到的基本都是分類問題,分類問題的目標變量是標稱型數據,或者離散型數據。而回歸的目標變量爲連續型,也便是迴歸對連續型變量作出預測,最直接的辦法是依據輸入寫出一個目標值的計算公式,這樣,對於給定的輸入,利用該公式能夠計算出相應的預測輸出。這個公式稱爲迴歸方程,而求迴歸方程顯然就是求該方程的迴歸係數,而一旦有了這些迴歸係數,再給定輸入,就能夠將這些迴歸係數乘以輸入值,就獲得了預測值。算法

二,線性迴歸json

  線性迴歸,簡單而言,就是將輸入項分別乘以一些常量,再將結果加起來獲得輸出。假設輸入數據存放在矩陣x中,而回歸係數存放在向量w中,那麼對於給定的數據x1,預測結果將會經過y=xTw給出。那麼,如何纔可以找出最佳的迴歸係數向量w呢?api

  很容易想到使用最小化偏差的w,可是這裏的偏差爲預測y值和真實y值的差值,使用該偏差的簡單累加將會出現正差值和負差值的相互抵消,因此,咱們能夠採用平方偏差來進行度量。即:數組

  Σ(yi-xiTW)2,i=1,2,3......N(N爲樣本總數)app

  這樣,用矩陣表示能夠寫成(y-Xw)T(y-Xw).由於要求函數的極小值,再對w求導得,xT(y-Xw),則令其等於0,便可獲得w的最優解:dom

  w*=(XTX)-1XTy函數

  須要注意的是,公式中,出現的求逆運算,而對於任意一個矩陣而言,不必定可逆,因此,咱們在實際寫代碼過程當中,須要事先肯定矩陣是否可逆,不然極可能會形成程序出現嚴重的錯誤。學習

  有了迴歸係數的求解公式,咱們就能夠寫代碼來根據樣本數據擬合出最佳的迴歸係數向量w了:測試

form numpy import *

#解析文件中的數據爲適合機器處理的形式
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.extend(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat

#標準線性迴歸算法
#ws=(X.T*X).I*(X.T*Y)    
def standRegres(xArr,yArr):
    #將列表形式的數據轉爲numpy矩陣形式
    xMat=mat(xArr);yMat=mat(yArr).T
    #求矩陣的內積
    xTx=xMat.T*xMat
    #numpy線性代數庫linalg
    #調用linalg.det()計算矩陣行列式
    #計算矩陣行列式是否爲0
    if linalg.det(xTx)==0.0:
        print('This matrix is singular,cannot do inverse')
        return 
    #若是可逆,根據公式計算迴歸係數
    ws=xTx.I*(xMat.T*yMat)
    #能夠用yHat=xMat*ws計算實際值y的預測值
    #返回歸係數
    return ws

  這裏,須要說明的是,Numpy提供了一個線性代數的庫linalg,其中包含有不少有用的函數,其中就有代碼中用到的計算矩陣行列式值得函數linalg.det(),若是行列式值爲0,則矩陣不可逆,若是不爲0,那麼就能夠順利求出迴歸係數。

  此外,咱們知道線性迴歸的方程的通常形式爲:y=wx+b;即存在必定的偏移量b,因而,咱們能夠將回歸係數和特徵向量均增長一個維度,將函數的偏移值b也算做迴歸係數的一部分,佔據迴歸係數向量中的一個維度,好比w=(w1,w2,...,wN,b)。相應地,將每條數據特徵向量的第一個維度設置爲1.0,即全部特徵向量的第一個維度值均爲1.0,這樣,最後獲得的迴歸函數形式爲y=w[0]+w[1]*x1+...+w[N]*xN.

  經過上面的數據咱們能夠獲得一個擬合的線性迴歸模型,可是咱們還須要驗證該模型的好壞。若是將全部樣本的真實值y保存於一個數列,將全部的預測值yHat保存在另一個數列,那麼咱們能夠經過計算這兩個序列的相關係數,來度量預測值與真實值得匹配程度。咱們能夠經過NumPy庫中提供的corrcoef()函數計算兩個序列的相關性。好比以下代碼能夠獲得真實值和預測值序列的相關性,相關性最好爲1,最差爲0,表示不相關。

#計算預測值序列
yHat=xMat*ws corrcoef(yHat.T,yMat)

三,局部加權線性迴歸

  線性迴歸一個比較容易出現的問題是有可能出現欠擬合現象,欠擬合顯然不能取得最好的預測效果。由於,咱們求的是均方偏差最小的模型,因此能夠在估計中引入一些誤差,從而下降預測的均方偏差,達到誤差和方差的折中,從而找到最佳的模型參數,即迴歸係數。

  解決上述問題的一個方法便是局部加權線性迴歸(LWLR)。即在算法中,爲每個待預測的數據點附近的賦予必定的權重,越靠近預測點的數據點分配的權重越高。這裏,咱們採用高斯核函數爲預測點附近的數據點分配權重,即:

  w(i,i)=exp(|x(i)-x|/-2*k2),其中參數k能夠由用戶本身定義。

  顯然,有上面高斯核函數可知,矩陣W是一個只含對角元素的矩陣。這樣,迴歸係數的解的形式變爲:w*=(xTWx)-1(xTWy)。對上述代碼稍做修改以後獲得以下局部加權線性迴歸函數

#局部加權線性迴歸

#每一個測試點賦予權重係數
#@testPoint:測試點
#@xArr:樣本數據矩陣
#@yArr:樣本對應的原始值
#@k:用戶定義的參數,決定權重的大小,默認1.0
def lwlr(testPoint,xArr,yArr,k=1.0):
    #轉爲矩陣形式
    xMat=mat(xArr);yMat=mat(yArr).T
    #樣本數
    m=shape(xMat)[0]
    #初始化權重矩陣爲m*m的單位陣
    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)
    #計算行列式值是否爲0,即肯定是否可逆
    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列表中
    yHat=zeros(m)
    #遍歷每個測試樣本
    for i in range(m):
        #計算預測值
        yHat[i]=lwlr(testArr[i],xArr,yArr,k)
    return yHat

  須要說明的是,當爲某一預測點附件的數據點分配權重時,由高斯核函數公式可知,與預測點約相近的點分配獲得的權重越大,不然權重將以指數級衰減,與預測點足夠遠的數據點權重接近0,那麼這些數據點將不會在該次預測中起做用。固然,用戶能夠經過本身設定參數k來控制衰減的速度,若是k值較大,衰減速度較慢,這樣就會有更多的數據點共同參與決策;不然,若是參數k很是小,那麼衰減速度極快,參與預測點決策的數據點就不多。因此,咱們在實驗中,應該多選擇幾組不一樣的k值,獲得不一樣的迴歸模型,從而找到最優的迴歸模型對應的k值。

  下圖從上到下,依次是k取1.0,0.01及0.003狀況下,對應的擬合模型。

  圖中,當k=1.0(上圖)時,意味着全部的數據等權重,這樣,擬合結果與普通的線性迴歸擬合結果一致,顯然極可能出現欠擬合狀況。當k=0.01時(中圖),顯然獲得了最好的擬合效果,由於此時掌握了數據的潛在模式,在預測時剔除了部分不重要數據的影響,增大了重要數據的權重。而k=0.003(下圖),能夠看出預測時,歸入了太多的噪聲點,擬合的直線與數據點過於貼近,出現了過擬合的現象。

  此外,局部加權線性迴歸也存在必定的問題,相對於普通的線性迴歸,因爲引入了權重,大大增長了計算量,雖然取得了不錯的擬合效果,但也相應地付出了計算量的代價。咱們發現,在k=0.01時,大多的數據點的權重都接近0,因此,若是咱們能避免這些計算,將必定程度上減小程序運行的時間,從而緩解計算量增長帶來的問題。

四,示例:預測鮑魚的年齡

  接下來,就利用上述算法對真實的數據進行測試,並計算預測的偏差。鮑魚的年齡能夠經過鮑魚殼的層數推算獲得。在運行代碼前,咱們還須要添加計算預測偏差的函數代碼:

#計算平方偏差的和
def rssError(yArr,yHatArr):
    #返回平方偏差和
    return ((yArr-yHatArr)**2).sum()

  固然,爲了獲得更好的效果,咱們有必要採起交叉驗證的方法,選取多個樣本集來進行測試,找出預測偏差最小的迴歸模型。

五,縮減係數"理解"數據的方法

  試想,若是此時數據集樣本的特徵維度大於樣本的數量,此時咱們還能採起上面的線性迴歸方法求出最佳擬合參數麼?顯然不可能,由於當樣本特徵維度大於樣本數時,數據矩陣顯然是非滿秩矩陣,那麼對非滿秩矩陣求逆運算會出現錯誤。

  爲了解決這個問題,科學家提出了嶺迴歸的概念,此外還有一種稱爲"前向逐步迴歸"的算法,該算法能夠取得很好的效果且計算相對容易。

1 嶺迴歸

  簡單而言,嶺迴歸便是在矩陣xTx上加入一個λI從而使得矩陣非奇異,進而能對矩陣xTx+λI求逆。其中矩陣I是一個單位矩陣,即對角線上元素皆爲1,其餘均爲0。這樣,迴歸係數的計算公式變爲:

  w*=(xTx+λI)-1(xTy)

  公式中經過引入該懲罰項,從而減小不重要的參數,更好的理解和利用數據。此外,增長了相關約束:Σwi2<=λ,即迴歸係數向量中每一個參數的平方和不能大於λ,這就避免了當兩個或多個特徵相關時,可能出現很大的正係數和很大的負係數。

  上面的嶺迴歸就是一種縮減方法,經過此方法能夠去掉不重要的參數,更好的理解數據的重要性和非重要性,從而更好的預測數據。

  在嶺迴歸算法中,經過預測偏差最小化來獲得最優的λ值。數據獲取以後,將數據隨機分紅兩部分,一部分用於訓練模型,另外一部分則用於測試預測偏差。爲了找到最優的λ,能夠選擇多個不一樣λ值重複上述測試過程,最終獲得一個使預測偏差最小的λ。

#嶺迴歸
#@xMat:樣本數據
#@yMat:樣本對應的原始值
#@lam:懲罰項係數lamda,默認值爲0.2
def ridgeRegres(xMat,yMat,lam=0.2):
    #計算矩陣內積
    xTx=xMat.T*xMat
    #添加懲罰項,使矩陣xTx變換後可逆
    denom=xTx+eye(shape(xMat)[1])*lam
    #判斷行列式值是否爲0,肯定是否可逆
    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
    #在30個不一樣的lamda下進行測試
    numTestpts=30
    #30次的結果保存在wMat中
    wMat=zeros((numTestpts,shape(xMat)[1]))
    for i in range(numTestpts):
        #計算對應lamda迴歸係數,lamda以指數形式變換
        ws=ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat

  須要說明的幾點以下:

  (1)代碼中用到NumPy庫中的eye()方法來生成單位矩陣。

  (2)代碼中仍保留了判斷行列式是否爲0的代碼,緣由是當λ取值爲0時,又回到了普通的線性迴歸,那麼矩陣極可能出現不可逆的狀況

  (3)嶺迴歸中數據須要進行標準化處理,即數據的每一維度特徵減去相應的特徵均值以後,再除以特徵的方差。

  (4)這裏,選擇了30個不一樣的λ進行測試,而且這裏的λ是按照指數級進行變化,從而能夠看出當λ很是小和很是大的狀況下對結果形成的影響

  下圖示出了迴歸係數與log(λ)之間的關係:

  能夠看出,當λ很是小時,係數與普通迴歸同樣。而λ很是大時,全部迴歸係數縮減爲0。這樣,能夠在中間的某處找到使得預測結果最好的λ。

2 逐步前向迴歸

  逐步前向迴歸是一種貪心算法,即每一步都儘量的減少偏差。從一開始,全部的權重都設爲1,而後每一步所作的決策是對某個權重增長或減小一個較小的數值。算法的僞代碼爲:

數據標準化,使其分佈知足均值爲0,和方差爲1
在每輪的迭代中:
    設置當前最小的偏差爲正無窮
    對每一個特徵:
        增大或減少:
            改變一個係數獲得一個新的w
            計算新w下的偏差
            若是偏差小於當前最小的偏差:設置最小偏差等於當前偏差
            將當前的w設置爲最優的w
    將本次迭代獲得的預測偏差最小的w存入矩陣中
返回屢次迭代下的迴歸係數組成的矩陣
#前向逐步迴歸
#@eps:每次迭代須要調整的步長    
def stageWise(xArr,yArr,eps=0.01,numIt=100):
    xMat=mat(xArr);yMat=mat(yArr)
    yMean=mean(yMat,0)
    yMat=yMat-yMean
    #將特徵標準化處理爲均值爲0,方差爲1
    xMat=regularize(xMat)
    m,n=shape(xMat)
    #將每次迭代中獲得的迴歸係數存入矩陣
    returnMat=zeros((numIt,m))
    ws=zeros((n,1));wsTest=ws.copy();wsMat=ws.copy()
    for i in range(numIt):
        print ws.T
        #初始化最小偏差爲正無窮
        lowestError=inf;
        for j in range(n):
            #對每一個特徵的係數執行增長和減小eps*sign操做
            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
                    wsMat=wsTest
        ws=wsMat.copy()
        returnMat[i,:]=ws
    return returnMat

  下面看一次迭代的算法執行過程,此時學習步長eps=0.01:

  能夠看到,上述結果中w1和w6都是0,這代表了這兩個維度的特徵對預測結果不構成影響,即所謂的不重要特徵。此外,在eps=0.01狀況下,一段時間後係數就已經飽和並在特定值之間來回震盪,這顯然是步長太大的緣故,咱們能夠據此調整較小的步長。

  前向逐步迴歸算法也屬於縮減算法。它主要的優勢是能夠幫助咱們更好地理解現有的模型並做出改進。當構建出一個模型時,能夠運行該算法找出重要的特徵,這樣就可能及時中止對不重要特徵的收集。一樣,在算法測試的過程當中,可使用s折交叉驗證的方法,選擇偏差最小的模型。

  此外,當咱們無論是應用嶺迴歸仍是前向逐步迴歸等縮減算法時,就相應的爲模型增長了誤差,與此同時也就減少了模型的方差。而最優的模型每每是在模型誤差和方差的折中時得到。不然,當模型方差很大誤差很小時模型複雜度很大而出現過擬合現象,而方差很小誤差很大時而容易出現欠擬合現象。所以,權衡模型的誤差和方差能夠作出最好的預測。

六,嶺迴歸應用示例:預測樂高玩具套裝的價格

  咱們知道樂高玩具是一種拼裝類玩具,由不少大小不一樣的塑料插件組成。一種樂高玩具套裝基本上在幾年後就會停產,但樂高收藏者之間仍會在停產後彼此交易。這樣,咱們能夠擬合一個迴歸模型,從而對樂高套裝進行估價。顯然這樣作十分有意義。

算法流程:

1 收集數據:用google shopping的api收集數據

2 準備數據:從返回的json數據中抽取價格

3 分析數據:可視化並觀察數據

4 訓練算法:構建不一樣的模型,採用嶺迴歸和普通線性迴歸訓練模型

5 測試算法:使用交叉驗證來測試不一樣的模型,選擇效果最好的模型

1 收集數據:使用Google 購物的API來獲取玩具套裝的相關信息和價格,能夠經過urllib2發送http請求,API將以JSON格式返回須要的產品信息,python的JSON解析模塊能夠幫助咱們從JSON格式中解析出所須要的數據。收集數據的代碼以下:

#收集數據
#添加時間函數庫
from time import sleep
#添加json庫
import json
#添加urllib2庫
import urllib2
#@retX:樣本玩具特徵矩陣
#@retY:樣本玩具的真實價格
#@setNum:獲取樣本的數量
#@yr:樣本玩具的年份
#@numPce:玩具套裝的零件數
#@origPce:原始價格
def searchForSet(retX,retY,setNum,yr,numPce,origPrc):
    #睡眠十秒
    sleep(10)
    #拼接查詢的url字符串
    myAPIstr='get from code.google.com'
    searchURL='https://www.googleapis.com/shopping/search/v1/public/products?\
        key=%s&country=US&q=lego+%d&alt=json' %(myAPIstr,setNum)
    #利用urllib2訪問url地址
    pg=urllib2.urlopen(searchURL)
    #利用json打開和解析url得到的數據,數據信息存入字典中
    retDict=json.load(pg.read())
    #遍歷數據的每個條目
    for i in range(len(retDict['items'])):
        try:
            #得到當前條目
            currItem=retDict['items'][i]
            #當前條目對應的產品爲新產品
            if currItem['product']['condition']=='new':
                #標記爲新
                newFlag=1
            else:newFlag=0
            #獲得當前目錄產品的庫存列表
            listOfInv=currItem['product']['inventories']
            #遍歷庫存中的每個條目
            for item in listOfInv:
                #獲得該條目玩具商品的價格
                sellingPrice=item['price']
                #價格低於原價的50%視爲不完整套裝
                if sellingPrice>origPrc*0.5print('%d\t%d\t%d\t%f\t%f',%(yr,numPce,newFlag,\
                        origPrc,sellingPrice))
                    #將符合條件套裝信息做爲特徵存入數據矩陣
                    retX.append([yr,numPce,newFlag,origPce])
                    #將對應套裝的出售價格存入矩陣
                    retY.append(sellingPrice)
        except:print('problem with item %d',%i)

#屢次調用收集數據函數,獲取多組不一樣年份,不一樣價格的數據
def setDataCollect(retX,retY):
    searchForSet(retX,retY,8288,2006,800,49.99)
    searchForSet(retX,retY,10030,2002,3096,49.99)
    searchForSet(retX,retY,10179,2007,5195,499.99)
    searchForSet(retX,retY,10181,2007,3428,199.99)
    searchForSet(retX,retY,10189,2008,5922,299.99)
    searchForSet(retX,retY,10196,2009,3263,249.99)

  須要指出的是,咱們在代碼中發送http請求,須要從NumPy導入urllib2模塊;使用json解析得到的數據時須要導入json模塊;同時爲避免多個函數同時訪問網站,在程序開始時先睡眠必定的時間,用於緩衝,即須要調用time模塊的sleep。

  此外,因爲套裝是由多個小插件組成,因此存在插件損失的狀況,因此須要過濾掉這樣的玩具套裝,咱們能夠經過必定的過濾條件(通常套裝有缺失可能有標識,可經過關鍵詞篩選,或者經過貝葉斯估計估計套裝完整性),這裏用的是價格來判斷,若是當前價格不到原始價格的一半,那麼這樣的套裝必然有缺陷,損壞和缺失等。由於,一旦具備收藏價值的玩具套裝停產,必然價格相對上漲,因此出現這種價格反常的狀況代表該產品套裝存在必定的缺陷,能夠將其過濾掉。

2 訓練算法:創建模型

  上面有了數據,那麼咱們就能夠開始完成代碼進行模型訓練了,這裏採用嶺迴歸來訓練模型,而且採用交叉驗證的方法來求出每一個λ對應的測試偏差的均值,最後分析選出預測偏差最小的迴歸模型。

#訓練算法:創建模型
#交叉驗證測試嶺迴歸
#@xArr:從網站中得到的玩具套裝樣本數據
#@yArr:樣本對應的出售價格
#@numVal:交叉驗證次數
def crossValidation(xArr,yArr,numVal=10):
    #m,n=shape(xArr)
    #xArr1=mat(ones((m,n+1)))
    #xArr1[:,1:n+1]=mat(xArr)
    #獲取樣本數
    m=len(yArr)
    indexList=range(m)
    #將每一個迴歸係數對應的偏差存入矩陣
    errorMat=zeros((numVal,30))
    #進行10折交叉驗證
    for i in range(numVal):
        trainX=[];trainY=[]
        testX=[];testY=[]
        #混洗索引列表
        random.shuffle(indexList)
        #遍歷每一個樣本
        for j in range(m):
            #數據集90%做爲訓練集
            if j<m*0.9:
                trainX.append(xArr1[indexList[j]])
                trainY.append(yArr[indexList[j]])
            #剩餘10%做爲測試集
            else:
                testX.append(xArr1[indexList[j]])
                testY.append(yArr[indexList[j]])
        #利用訓練集計算嶺迴歸係數
        wMat=ridgeRegres(trainX,trainY)
        #對於每個驗證模型的30組迴歸係數
        for k in range(30):
            #轉爲矩陣形式
            matTestX=mat(testX);matTrainX=mat(trainX)
            #求訓練集特徵的均值
            meanTrain=mean(matTrainX,0)
            #計算訓練集特徵的方差
            varTrain=val(matTrainX,0)
            #嶺迴歸須要對數據特徵進行標準化處理
            #測試集用與訓練集相同的參數進行標準化
            matTestX=(matTestX-meanTrain)/varTrain
            #對每組迴歸係數計算測試集的預測值
            yEst=matTestX*mat(wMat[k,:]).T+mean(trainY)
            #將原始值和預測值的偏差保存
            errorMat[i,k]=rssError(yEst.T.A,array(testY))
    #對偏差矩陣中每一個lamda對應的10次交叉驗證的偏差結果求均值
    meanErrors=mean(errorMat,0)
    #找到最小的均值偏差
    minMean=float(min(meanErrors))
    #將均值偏差最小的lamda對應的迴歸係數做爲最佳迴歸係數
    bestWeigths=wMat[nonzero(meanErrors==minMean)]
    xMat=mat(xArr);yMat=mat(yArr).T
    meanX=mean(xMat,0);valX=val(xMat,0)
    #數據標準化還原操做
    unReg=bestWeigths/valX
    print('the best model from Ridge Regression is :\n',unReg)
    print('with constant term :',-1*sum(multiply(meanX,unReg))+mean(yMat))

  一樣,這裏須要說明的有如下幾點:

  (1) 這裏對於數據集採用隨機的方式(random.shffle())選取訓練集和測試集,訓練集佔數據總數的90%,測試集剩餘的10%。採起這種方式的緣由是,便於咱們進行屢次交叉驗證,獲得不一樣的訓練集和測試集.

  (2) 咱們知道嶺迴歸中會選取多個不一樣的λ值,來找到預測偏差最小的模型;此外,算法中採用交叉驗證的方法,因此對於每個λ對應着多個測試偏差值,因此在分析預測效果最好的λ以前,須要先對每一個λ對應的多個偏差求取均值。

  (3) 咱們呢知道嶺迴歸算法須要對訓練集數據的每一維特徵進行標準化處理,那麼爲保證結果的準確性,也須要對測試集進行和訓練集相同的標準化操做,即測試集數據特徵減去訓練集該維度特徵均值,再除以訓練集該維度特徵方差

  (4) 由於採用嶺迴歸算法時,對數據進行了標準化處理,而標準的迴歸算法則沒有,因此在代碼最後咱們仍是須要將數據進行還原,這樣便於分析比較兩者的真實數據的預測偏差。

  

  由實驗結果獲得迴歸方程:

  上面模型可能仍是不易理解,再看一下具體的縮減過程當中係數的變化狀況:

     最後獲得的迴歸係數是通過不一樣程度的衰減獲得的。好比上圖中第一行第四項比第二項係數大5倍,比第一項大57倍。依次來看,第四特徵能夠看作是最重要特徵,在預測時起最主要做用,其次就是第二特徵。也便是,特徵對應的係數值越大,那麼其對預測的決定做用也就越大;若是某一維度係數值爲0,則代表該特徵在預測結果中不起做用,能夠被視爲不重要特徵。

  因此,這種縮減的分析方法仍是比較有用的,由於運算這些算法能夠幫助咱們充分理解和挖掘大量數據中的內在規律。當特徵數較少時可能效果不夠明顯,而當特徵數至關大時,咱們就能夠據此瞭解特徵中哪些特徵是關鍵的,哪些是不重要的,這就爲咱們節省很多成本和損耗。

7,總結

 (1) 迴歸與分類的區別,前者預測連續型變量,後者預測離散型變量;迴歸中求最佳係數的方法經常使用的是最小化偏差的平方和;若是xTx可逆,那麼迴歸算法可使用;能夠經過預測值和原始值的相關係數來度量回歸方程的好壞

  (2) 當特徵數大於樣本總數時,爲解決xTx不可逆的問題,咱們能夠經過引入嶺迴歸來保證可以求得迴歸係數

  (3) 另一種縮減算法是,前向逐步迴歸算法,它是一種貪心算法,每一步經過修改某一維度特徵方法來減少預測偏差,最後經過屢次迭代的方法找到最小偏差對應的模型

  (4) 縮減法能夠看作是對一個模型增長誤差的同時減小方差,經過誤差方差折中的方法,能夠幫助咱們理解模型並進行改進,從而獲得更好的預測結果

相關文章
相關標籤/搜索