【Python機械学習】回帰問題でスコア(RMSE)を改善する方法の覚え書き

分類問題ばかりやっていたので、回帰問題にも取り組んでみました。

KaggleのHousePricesコンペのいくつかのカーネルを読んだりして、勉強になったことの覚え書きです。

お膳立ては以下の通り

・まずはベースラインとして、一番相関係数の高い特徴量を1つ選んで線形回帰

・特徴量を増やす

・目的変数を正規分布に近づける

・正則化項つき線形モデルを試す

・非線形モデルを試す

・(アンサンブルしてみる。スタッキング)

ではやっていきます。

 

取り扱うデータセット

今回はKingCountyの家の価格予測の問題のデータを利用します。

以下のURLから入手できます。(Kaggleの会員登録が必要です)

https://www.kaggle.com/harlfoxem/housesalesprediction/data

カラムの詳細は以下の通り

id : a notation for a house
date : Date house was sold
price : Price is prediction target
bedrooms : Number of Bedrooms/House
bathrooms : Number of bathrooms/House
sqft_living : square footage of the home
sqft_lot : square footage of the lot
floors : Total floors (levels) in house
waterfront : House which has a view to a waterfront
view : Has been viewed
condition : How good the condition is ( Overall )
grade : overall grade given to the housing unit, based on King County grading system
sqft_above : square footage of house apart from basement
sqft_basement : square footage of the basement
yr_built : Built Year
yr_renovated : Year when house was renovated
zipcode : zip
lat : Latitude coordinate
long : Longitude coordinate
sqft_living15 : Living room area in 2015(implies– some renovations) This might or might not have affected the lotsize area
sqft_lot15 : lotSize area in 2015(implies– some renovations)
欠けているデータはなく、date以外は数値型となっています。

 

相関係数の高い特徴量を1つ選んで線形回帰

数値特徴量のみを抽出して、ターゲット(price)との相関係数を出します。

sqft_livingが最も相関係数が高いので、これで線形回帰モデルを作ります。

ちなみに散布図をプロットしてみるとこんなようになっています。

ばっちり正の相関があるようですね。

線形回帰にかける際に、特徴量が1つだけだと、numpyでreshape(-1,1)をかけておかないとモデルを作る際に怒られます。

RMSEの算出についてですが、本当は

mp.sqrt(mean_squared_error(y,y_pred)みたいな感じで関数つくって一発でやりたかったのですが、謎のエラーが出て解決できなかったため、いったんmseをとって最後にルートをかけています。

さて、RMSEは261550という数字が出ました。これを基準にして、これからスコアが小さくなっていくかどうか見ていきたいと思います。

 

特徴量を増やす

いったん全部の特徴量をランダムフォレストに投入して、重要度の高いものを増やしてみます。

sqft_livingよりもgradeの方が大事な特徴量だったようです。

重要度が高い順から10個選択して、再度モデルを交差検証します。

スコアは207782とだいぶ向上しました!

 

目的変数を正規分布に近づける

線形回帰モデルはパラメトリックモデルで、データが正規分布に従うという仮定が置かれているそう。

詳しくはこちら→https://toukei-lab.com/box-cox%E5%A4%89%E6%8F%9B%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E6%AD%A3%E8%A6%8F%E5%88%86%E5%B8%83%E3%81%AB%E5%BE%93%E3%82%8F%E3%81%AA%E3%81%84%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E8%A7%A3%E6%9E%90

ですので、データの構造を無理やり正規分布に変換してしまうことで、スコアが改善することがあります。

やり方は2つあって、1つは先ほど案内したリンク先に書いてある「BoxCox変換」

もうひとつは、対数変換です。

今回は対数変換をしてみます。

まず、デフォルトでの目的変数の分布はこのようになっています。

対数変換をかけると以下のようになります。

さて、目的変数をこうした状態で先ほどと同じように交差検証してみるとどうでしょうか。

※予測値はnp.expm1()で元のスケールに戻す点に気を付ける

※追記:以下のコードは対数変換→データを分割、の順序になっていますが、逆じゃないとだめなようでした、、。

211913と悪くなってしまいました、、。

別の回帰問題のコンペでは対数変換でスコア改善したこともあったので、今回はダメでしたが試してみてよいと思います。

 

正則化項付き線形回帰モデルを試す

L1正則化、L2正則化を加えて、過学習を抑えてスコアが改善するか試してみます。

L1正則化項を加えたものがLasso回帰、L2正則化項を加えたものがRidge回帰、L1+L2両方いれたものがElasticNetです。

正則化項付きモデルは、スケーリングしてからでないとうまく働かないようですので、(外れ値に強い)RobustScalerをpipelineで入れておきます。

Ridge,LassoではRMSEスコアにほぼ変化はありませんでしたが、ElasticNetで微妙に改善しました。

ElasticNetのl1_ratioは0.8の時最適になりました。これはL1:L2=0.8:0.2という意味になります。

 

非線形モデルを試す

これでまで線形モデルでしたが、非線形モデルもやってみましょう。

ランダムフォレスト、XGBoost、LightGBMで見てみます。

圧倒的に非線形モデルが強いですね。

特にLightGBMはパラメータまったくチューニングしていなくてもパフォーマンス高くてありがたいです。

 

おまけのスタッキング

最後にスコアのよかった非線形3モデルでスタッキングも試してみようと思います。

scikit-learnにはスタッキングのAPIはないのですが、mlxtendというライブラリにあります。

使い方としては、StackingRegressorの引数regressorsで第一段階で使うモデルを、meta_regressorでoofしたデータを突っ込む第二段階のモデルを設定するだけでとても簡単です。

今回は、RF,XGB,LGBMで第一段階の予測をして、それを再度RFでモデルを作成します。

残念ながらスコアの向上は見られませんでした。

 

おわり

というわけで、回帰問題について勉強したことの覚え書きでした。

自分と同じ機械学習初学者さんのお役に立てたら幸いです。

最後までよんでいただきありがとうございました。