机器学习之局部加权、岭回归和前向逐步回归
回歸是對(duì)一個(gè)或多個(gè)自變量和因變量之間的關(guān)系進(jìn)行建模,求解的一種統(tǒng)計(jì)方法,之前的博客中總結(jié)了在線(xiàn)性回歸中使用最小二乘法推導(dǎo)最優(yōu)參數(shù)的過(guò)程和logistic回歸,接下來(lái)將對(duì)最小二乘法、局部加權(quán)回歸、嶺回歸和前向逐步回歸算法進(jìn)行依次說(shuō)明和總結(jié)
1. 用線(xiàn)性回歸找到最佳擬合曲線(xiàn)
(1)回歸的一般方法
收集數(shù)據(jù):采用任意方法收集數(shù)據(jù)
準(zhǔn)備數(shù)據(jù):回歸需要數(shù)值型數(shù)據(jù),標(biāo)稱(chēng)型數(shù)據(jù)將被轉(zhuǎn)成數(shù)值型數(shù)據(jù)
分析數(shù)據(jù):繪出數(shù)據(jù)的可視化二維圖將有助于對(duì)數(shù)據(jù)做出理解和分析,在采用縮減法求得新回歸系數(shù)之后,可以將新擬合線(xiàn)繪在圖上作為對(duì)比
訓(xùn)練算法:找到回歸系數(shù)
測(cè)試算法:使用R2或者預(yù)測(cè)值和數(shù)據(jù)的擬合度,來(lái)分析模型的效果
使用算法:使用回歸,可以在給定輸入的時(shí)候預(yù)測(cè)出一個(gè)數(shù)值,這是對(duì)分類(lèi)方法的提升,因?yàn)檫@樣可以預(yù)測(cè)連續(xù)性數(shù)據(jù)而不僅僅是離散的類(lèi)別標(biāo)簽
(2)需求
對(duì)dataset/ex0.txt文件中的數(shù)據(jù)集采用線(xiàn)性回歸找到最擬合直線(xiàn),數(shù)據(jù)集:https://github.com/lizoo6zhi/MachineLearn.samples/tree/master/dataset
(3)繪制數(shù)據(jù)的可視化二維圖
(4)通過(guò)最小二乘法得到最優(yōu)參數(shù)
前面我們已經(jīng)推導(dǎo)過(guò)使用最小二乘法求最優(yōu)參數(shù):
代碼實(shí)現(xiàn):
def stand_regres(dataset,label):"""標(biāo)準(zhǔn)線(xiàn)性回歸函數(shù)dataset:listlabel:list"""X = np.mat(dataset)Y = np.mat(label).Ttemp = X.T * Xif np.linalg.det(temp) == 0.0: #計(jì)算行式的值print("X.T*X沒(méi)有逆矩陣")return else:temp = temp.I * X.T * Yreturn temp注意上面代碼中紅色標(biāo)記處,通過(guò)計(jì)算行列式的值判斷X.T*X是否有逆矩陣
(5)通過(guò)計(jì)算出的最優(yōu)參數(shù)對(duì)樣本進(jìn)行回歸測(cè)試,并繪制擬合曲線(xiàn)
def plot_stand_regress(dataset,label,ws,ax):"""繪制數(shù)據(jù)集和擬合曲線(xiàn)"""dataset_matrix = np.mat(dataset)x = dataset_matrix[:,1]y = labelcal_y = dataset * wsax.scatter(x.T.getA(),y,s=10,c='red')ax.plot(x,cal_y)(6)在python中,NumPy庫(kù)提供了相關(guān)系數(shù)的計(jì)算方法,可以通過(guò)corrcoef(yEstimate,yActual)來(lái)計(jì)算預(yù)測(cè)值與真實(shí)值的相關(guān)性
print(np.corrcoef(cal_y.T,np.mat(y)))從上圖可以看出,預(yù)測(cè)值與真實(shí)值之間的相關(guān)系數(shù)為0.98647356
最佳擬合直線(xiàn)方法將數(shù)據(jù)視為直線(xiàn)進(jìn)行建模,具有十分不錯(cuò)的效果,但若是數(shù)據(jù)的離散程度很大呢,那該怎么辦?
2. 局部加權(quán)線(xiàn)性回歸
我們現(xiàn)實(shí)生活中的很多數(shù)據(jù)不一定都能用線(xiàn)性模型描述。比如房?jī)r(jià)問(wèn)題,很明顯直線(xiàn)非但不能很好的擬合所有數(shù)據(jù)點(diǎn),而且誤差非常大,但是一條類(lèi)似二次函數(shù)的曲線(xiàn)卻能擬合地很好。為了解決非線(xiàn)性模型建立線(xiàn)性模型的問(wèn)題,我們預(yù)測(cè)一個(gè)點(diǎn)的值時(shí),對(duì)這個(gè)點(diǎn)附近的點(diǎn)設(shè)置權(quán)值。基于這個(gè)思想,便產(chǎn)生了局部加權(quán)線(xiàn)性回歸算法。在這個(gè)算法中,其他離一個(gè)點(diǎn)越近,權(quán)重越大,對(duì)回歸系數(shù)的貢獻(xiàn)就越多。損失函數(shù)如下:
其中w(i)是權(quán)重,它根據(jù)要預(yù)測(cè)的點(diǎn)與數(shù)據(jù)集中的點(diǎn)的距離來(lái)為數(shù)據(jù)集中的點(diǎn)賦權(quán)值,當(dāng)某點(diǎn)離要預(yù)測(cè)的點(diǎn)越遠(yuǎn),其權(quán)重越小,否則越大。一個(gè)比較好的權(quán)重函數(shù)如下:
?
該函數(shù)稱(chēng)為指數(shù)衰減函數(shù),其中k為波長(zhǎng)參數(shù),它控制了權(quán)值隨距離下降的速率,該函數(shù)形式上類(lèi)似高斯分布(正態(tài)分布),但并沒(méi)有任何高斯分布的意義。該算法解出回歸系數(shù)如下:
注:局部加權(quán)線(xiàn)性回歸中的上述內(nèi)容摘抄自https://blog.csdn.net/herosofearth/article/details/51969517,非常感謝作者分享!
(1)需求
使用局部加權(quán)線(xiàn)性回歸對(duì)dataset/ex0.txt文件中的數(shù)據(jù)集進(jìn)行曲線(xiàn)擬合
(2)實(shí)現(xiàn)
def lwrw(test_point, xarray, yarray, k = 1.0):"""局部加權(quán)回歸函數(shù)(locally weighted linear regression)dataset:listlabel:list"""mat_x = np.mat(xarray)mat_y = np.mat(yarray).Trow,col = np.shape(mat_x) weights = np.mat(np.eye(row))for i in range(row):diffmat = test_point - mat_x[i,:]weights[i,i] = np.exp((diffmat*diffmat.T)/(-2.0*k*k))temp = mat_x.T * weights * mat_xif np.linalg.det(temp) == 0.0:print("mat_x.T * weights * X沒(méi)有逆矩陣")return else:temp = temp.I * mat_x.T * weights * mat_yreturn test_point*temp(3)測(cè)試
分別設(shè)置k為0.01和0.003,當(dāng)k=1時(shí)擬合效果和最小二乘法擬合效果一樣
def plot_lwrw_regress(dataset,label,cal_y_list,ax):"""繪制數(shù)據(jù)集和擬合曲線(xiàn)"""dataset_matrix = np.mat(dataset)x = dataset_matrix[:,1]y = labelax.scatter(x.T.getA(),y,s=10,c='red')#對(duì)dataset進(jìn)行排序sorted_index = x.argsort(0)sorted_x = dataset_matrix[sorted_index][:,0,:] #關(guān)鍵ax.plot(sorted_x[:,1],cal_y_list[sorted_index])if __name__ == "__main__":dataset,label = load_dataset('dataset/ex0.txt')fig = plt.figure()#當(dāng)k為0.01時(shí)for row in range(rows):cal_y = lwrw(dataset[row],dataset,label,0.01)x_y_map[row] = cal_yax = fig.add_subplot(323)ax.text(0.05,4.2,'k=0.01')plot_lwrw_regress(dataset,label,x_y_map,ax)#當(dāng)k為0.003for row in range(rows):cal_y = lwrw(dataset[row],dataset,label,0.003)x_y_map[row] = cal_yax = fig.add_subplot(325)ax.text(0.05,4.2,'k=0.003')plot_lwrw_regress(dataset,label,x_y_map,ax)plt.show()效果:
大家可以通過(guò)不同的k系數(shù)測(cè)試效果,局部加權(quán)線(xiàn)性回歸存在一個(gè)問(wèn)題就是增加了計(jì)算量,因?yàn)樗鼘?duì)每個(gè)點(diǎn)做預(yù)測(cè)時(shí)都必須使用整個(gè)數(shù)據(jù)集
3. 嶺回歸
思考下,如果數(shù)據(jù)的特征比樣本還多應(yīng)該怎么辦?是否還可以使用線(xiàn)性回歸和之前的方法來(lái)做預(yù)測(cè)?
答案是否定的,即不能再使用前面介紹的方法,這是因?yàn)樵谟?jì)算(X.T*X)的逆矩陣的時(shí)候會(huì)出錯(cuò)
有逆矩陣的矩陣一定是方正,但方正不一定有逆矩陣,只有方正的行列式不為0時(shí)才有逆矩陣
為了解決整個(gè)問(wèn)題,統(tǒng)計(jì)學(xué)家引入了嶺回歸(ridge regression)的概念,簡(jiǎn)單的說(shuō),嶺回歸就是在X.T * X上加一個(gè)λI使得矩陣非奇異,進(jìn)而確保(X.T * X + λI)一定可逆,其中I為m*m的單位矩陣,λ是用戶(hù)定義的一個(gè)數(shù)值,我們可以通過(guò)測(cè)試使用不同的λ參數(shù)來(lái)確定最優(yōu)λ
嶺回歸與多項(xiàng)式回歸唯一的不同在于代價(jià)函數(shù)上的差別。嶺回歸的代價(jià)函數(shù)如下:
為了方便計(jì)算導(dǎo)數(shù),通常也寫(xiě)成下面的形式:
上式中的w是長(zhǎng)度為n的向量,不包括截距項(xiàng)的系數(shù)θ0;θθ是長(zhǎng)度為n+1的向量,包括截距項(xiàng)的系數(shù)θ0;m為樣本數(shù);n為特征數(shù)
嶺回歸的代價(jià)函數(shù)仍然是一個(gè)凸函數(shù),因此可以利用梯度等于0的方式求得全局最優(yōu)解(正規(guī)方程):
(1)需求
通過(guò)可視化圖形描述λ與回歸系數(shù)之間的關(guān)系
(2)實(shí)現(xiàn)
通過(guò)以e為底的指數(shù)函數(shù)設(shè)置λ的值,如:exp(i-10),i為[0,30],同公式計(jì)算不同λ下回歸系數(shù)的變化
(3)代碼
def ridge_regres(xarray,yarray,lam=0.2):"""嶺回歸處理當(dāng)特征比樣本點(diǎn)還多,也酒水說(shuō)輸入數(shù)據(jù)的矩陣X不是滿(mǎn)秩矩陣,非滿(mǎn)秩矩陣在求逆時(shí)會(huì)出現(xiàn)問(wèn)題w = (X.T*X + rI).I * X.T * Y"""xmat = np.mat(xarray)ymat = np.mat(yarray).Txtx = xmat.T * xmatdenom = xtx + np.eye(np.shape(xmat)[1])*lamif np.linalg.det(denom) == 0.0:print('denom 沒(méi)有逆矩陣')ws = denom.I * xmat.T * ymatreturn wsdef ridge_test(xarray,yarray,ax):xmat = np.mat(xarray)row,col = np.shape(xmat)ymat = np.mat(yarray)xmean,xvar = data_normalize(xarray) #對(duì)數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理np.seterr(divide='ignore',invalid='ignore')xmat = (xmat - xmean) / xvarnum_test_pts = 30wmat = np.ones((num_test_pts,col))lam_list = []for i in range(num_test_pts):lam = np.exp(i-10)lam_list.append(i-10)ws = ridge_regres(xarray,yarray,lam)wmat[i,:] = ws.T#繪制不同lam情況下參數(shù)變化情況for j in range(np.shape(wmat)[1]):ax.plot(lam_list,wmat[:,j])效果:
x軸為i的取值,y軸為回歸系數(shù)值,從圖可以看出當(dāng)λ非常小時(shí),系數(shù)和普通回歸一樣,當(dāng)λ非常大時(shí),所有回歸系數(shù)都縮減為0,因此,我們可以在中間某處找到是的預(yù)測(cè)的結(jié)果最好的λ值
以下為λ=0.02的效果圖
這樣我們可以結(jié)合局部加權(quán)和嶺回歸計(jì)算最優(yōu)回歸系數(shù),還有其他一些縮減方法,如lasso、LAR、PCA回歸以及子集選擇等,這些方法不僅可以提高預(yù)測(cè)精確率,而且還可以解釋回歸系數(shù),將后續(xù)進(jìn)行總結(jié)
再使用嶺回歸對(duì)數(shù)據(jù)集dataset/abalone.txt測(cè)試,看看回歸系數(shù)變化
4. 前向逐步回歸
前向逐步回歸算法可以得到與lasso差不多的效果,但更加簡(jiǎn)單。前向回歸算法屬于一種貪心算法,即每一步都盡可能減少誤差,一開(kāi)始,所有的權(quán)重都設(shè)為1,然后每一步所作的決策是對(duì)某個(gè)權(quán)重增加或減少一個(gè)很小的值
偽代碼如下:
數(shù)據(jù)標(biāo)準(zhǔn)化,使其分布滿(mǎn)足0均值和單位方差 在每輪迭代過(guò)程中:設(shè)置當(dāng)前最小誤差lowestError為正無(wú)窮對(duì)每個(gè)特征:增大或減少:改變一個(gè)系數(shù)得到一個(gè)新的w計(jì)算新w下的誤差如果誤差error小于當(dāng)前最小誤差:設(shè)置wbest等于當(dāng)前的w將當(dāng)前w設(shè)置為新的wbest(1)需求
使用前向逐步回歸算法,算出最優(yōu)回歸參數(shù),并可視化顯示回歸參數(shù)隨迭代次數(shù)的變化情況,最后標(biāo)準(zhǔn)回歸算法進(jìn)行比較
(2)代碼實(shí)現(xiàn)
def stage_wise(dataset,label,step,numiter=100):"""前向逐步回歸"""xmat = np.mat(dataset)xmean,xvar = data_normalize(dataset) #平均值和標(biāo)準(zhǔn)差ymat = np.mat(label).Tymat = ymat - np.mean(ymat,0)xmat = (xmat - xmean) / xvarm,n = np.shape(xmat)return_mat = np.zeros((numiter,n))ws = np.zeros((n,1))ws_test = ws.copy()ws_max = ws.copy()for iter in range(numiter): #迭代次數(shù)lowest_error = np.inffor j in range(n): #對(duì)每個(gè)特征進(jìn)行變量for sign in [-1,1]:ws_test = ws.copy()ws_test[j] += step*signytest = xmat * ws_testrssE = ((ymat.A-ytest.A)**2).sum()if rssE < lowest_error:lowest_error = rssEws_max = ws_testws = ws_max.copy()return_mat[iter,:] = ws.Treturn return_mat def stage_wise_test(ws_mat,iternum,ax):"""前向逐步回歸算法中回歸系數(shù)隨迭代次數(shù)的變化情況""" x = range(iternum)for i in range(np.shape(ws_mat)[1]):ax.plot(x,ws_mat[:,i])(3)測(cè)試,輸出可視化效果
#前向逐步回歸 ax = fig.add_subplot(326) ws = stage_wise(dataset,label,0.01,500) print("前向逐步回歸經(jīng)過(guò)迭代后的最后回歸系數(shù):",ws[-1,:]) stage_wise_test(ws,500,ax)效果:
上圖表示了回歸系數(shù)隨迭代次數(shù)的變化情況,當(dāng)?shù)?50次時(shí),回歸系數(shù)穩(wěn)定分別為:
(4)接下來(lái)使用標(biāo)準(zhǔn)回歸算法,也就是最小二乘法對(duì)dataset/abalone.txt數(shù)據(jù)集進(jìn)行測(cè)試,計(jì)算回歸系數(shù)
#使用標(biāo)準(zhǔn)回歸對(duì)"dataset/abalone.txt"數(shù)據(jù)集進(jìn)行測(cè)試#對(duì)數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理xman,xvar = data_normalize(dataset)xmat = np.mat(dataset)xmat = (xmat - xman) / xvarymat = np.mat(label)ax = stand_regres(xmat,ymat)print("標(biāo)準(zhǔn)回歸后得到的回歸系數(shù):",ws[-1,:])最終輸出結(jié)果和前向逐步回歸算出系數(shù)一樣:
5. 總結(jié)
與分類(lèi)一樣,回歸也是預(yù)測(cè)目標(biāo)值的過(guò)程,回歸與分類(lèi)的不同點(diǎn)在于,前者預(yù)測(cè)連續(xù)性變量,而后者預(yù)測(cè)離散型變量,回歸是統(tǒng)計(jì)學(xué)中最有力的工具之一,在回歸方程里,求得特征對(duì)應(yīng)的最佳回歸系數(shù)的方法是最小 化誤差的平方和,給定輸入的矩陣X,如果X.T * X的逆存在并可以求得的化,回歸法可以直接使用,數(shù)據(jù)集上計(jì)算出的回歸方程并不一定意味著它是最佳的,可以使用預(yù)測(cè)值yHat和原始值y的相關(guān)性來(lái)度量回歸方程的好壞。
當(dāng)數(shù)據(jù)的樣本數(shù)比特征數(shù)還少的時(shí)候,矩陣X.T * X的逆不能直接計(jì)算,即便當(dāng)樣本數(shù)比特征數(shù)多時(shí),X.T * X的逆仍可能無(wú)法直接計(jì)算,這是因?yàn)樘卣饔锌赡芨叨认嚓P(guān),這時(shí)可以考慮使用嶺回歸,因?yàn)楫?dāng)X.T * X的逆不能計(jì)算時(shí),它仍保證能求得回歸系數(shù)
嶺回歸是縮減法的一種,相當(dāng)于對(duì)回歸系數(shù)的大小施加了限制,另一種很好的縮減法是lasso,lasso難以求解,但可以 使用計(jì)算簡(jiǎn)便的逐步線(xiàn)性回歸方法來(lái)求得近似解
最后來(lái)張綜合圖:
轉(zhuǎn)載于:https://www.cnblogs.com/xiaobingqianrui/p/10260453.html
總結(jié)
以上是生活随笔為你收集整理的机器学习之局部加权、岭回归和前向逐步回归的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java基础【之】JDK环境配置(Win
- 下一篇: node读取文件操作