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

相關資料

 

 

相關文章
相關標籤/搜索