机器学习实战-预测数值型数据:回归
1,用線性回歸找到最佳擬合直線
回歸的目的是預(yù)測(cè)數(shù)值型的目標(biāo)值。
回歸方程(regression equation)主要是求回歸系數(shù),一旦有了回歸系數(shù),在給定輸入,做預(yù)測(cè)就是用回歸系數(shù)乘以輸入值,在將結(jié)果全部加在一起,就得到了預(yù)測(cè)值。(因?yàn)榛貧w系數(shù)是一個(gè)向量,輸入也是向量,這些運(yùn)算就是求出二者的內(nèi)積)
回歸的一般方法:
1)收集數(shù)據(jù):采用任意方法收集數(shù)據(jù)
2)準(zhǔn)備數(shù)據(jù):回歸需要數(shù)值型數(shù)據(jù),標(biāo)稱型數(shù)據(jù)將被轉(zhuǎn)換為二值型數(shù)據(jù)
3)分析數(shù)據(jù),二維圖
4)訓(xùn)練算法:找到回歸系數(shù)
5)測(cè)試算法:使用或者預(yù)測(cè)值和數(shù)據(jù)的擬合度,來分析模型的效果
6)使用算法:使用回歸,在給定的時(shí)候預(yù)測(cè)出一個(gè)數(shù)值
求回歸方程:
假定輸入數(shù)據(jù)存放在矩陣X中,而回歸系數(shù)存放在向量w中。那么對(duì)于給定的數(shù)據(jù),預(yù)測(cè)結(jié)果將會(huì)通過給出。通過x,y數(shù)據(jù)找到回歸系數(shù)向量w,一個(gè)常用的方法是找出誤差最小的w。這里的誤差是指預(yù)測(cè)值和真實(shí)值之間的差值。避免正差值和負(fù)差值之間相互抵消,因此采用平方誤差。
平方誤差可以寫作
用矩陣表示還可以寫作,如果對(duì)w求導(dǎo),得到,令其等于零,解出w
w上方的小標(biāo)記表示,這事當(dāng)前可以估計(jì)出的w的最優(yōu)解,從現(xiàn)有數(shù)據(jù)上估計(jì)出的w可能并不是數(shù)據(jù)中的真實(shí)值,所以這里使用了一個(gè)"帽"符號(hào)來表示是w的一個(gè)最佳估計(jì)。注意:公式中包含,也就是需要對(duì)矩陣求逆,代碼中需要判斷矩陣的逆到底存不存在
另外還可以使用NumPy庫中的矩陣方法,該方法叫OLS,意思是“普通最小二乘法”(ordinary least squares)
from numpy import *#加載數(shù)據(jù) def loadDataSet(fileName): #general function to parse tab -delimited floatsnumFeat = 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#返回回歸系數(shù) def standRegres(xArr,yArr):xMat = mat(xArr); yMat = mat(yArr).TxTx = xMat.T*xMatif linalg.det(xTx) == 0.0:# det判斷行列式print ("This matrix is singular, cannot do inverse")returnws = xTx.I * (xMat.T*yMat)return wsimport matplotlib.pyplot as plt xmat=mat(xarr) ymat=mat(yarr) yhat=xmat*ws fig=plt.figure() ax=fig.add_subplot(111) #a是個(gè)矩陣或者數(shù)組,a.flatten()就是把a(bǔ)降到一維,默認(rèn)是按橫的方向降 # 此時(shí)的a是個(gè)矩陣,降維后還是個(gè)矩陣,矩陣.A(等效于矩陣.getA())變成了數(shù)組,A[0]就是數(shù)組里的第一個(gè)元素 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) plt.savefig("2.png") plt.show()?
幾乎任意數(shù)據(jù)集都可以用上述方法建立模型,但是判斷模型的好壞,可以通過計(jì)算著兩個(gè)序列的相關(guān)系數(shù)來,計(jì)算預(yù)測(cè)值yHat序列和真實(shí)值y序列的匹配程度。
yhatT=yhat.T coef=corrcoef(yhatT,ymat) print(coef)[[1. 0.13653777][0.13653777 1. ]]2,局部加權(quán)線性回歸
線性回歸的一個(gè)問題是有可能出現(xiàn)欠擬合現(xiàn)象,因?yàn)樗蟮氖蔷哂凶钚【秸`差的無偏估計(jì)。
局部加權(quán)線性回歸(Locally weighted linear regression,LWLR)。在該算法中,給每個(gè)待測(cè)點(diǎn)附近的每個(gè)點(diǎn)賦予一定的權(quán)重;然后基于最小均方差來進(jìn)行普通的回歸。
其中w是一個(gè)矩陣,用來給每個(gè)數(shù)據(jù)點(diǎn)賦予權(quán)重
LWLR使用“核”(與支持向量機(jī)中的核類似)來對(duì)附近的點(diǎn)賦予更高的權(quán)重。核的類型可以自由選擇,最常用的核是高斯核,高斯核對(duì)應(yīng)的權(quán)重如下
這樣就構(gòu)建了一個(gè)只含有對(duì)角元素的權(quán)重矩陣,并且點(diǎn)x與x(i)越近,w(i,i)將會(huì)越大()。參數(shù)k,決定了對(duì)附近的點(diǎn)賦予多大的權(quán)重,這也是LWLR時(shí)唯一需要考慮的參數(shù),
import matplotlib.pyplot as pltdef 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): #next 2 lines create weights matrixdiffMat = 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 * wsdef lwlrTest(testArr,xArr,yArr,k=1.0): #loops over all the data points and applies lwlr to each onem = shape(testArr)[0]yHat = zeros(m)for i in range(m):yHat[i] = lwlr(testArr[i],xArr,yArr,k)return yHatxarr,yarr=loadDataSet('ex0.txt') xmat=mat(xarr) ymat=mat(yarr) yhat=lwlrTest(xarr,xarr,yarr,0.01) srcInd=xmat[:,1].argsort(0) xsort=xmat[srcInd][:,0,:] print(xsort) fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xsort[:,1],yhat[srcInd]) ax.scatter(xmat[:,1].flatten().A[0],mat(yarr).T.flatten().A[0],s=2,c='red') plt.show()局部加權(quán)線性回歸也存在一個(gè)問題,即增加了計(jì)算量,因?yàn)樗麑?duì)每個(gè)點(diǎn)做預(yù)測(cè)是都必須使用整個(gè)數(shù)據(jù)集
3,預(yù)測(cè)鮑魚的年齡
使用較小的核將得到較低的誤差,但是不能所有數(shù)據(jù)集都使用最小的核,因?yàn)槭褂米钚〉暮藢⒃斐蛇^擬合,對(duì)新數(shù)據(jù)不一定能達(dá)到最好的預(yù)測(cè)效果。
4,縮減發(fā)來“理解”數(shù)據(jù),
如果數(shù)據(jù)的特征比樣本點(diǎn)還多,就不能使用之前的方法來做預(yù)測(cè)。因?yàn)橛?jì)算的時(shí)候回報(bào)錯(cuò)。特征比樣本點(diǎn)還多(n>m),也就是說輸入數(shù)據(jù)的矩陣X不是滿秩矩陣。非滿秩矩陣在求逆向時(shí)會(huì)出現(xiàn)問題。一般采用嶺回歸和lasso回歸
4.1嶺回歸(ridge regression)
嶺回歸就是在矩陣上加一個(gè)I 求逆,其中矩陣I是mxm的單位矩陣,是用戶定義的一個(gè)數(shù)值,回歸系數(shù)變?yōu)?/p>
嶺回歸最先用來處理特征數(shù)多于樣本數(shù)的情況,現(xiàn)在也用于在估計(jì)中加入偏差,從而得到更好的估計(jì)。通過限制來限制所有w之和,通過引入懲罰性,能夠減少不重要的參數(shù),能更好的理解數(shù)據(jù),這個(gè)技術(shù)叫做縮減(shrinkage)
通過預(yù)測(cè)誤差最小化得到。通過選取不同的來重復(fù)上述測(cè)試過程,最終得到一個(gè)是測(cè)試誤差最小的
import matplotlib.pyplot as plt#嶺回歸 def ridgeRegres(xMat,yMat,lam=0.2):xTx = xMat.T*xMatdenom = xTx + eye(shape(xMat)[1])*lamif linalg.det(denom) == 0.0:print("This matrix is singular, cannot do inverse")returnws = denom.I * (xMat.T*yMat)return wsdef ridgeTest(xArr,yArr):xMat = mat(xArr); yMat=mat(yArr).TyMean = mean(yMat,0)yMat = yMat - yMean #to eliminate X0 take mean off of Y#regularize X'sxMeans = mean(xMat,0) #calc mean then subtract it offxVar = var(xMat,0) #calc variance of Xi then divide by itxMat = (xMat - xMeans)/xVar #特征數(shù)據(jù)標(biāo)準(zhǔn)化處理 numTestPts = 30wMat = zeros((numTestPts,shape(xMat)[1]))for i in range(numTestPts):ws = ridgeRegres(xMat,yMat,exp(i-10))wMat[i,:]=ws.Treturn wMatabx,aby=loadDataSet('abalone.txt') ridgeweights=ridgeTest(abx,aby) fig=plt.figure() ax=fig.add_subplot(111) ax.plot(ridgeweights) plt.show()4.2 lasso回歸
增加如下約束時(shí),普通的最小二乘法回歸會(huì)得到與嶺回歸的一樣的公式:
使用普通的最小二乘法回歸在當(dāng)兩個(gè)或更多的特征相關(guān)時(shí),可能會(huì)得出一個(gè)很大的正系數(shù)和一個(gè)很大的負(fù)系數(shù)。正是因?yàn)榇思s束條件存在,使用嶺回歸可以避免此問題。
與嶺回歸類似,另一個(gè)縮減方法lasso也對(duì)回歸系數(shù)做了限定,對(duì)應(yīng)的約束條件
此處約束條件使用絕對(duì)值取代了平方和。當(dāng)足夠小的時(shí)候,一些系數(shù)會(huì)因此被迫縮減到0,這個(gè)特性可以幫我們更好的理解數(shù)據(jù)。
4.3前向逐步回歸
一種貪心算法,即每一步都盡可能減少誤差。一開始所有權(quán)重都等于1,然后每一步所做的決策是對(duì)某個(gè)權(quán)重增加或減少一個(gè)很小的值。
''' 數(shù)據(jù)標(biāo)準(zhǔn)化,使其分布滿足0均值和單位方差 在每輪跌倒過程中:設(shè)置當(dāng)前最小誤差lowestError為正無窮對(duì)每個(gè)特征:增大或縮小:改變一個(gè)系數(shù)得到一個(gè)新的w計(jì)算新w下的誤差如果誤差Error小于當(dāng)前最小誤差lowestError:設(shè)置wbest等于當(dāng)前的w將w設(shè)置為新的wbest ''' def regularize(xMat):#regularize by columnsinMat = xMat.copy()inMeans = mean(inMat,0) #calc mean then subtract it offinVar = var(inMat,0) #calc variance of Xi then divide by itinMat = (inMat - inMeans)/inVarreturn inMat#逐步線性回歸算法的實(shí)現(xiàn),與lasso做法相似單計(jì)算簡單 def stageWise(xArr,yArr,eps=0.01,numIt=100):xMat = mat(xArr); yMat=mat(yArr).TyMean = mean(yMat,0)yMat = yMat - yMean #can also regularize ys but will get smaller coefxMat = regularize(xMat)m,n=shape(xMat)#returnMat = zeros((numIt,n)) #testing code removews = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()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*signyTest = xMat*wsTestrssE = rssError(yMat.A,yTest.A)if rssE < lowestError:lowestError = rssEwsMax = wsTestws = wsMax.copy()stagedata2=stageWise(abx,aby,0.001,5000)xmat=mat(abx) ymat=mat(aby).T xmat=regularize(xmat) ym=mean(ymat,0) ymat=ymat-ym weights=standRegres(xmat,ymat.T) print(weights.T)... [[ 0.044 -0.011 0.12 0.022 2.023 -0.963 -0.105 0.187]] [[ 0.0430442 -0.02274163 0.13214087 0.02075182 2.22403814 -0.99895312-0.11725427 0.16622915]]可以看到進(jìn)過5000次迭代后,逐步線性回歸算法與常規(guī)的最小二乘法效果類似。該算法主要優(yōu)點(diǎn)可以找出重要的特征,這樣就可能及時(shí)停止對(duì)那些不重要特征的收集。
5,權(quán)衡偏差和方差
模型和測(cè)量之間存在差異,就出現(xiàn)了誤差。對(duì)復(fù)雜的過程進(jìn)行簡化,這將導(dǎo)致差異的發(fā)生。
一般采用降低核大小和采用縮減法。縮減法通過吧一些特征的回歸系數(shù)縮減到0,同時(shí)也就減少了模型的復(fù)雜度。
6,實(shí)例:預(yù)測(cè)樂高玩具套裝的價(jià)格
用回歸法預(yù)測(cè)樂高套裝的價(jià)格:
1)收集數(shù)據(jù):任何方式
2)準(zhǔn)備數(shù)據(jù):從返回的JSON中抽取價(jià)格
3)分析數(shù)據(jù):可視化并觀察數(shù)據(jù)
4)訓(xùn)練算法:構(gòu)建不同的模型,采用逐步線性回歸和直接的線性回歸模型
5)測(cè)試算法:使用交叉驗(yàn)證來測(cè)試不同的模型,分析哪個(gè)效果最好
6)使用算法:這次練習(xí)的目標(biāo)就是生產(chǎn)數(shù)據(jù)模型
6.1收集數(shù)據(jù),
from time import sleep import json import urllib def searchForSet(retX, retY, setNum, yr, numPce, origPrc):sleep(10) #防止短時(shí)間內(nèi)有過多的api調(diào)用myAPIstr = 'AIzaSyD2cR2KFyx12hXu6PFU-wrWot3NXvko8vY'searchURL = 'https://www.googleapis.com/shopping/search/v1/public/products?key=%s&country=US&q=lego+%d&alt=json' % (myAPIstr, setNum)pg = urllib.request.urlopen(searchURL)retDict = json.loads(pg.read()) #打開和解析操作for i in range(len(retDict['items'])):try:currItem = retDict['items'][i]if currItem['product']['condition'] == 'new':newFlag = 1else: newFlag = 0listOfInv = currItem['product']['inventories']for item in listOfInv:sellingPrice = item['price']#信息過濾可以采用貝葉斯來判斷,此處使用剪短的啟發(fā)式if sellingPrice > origPrc * 0.5: print("%d\t%d\t%d\t%f\t%f" % (yr,numPce,newFlag,origPrc, sellingPrice))retX.append([yr, numPce, newFlag, origPrc])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, 269.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)2,訓(xùn)練算法:建立模型
使用 standRegres ,在新數(shù)據(jù)集上進(jìn)行回歸處理拿到ws,得到公式
#交叉驗(yàn)證測(cè)試回歸 def crossValidation(xArr,yArr,numVal=10):m = len(yArr) indexList = range(m)errorMat = zeros((numVal,30))#create error mat 30columns numVal rowsfor i in range(numVal):trainX=[]; trainY=[]testX = []; testY = []random.shuffle(indexList) #對(duì)數(shù)據(jù)進(jìn)行混洗for j in range(m):#create training set based on first 90% of values in indexListif j < m*0.9: trainX.append(xArr[indexList[j]])trainY.append(yArr[indexList[j]])else:testX.append(xArr[indexList[j]])testY.append(yArr[indexList[j]])wMat = ridgeTest(trainX,trainY) #get 30 weight vectors from ridgefor k in range(30):#loop over all of the ridge estimatesmatTestX = mat(testX); matTrainX=mat(trainX)meanTrain = mean(matTrainX,0)varTrain = var(matTrainX,0)matTestX = (matTestX-meanTrain)/varTrain #regularize test with training paramsyEst = matTestX * mat(wMat[k,:]).T + mean(trainY)#test ridge results and storeerrorMat[i,k]=rssError(yEst.T.A,array(testY))#保存每個(gè)λ對(duì)應(yīng)的多個(gè)誤差值#print errorMat[i,k]meanErrors = mean(errorMat,0)#calc avg performance of the different ridge weight vectorsminMean = float(min(meanErrors))bestWeights = wMat[nonzero(meanErrors==minMean)]#can unregularize to get model#when we regularized we wrote Xreg = (x-meanX)/var(x)#we can now write in terms of x not Xreg: x*w/var(x) - meanX/var(x) +meanYxMat = mat(xArr); yMat=mat(yArr).TmeanX = mean(xMat,0); varX = var(xMat,0)unReg = bestWeights/varXprint("the best model from Ridge Regression is:\n",unReg)print ("with constant term: ",-1*sum(multiply(meanX,unReg)) + mean(yMat))通過交叉驗(yàn)證落后得到的的回歸系數(shù),存在大小不一,如果在特征很多的情況下,可以方便的選擇出那些特征是關(guān)鍵的,那些特征是不重要的。
7,總結(jié)
回歸與分類不同,分類預(yù)測(cè)離散型變量,回歸預(yù)測(cè)連續(xù)性變量。求特征對(duì)應(yīng)的最佳回歸系數(shù)的方法是最小化誤差的平方和。前提是的逆存在。數(shù)據(jù)集上計(jì)算的回歸方程不一定是最佳的,可以使用預(yù)測(cè)yhat和原始值y,的相關(guān)性來度量回歸方程的好壞。
當(dāng)樣本數(shù)比特征數(shù)還少的時(shí)候,的逆不能直接計(jì)算,可以考慮是用嶺回歸,
嶺回歸是縮減法的一種,相當(dāng)于對(duì)回歸系數(shù)的大小做了限制。另一種鎖甲你發(fā)是lasso,lasso難以求解,可以考慮使用簡單的逐步線性回歸來求得近似結(jié)果
縮減法可以看成是對(duì)一個(gè)模型增加編差的同時(shí)減少方差。偏差方差折中是一個(gè)重要的概念
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的机器学习实战-预测数值型数据:回归的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模拟器什么的都过时了!这样玩吃鸡才能真正
- 下一篇: 感应熔炼设备市场现状及未来发展趋势分析