歡迎關注哈希大數據微信公眾號【哈希大數據】
在之前我們介紹了直接使用線性回歸進行波士頓房價的預測,但是預測準確率僅有60%左右。預測準確率不高一方面是我們未對數據進行一定的預處理(包括歸一化和標準化等),這樣不能確保在使用優化方式時,對不同特征參數起到同樣的影響。 其次是未深入挖掘數據特征間關系,比如當原始數據某些特征與目標值不具有線性關系時,不應當納入訓練模型中。而且數據特征之間可能存在共線性等其他問題,不完全適合使用線性回歸模型進行擬合。
因此,本節我們將介紹Ridge Regression(嶺回歸)和Lasso Regression(拉索回歸),進行波士頓房價數據集中的特征選取和共線性問題的處理,從而更加準確的構建模型實現房價預測。
算法理論介紹
機器學習機制回顧
在之前Linear Regression普通線性回歸的應用中(忘記的小伙伴可拉到文末查看線性回歸詳情內容),我們的輸入數據是具有13個特征屬性的波士頓房價數據集。
回歸模型的構建就是實現這13個特征屬性值的線性加權之和,用于與實際的房價進行擬合。
image
然后通過機器學習功能來訓練數據集進而獲取該模型的參數也就是每個特征屬性之前的權值系數(即權值a的確定)。
機器學習是如何得到權值呢?是通過定義的一個損失函數,實現將訓練數據代入我們模型的預測房價和真實房價的差的平方,然后再將這些平方求和,即普通最小二乘法。
image
因此求權值a的問題,就成了損失函數求和的最小化的最優化問題。
通過一定的理論推導可以得知權值系數實際為(特征屬性值的廣義逆):
image
而且普通的線性回歸算法可以直接訓練得到該結果進而實現對房價的預測。
但是,直接使用普通的線性回歸模型,當訓練樣本數量過少,甚至少于樣本維數(僅有12條房屋數據),這樣將導致特征數據矩陣無法求逆,則不能完成參數a的估計;其次如果樣本特征中存在大量相似的特征(即樣本屬性之間存在共線性關系),將會導致很多權重所代表的意義重復,使原本簡單高效的模型復雜化。
因此希望可以對參數a的計算時提供某種約束(增加一個懲罰因子),只保留具有共線性的一個特征屬性值,而實現特征數據的縮減同時解決過擬合的問題,嶺回歸和拉索回歸恰好可以解決該問題。
下面來詳細了解一下嶺回歸和拉索回歸的相關理論和python實現。
嶺回歸 Ridge
在出現普通線性回歸無法解決的問題時,可以在原來加一個小擾動值λI
image
,其中I為對角矩陣
image
,可以對特征屬性的權重計算進行一定約束,形象的稱加入的對角矩陣I為嶺。當λ越大,懲罰約束作用就越大,而原始數據對回歸求取參數的作用就會減小,λ為0時也就是普通的線性回歸算法。如果給λ指定一個合適的值,就能在一定意義上解決過擬合的問題(原先過擬合的特別大或者特別小的參數會被約束到正常取值但不會為零)。可以通過多次調試尋找較優的λ值,也就是當λ調整到獲取的參數值穩定時即可。
因此嶺回歸可以初步解決特征權值參數a的動態調整(普通線性回歸是無偏估計的唯一值),進而緩解過擬合的問題(盡可能找到不同 特征與目標值的具體關系)。
拉索回歸 Lasso
嶺回歸可以動態調整特征屬性的權重參數,進而使得模型更加契合實際情況,充分解釋不同特征對目標值的影響力,但是其只能將具有線性相關的相似特征屬性的權重降低卻不能完全剔除。
拉索回歸與嶺回歸類似也是加入了一個擾動項,其使用的懲罰項對角矩陣而是可以實現特征選擇的收縮懲罰性:
image
,可以保證當λ充分大時可以把某些特征屬性的權重精確地收縮到0,也就是在模型中剔除了該特征屬性,從而從大量特征數據中挑選出。該方法的兩大好處:一方面剔除噪聲特征(也就是房價不受其影響的特征),其次可以消除具有線性相關關系的不同屬性(會造成模型的不穩定,原因在之后做具體介紹)。
除此以外,嶺回歸中的約束因子λ需要手動調試,而在拉索回歸算法中,可以實現λ參數的交叉驗證,而尋找使得誤差最小的λ的取值,使用交叉檢驗的訓練方法可以進一步提高模型的科學性和準確性。
python實現
Ridge python
同樣使用scikit-learn庫中的包實現該算法,嶺回歸算法實現的部分代碼如下:
from sklearn.linear_model import Ridge
嶺回歸模型的導入
ridge = Ridge(alpha=float(‘{}’.format(i))).fit(house_price_train_X,house_price_train_y)# 默認的lamda的參數為i
嶺回歸模型訓練的準確率
predict_result_ridge = ridge.predict(house_price_test_X)
predict_result_ridge1 = ridge.score(house_price_train_X, house_price_train_y)
predict_result_ridge0 = ridge.score(house_price_test_X, house_price_test_y)
print(‘嶺回歸懲罰參數為 {} ,訓練集的準確率:’.format(i),predict_result_ridge1)
print(‘嶺回歸懲罰參數為 {} ,測試集的準確率:’.format(i), predict_result_ridge0)
Lasso python
普通拉索回歸算法實現的部分代碼如下:
普通拉索回歸模型的導入
from sklearn.linear_model import Lasso
lasso = Lasso(alpha=np.float(‘{}’.format(i)) ,max_iter=1000000).fit(house_price_train_X, house_price_train_y) # 默認的lamda的參數為i
拉索模型訓練的準確率
predict_result_lasso = lasso.predict(house_price_test_X)
predict_result_lasso1 = lasso.score(house_price_train_X, house_price_train_y)
predict_result_lasso0 = lasso.score(house_price_test_X, house_price_test_y)
print(‘拉索回歸懲罰參數為 {} ,訓練集的準確率:’.format(i), predict_result_lasso1)
print(‘拉索回歸懲罰參數為 {} ,測試集的準確率:’.format(i), predict_result_lasso0)
print(‘拉索回歸懲罰參數為 {},使用的特征屬性有:{}’.format(i,np.sum(lasso.coef_ != 0))
交叉驗證的拉索回歸算法實現的部分代碼如下:
實現交叉檢驗拉索回歸模型的導入
from sklearn.linear_model import LassoCV
lasso_cv = LassoCV(alphas=np.logspace(-3,1,2,50) ,max_iter=1000000).fit(house_price_train_X, house_price_train_y) # 默認的lamda的參數為i
交叉檢驗拉索模型訓練的準確率
predict_result_lasso_cv = lasso_cv.predict(house_price_test_X)
predict_result_lasso_cv1 = lasso_cv.score(house_price_train_X, house_price_train_y)
predict_result_lasso_cv0 = lasso_cv.score(house_price_test_X, house_price_test_y)
print(‘交叉檢驗拉索回歸 訓練集的準確率:’, predict_result_lasso_cv1)
print(‘交叉檢驗拉索回歸 測試集的準確率:’, predict_result_lasso_cv0)
image.png
預測對比結果
1、當設置懲罰參數為0時會提示建議使用回歸模型。2、當懲罰參數不同時,lasso算法選數據特征屬性個數是不同的。3、如果懲罰參數設置過大,則無法進行預測。4、也因數據自身特征,三種方式的預測準確率相差不大。可以提示我們在訓練不同數據時,要針對性的選用不同模型。(源碼請直接通過給后臺發消息獲取哦!)