Kaggle實戰之一回歸問題


 

0. 前言

1.任務描述

  • 預測任務:根據某時刻房價相關數據,預測區域內該時刻任一街區的平均房價,決定是否對投資該街區的房子。
  • 評估函數:RMSE

評估函數:RMSE即損失函數,范數越大,越注重預測值誤差大的樣例

  • 工具:ipython notebook

2.數據概覽

整體概況

用 python 的pandas包導入樣本數據,查看前五行,每一行表示一個街區,包含十項數據特征:

經度 維度 房齡 房間數 卧室數 人口數 家庭數 收入 房價 臨海
-122.23 37.88 41 880 129 322 126 8.3252 452600 NEAR BAY
-122.22 37.86 21 7099 1106 2401 1138 8.3014 358500 NEAR BAY
-122.24 37.85 52 1467 190 496 177 7.2574 352100 NEAR BAY
-122.25 37.85 52 1274 235 558 219 5.6431 341300 NEAR BAY
-122.25 37.85 52 1627 280 565 259 3.8462 342200 NEAR BAY

其中房價一列實際是此次任務的 label, 查看數據基本情況:


   RangeIndex: 20640 entries, 0 to 20639

Data columns (total 10 columns):
longitude             20640 non-null float64
latitude              20640 non-null float64
housing_median_age    20640 non-null float64
total_rooms           20640 non-null float64
total_bedrooms        20433 non-null float64
population            20640 non-null float64
households            20640 non-null float64
median_income         20640 non-null float64
median_house_value    20640 non-null float64
ocean_proximity       20640 non-null object
dtypes: float64(9), object(1)

可以看到一共有 20640 行記錄,注意到其中 total_rooms 屬性有207行缺失,ocean_proximity 屬性是 object 類型,查看該屬性的統計情況:


<1H OCEAN     9136
INLAND        6551
NEAR OCEAN    2658
NEAR BAY      2290
ISLAND           5

對9項數值型屬性畫直方圖,感受下每個屬性的分布情況:

可以看到 housing_median_age、median_house_value、median_income 有明顯的翹尾情況,說明這三個屬性在數據收集階段,做過被截斷處理。median_house_value 作為此次任務的預測目標值,它的截斷處理在實際情況中可能是個問題,因為它意味着你模型的預測值可能無法超過這個上限。上圖還可以看出有四項屬性屬於“長尾分布”的情況,一般來說,機器學習的模型更喜歡類似正態分布的“鍾型”特征。

可視化

人腦非常擅長圖像視覺的信息處理。用經度緯度確定地理位置,用圓圈大小表示人口數量,用熱力圖表示房價高低,再從外部導入一張經緯度吻合的地圖,可以得到一張可視化的數據圖:

可以看到海景房房價普遍偏高,但是北部區域是個例外,說明臨海距離應該是個很好的特征。另外,人口聚集地中心區域,房價也相應偏高,是不是做聚類之后,計算到聚類中心的距離也是一個很好的特征呢?

相關性計算

相關性既包括特征與label的相關性,也包括特征之間的相關性。首先看特征與 label 之間的皮爾遜系數:

median_income         0.687160
total_rooms           0.135097
housing_median_age    0.114110
households            0.064506
total_bedrooms        0.047689
population           -0.026920
longitude            -0.047432
latitude             -0.142724
 

觀察房價與收入的二維圖:

總體上,房價與收入具有很強的相關性,收入越高,該地區的房價也越高。但是也有一些收入較高,但是房價很低,或者收入較低,房價奇高的點,可能是異常點,需要從訓練數據中去除。

3. 數據准備

隨機采樣

測試集從數據集中分離而來,大小一般設置為全部數據的20%。分離的辦法可以隨機取,有點是采樣均勻,缺點是每次取出的測試集可能不一樣。要克服這個缺點,在隨機取的時候,可以固定隨機數種子。其他的方法還有根據某列屬性的尾號或者 md5 來划分,優點是每次運行的測試集是固定的,確定是要確保尾號或者 md5 數值是均勻分布的,並且與 label 不存在相關性。在工業界,上線算法ab分桶時,常常也用類似的方法,比如按照用戶id尾號分流、按照用戶id的md5分流等,特別要注意未登錄用戶的分桶情況,因為未登錄用戶與點擊率是有相關性的。

分組按比例隨機采樣

隨機產生測試集,可能有的一個弊端是,重要屬性的部分區間可能丟失。舉個極端的例子,在所有分類模型中,label是最重要的屬性,假設100個樣本中只有2個正樣本,則有很大概率訓練樣本全部是負樣本。這個任務中,median_income 屬性是決定房價的一個重要特征,在直方圖中,可以看到收入大於7.5的樣本已經比較稀疏了。如果完全按照隨機采樣方法產生訓練樣本和測試樣本,有可能訓練樣本中完全不包含收入大於7.5的樣本,這對於模型訓練是很不利的。

解決的方法很簡單,將 median_income 進行分組,每組里面按照0.2的比例抽取測試樣本。分組的時候,注意每組里面樣本數量不能太少,可以參考如下處理方法:

 group = ceil(min(median\_income,7.5) / 1.5)

將 median_income 分為5組,每組按比例采樣,這樣處理的結果是,測試樣本在 median_income 的分布,比當做整體(一組)完全隨機采樣的方法,更符合整體分布。

數據預處理

  • 空值處理:數據清洗包括,total_rooms 用中位數代替,ocean_proximity 用one-hot-encode編碼轉為數值型,one-hot-encode與直接編碼為 [0,1,2,3..] 相比,不會引入相似或者相近的意義。比如 2 和 3 在數值上相近,但是它們各自表示的NEAR BAY與INLAND屬性項並不存在實質的相似關系(盡管有這個可能)。
  • 構造特征:數據集里因為不同district里戶數不同,所以 total_rooms、total_bedrooms、population 這些屬性可能沒有太大的意義,而每戶的房間數、卧室數、人數相關性則較,所有在數據集中可以新增這些特征。
  • 歸一化:數值型特征的一個特點是,不同的屬性取值范圍差別極大,對模型學習、正則項設置不利。有兩種簡單的方法可以應對這種情況:變換到0-1區間的歸一化或者標准正態分布。前者對異常點非常敏感,如果存在某個值比正常值區間距離很遠,這種處理會導致正常數據點分布過於集中;后者對過於集中的數據分布敏感,如果原數據集方差很小,除以近0的數值容易導致精度失真。
  • 偏度處理:在大部分數值型特征中,通常分布不符合正態分布,而是類似於“長尾”。例如房價中,低價占大部分,豪宅屬於小部分。應對這種數據分布,一般可以通過神奇的log化處理轉化類近似正態分布。

 

中場休息時間。。。喝口茶~ 歡迎關注公眾號:kaggle實戰,或博客:http://www.cnblogs.com/daniel-D/

 

4. 模型訓練

訓練集和測試集

先用線性回歸模型在訓練集上訓練,然后用訓練好的模型再次預測訓練集的label,計算RMSE為6.8w刀,MAE誤差為4.9w刀,模型明顯underfitting。解決的方法有:用復雜模型、用更好的特征、用更弱的約束。

改用決策樹模型進行訓練,得到訓練集的誤差為0.0,在測試集中誤差極大 。在回歸問題里,百分百完全預測准確基本是不可能的,說明模型存在過擬合現象。解決的方法有:用簡單模型、用更大的數據量、更強的約束、ensemble方法等。為了更好評估過擬合情況,可以用 K-fold 進行交叉驗證。基本過程如下:把全部數據集隨機分成K份,每次挑選其中K-1份訓練數據,剩下一份作為測試集計算誤差,總共重復K次。相比於只划分一份訓練集和測試集,這種方法更加健壯。

隨機森林模型是多個決策樹模型ensemble后的結果,比單個決策樹模型具有更強抗overfitting的能力。改用隨機森林模型進行訓練,發現結果好得多,但是測試集誤差依舊遠遠大於訓練集誤差,說明模型還需要更強的約束。為了找到較好的約束參數,可以采用grid search方法。

grid search

模型的超參可能有多個,每個有多種選擇,由此形成了參數網格grid。前面講過用交叉驗證的方法可以評估一個模型的效果,以上兩種方法結合,可以讓模型遍歷每個網格點,用交叉驗證的方法得到該網格點的模型預測誤差,從而找到表現最好的模型。最終找的的較好超參是 max_features 為6,n_estimators 為 30, RMSE 49900。

 

5. kaggle實戰

准確率top4%的 kenerl 地址鏈接,真實的數據集和本文以上描述有所區別

數據處理

  • outliers直接用邊界值去除,注意去除過程也是也風險的。
  • 分析target分布,發現有偏斜,用log轉化為近似正態分布

特征工程

  • 空值處理。空值的處理方法要因地制宜,主要有:轉換為某個固定字符串如“None”或者用0代替;以用近鄰記錄該特征的中位數代替;通過其他特征推斷;用數據集中最常出現的值代替;部分可以移除等
  • 類型轉換。數值型特征可能表示category信息,統一轉化為str類型。
  • 編碼。所有類別特征都轉化為one hot encode,對於可能包含順序關系的,額外添加label encode編碼。
  • 添加特征。在現有特征上,變換添加可能對預測目標有強關聯的特征。
  • Box-Cox變換。對偏度大於0.75的數值型特征進行Box-Cox變換(類似於log),轉換為近正態分布。

模型訓練

  • 先后應用LASSO RegressionElastic Net RegressionKernel Ridge RegressionGradient Boosting RegressionXGBoostLightGBM基礎模型,注意部分模型對scale較敏感,應先經過RobustScaler處理。

Stacking models

  • 最簡單的方法,以上模型預測值取平均,可以得到比單個模型好的預測效果。
  • 次簡單的方法,因為不同模型精度不一樣,理應取不同的權重,上面直接取平均太粗暴,改用 regression 來訓練權重。所以訓練集還需要划分出一部分數據,用來訓練lasso regression模型。

Ensembling

  • 用 ElasticNet、KernelRidge、 GradientBoostingRegressor 做底層模型,用 lasso regression 來得到每個模型的權重,Stacking models RMSE loss:0.07815
  • 用 XGBRegressor 單模型得分RMSE loss:0.07851
  • 用 LGBMRegressor 單模型得分RMSE loss: 0.07194
  • 最后拍個權重,求平均:stacked_pred*0.70 + xgb_pred*0.15 + lgb_pred*0.15 得到最終預測RMSE loss: 0.07524

相關資料

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM