RのWeb制作

Webサービス制作のための技術情報を。

Python データサイエンス

【社内コンペ】回帰分析メモ 2019/09/13版

投稿日:2019年8月26日 更新日:

これは何?

某社で行われている社内コンペのメモです。私の備忘録でもあります。

今回の目的変数

建築物の坪単価
「え、建物の単価じゃないのか」と思ったあなたは正常。

今回の評価指標・ベースレート

正解単価の±10%以内に入った数 / 全数
※35%を超えれば良い
※重回帰(LinearRegression)でのベースレートは22%

今回の説明変数の特徴

0. リアルデータで欠損値が多い。
データの信頼性が低いかもしれない(担当者談)←マジカヨ・・・

1. どれが一番重要という変数がない。
自作合成変数が変数重要度No.1だったりする。

2. 変数の数が多い
138変数ある。
カテゴリ変数をone-hot化するだけで255変数

3. 決定木の場合はone-hot化すると判定精度が低下しかねない。
線形の場合は必須。
線形と決定木系のよくやる前処理方法は違うようだ。アルゴリズムが全く別だししゃーないか。

4. 設計会社区分で各カラムのmean、medianを取ったがうまくいかず。
上記の方法は、Train内で情報リーク(TestにTrainの情報が行って判別精度を甘めに見積もってしまうこと)が起こってしまうので採用できないようだ。
上記区分が不均一なデータだったので、SMOTEを試したがうまく行かず。
そもそもSMOTEはあまりうまく行かないようだ。(まあ適当にN点間の平均値取ってるだけだし仕方ないよね。)

5. 専門知識が無い
カラム内容を見てもさっぱりでした。もちろん少しは本で理解したが。

今回の目標

基本に忠実に行う。
コードはできるだけ自動化させる。(変数選択、合成等)
目視で変数選択しようにも、重要度がどれもほぼ変わらないぞ~(==;)みたいな状態だったので。

基本(的な学習器)に忠実に(テストして、最高のモノで学習を)行う。
回帰の場合は下記の通りとなっているが、果たしてそうなのか?
SGD

L1 ElasticNet

L2 SVR(linear)

SVR(rbf) EnsembleRegressors

Choosing the right estimator – scikit-learnより

作った処理の流れ

注意するところ

最適なCV方法をまず見つけることが一番大事。正答率という羅針盤がない航海になる。
変数名が専門用語だったので理解できず。業務内容理解しよね。

内容確認

Train+Testまとめて実施した。平均値埋めとかしない限りはリークは起こらないので問題なし。

目的変数を加工してはいかんのか?
→ いかんわけじゃない。目的変数を正規化したり、log化したり、合成するのもありだったりするようだ。

データ可視化

ひと目見て、あっ・・・(察し)となった。

目的変数に大きな外れ値が存在した。
それで何も考えずに行った正答率が非常に低かったのかも。
IQR(四分位値のアレ)を使って除外した。

説明変数にも大きな外れ値(カテゴリ変数はもちろん除く)があったので、
IQRを使ってNull化→欠損値と違う値で埋めた(決定木用)。これは精度向上に効果があった。

加えて、色々切り分けて見ても重要な変数がほぼない。
設計会社区分別での坪単価等が異なったので、それらしい変数を入れてみたがうまくいかず。

相関係数確認

-0.5~0.5だらけ

欠損値補正

Median、0等で埋めたり、TrainのみAveで埋めたりした中で一番良いやつを頼む。(ただし情報リークには気をつけることだ。)
学習器を使って埋める方法等もっとあると思う。

ただし、Mean埋めは線形タイプに、0(や-1など元々のカラム出てきてない値)は決定木タイプで使用するとGood。
異常値であることを機械に知らせてあげよう。
Nan値を予測して埋める手法を試してみたが正答率は結局下がった。もしかしたら線形タイプでは上がるかもしれない。

もう少し工夫はできる気がする。

変数合成

Null個数カラム=「レコードの中にNull値数が多いレコードは何故か値が低い」という知見を利用。

データ水増し

今回はやりましたがうまくいきませんでした。
分類(特に画像処理)だとよくやるもよう・・・画像を回転させるとそれだけで1枚にできるらしい。

正規化

MinMax、StandardScaler、RobustScaler、Normalizer
今回はMinMaxが一番良かった。StandardScalerが死んでた。

ただし、線形には効果はあるけど、決定木系には効果なし。
決定木系は順序(Rank)と集合で見ているもよう。

多モデルのテスト

テスト用関数も作った。
一番いいやつを頼む。

線形

from sklearn.linear_model import LinearRegression # 重回帰分析
LR = LinearRegression()
from sklearn.linear_model import SGDRegressor # データ量多い回帰
SGDR = SGDRegressor()
from sklearn.linear_model import Lasso # ラッソ(L1)
L1R = Lasso()
from sklearn.linear_model import Ridge # リッジ(L2)
L2R = Ridge()
from sklearn.svm import SVR # サポートベクター回帰
SVRR = SVR(gamma='auto')

決定木

from sklearn.tree import DecisionTreeRegressor # 決定木
DTR = DecisionTreeRegressor()
from sklearn.ensemble import BaggingRegressor # バギング回帰
BGR = BaggingRegressor(DTR, n_estimators=10, max_samples=0.3)
from sklearn.ensemble import RandomForestRegressor # ランダムフォレスト回帰
RFR = RandomForestRegressor(n_estimators=100)
import xgboost as xgb # XGB
XGBR = xgb.XGBRegressor(objective="reg:linear")

厳密に言うとバギング回帰は決定木ではない。
今回は中に決定木を入れているので決定木にした。

結果
XGBの独り勝ち

価格予想の論文でSVRが使われていたので、コレで頑張って22 → 40%くらい出してた。(つもりになっていた。ただの過学習だった)

しかし、XGB(回帰)をちょっと入れてみるか・・・結果33%で「は?(これまでの頑張りとは)」ってなった。

基本に忠実にやってみたけどやっぱりXGBが強い。
SVRも結構できる子やな~って感じ。(ただし過学習の恐怖からは逃れられない。)

CV値(自作関数)の確認も行った。
決定木の前処理を行えば、線形は死んで(マイナス突破)いた。
決定木系はプラスだった、が正答率25~30%程度と低い。

パラメーターチューニング

グリッドサーチ
・SVR、XGBで頑張った。
SVRは結局kernelはpolyが一番良く、sigmoidが一番悪かった。変数減らしてやったほうがとても早い。

ランダムサーチ
・SVR、XGBで頑張った。
今回評価指標がすごくレアなものなので、グリッドサーチに勝てなかった。過学習してるだけかも知らん。

その他の学習器の試行

keras(MLPとNNとDeepLearning)
Train+TestのdropNA後標準化のみ(8変数)で32%が出たように見えたが、変数が増えると死んだ(20~25%)。
たぶん変数の多さに比べてネットワークの大きさが足りない(層を多くしたりノードを横に増やすとプラスだったが限定的だった)。
あとは前処理が全然試行錯誤できていない。Log処理(疑似標準化)が強いもよう。

変数自動合成

元々あった255変数を、下記の方法で正答率が上がるものをピックアップして追加する。
・組み合わせ(+、-、×、÷)
・変数単独で計算(x^2、exp、log2、log10)する

ただし、めっちゃ手間がかかるので遺伝的プログラミング(遺伝的プログラミングによる特徴量生成でLightGBMの精度向上【kaggle Advent Calendar 11日目】)を導入しました。コードはコンペが終わったら全部載せます。

決定木は変数間の相互作用的なのは見えやすいが、比率(割り算)や差(引き算)を認識するのが困難なのでこういった自動化の手法は必須だと考えている。
3つ以上の変数の合成変数もアリなもよう。(遺伝的プログラミングなら理論上試行する)

変数選択

今回は後退的選択法を選択。
チューニングしたXGBを使い、重要度の低い変数から1つずつ削り取っていく方法にした。(詳細
変数の重要度が低い順から「切ったら精度下がるか?」で判定する方法を実装している。(自作)

回答提出用加工

下記の方法を採用
・なにもしない単一モデル
・平均アンサンブル
・重み付けアンサンブル

Aveや価格帯での重み付け(「ここら辺の価格帯はこの学習器が調子いい」というのがあるので)で具合のいいように組み合わせてみる。
分類は多数決が多いらしい。
回帰でアンサンブルって聞いたことがない(たぶん不勉強→Aveアンサンブルが多いもよう)。

平均が残念だったので重み付けして調整した。
正答率が1~3%くらい上がる感じだが、正しく施行しないと過学習と同じ様になる。
重み付けは1/RMSE^2で実行。1/RMSEでも余り変わらず。

あまりここだけに拘泥するのはよくない。
良い特徴量を作れたほうが強い。

回答提出用加工

TrainとTest+回答提出用(1)を使った学習
分類で良く使われる手法。

精度UPにはつながるが、ええのかこれとは思う。

回答提出

一番いい奴を頼む。

なんでこれ書いたの?

機械学習の一つ一つの手法ばっかりが着目されていて、やることをまとめて書いてある回帰分析の方法がなかったので。
数学や統計の以前に、プロジェクトとしてどうすんのコレ?っていう。

回帰分析の資料がねえ!

とっつきやすいように数式はゼロにした。

結果

コード

2019年9月末締め切りなのでお楽しみに。

-Python, データサイエンス

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

[Meisyo]練習難易度の不均衡是正への分析的アプローチ2

[Meisyo]練習難易度の不均衡是正への分析的アプローチから早3か月。 「練習ごとに難易度が違いすぎるんですけど!!」という不満は少しは解消されたかなー・・・ 効果測定してないのにわかるの?エスパー …

TensorFlowまで到達

ちょいちょい数式に詰まりながらも、DeeplearningのフレームワークTensorFlowの学習まで漕ぎ着けました。 一番困ったのは「説明無しで数式使うよ!」 マジやめてください・・・まあ勉強する …

[python]MNISTの学習モデルを保存し、テストする

機械学習のHello World的なMNISTにて、学習モデルを保存し、実行する際のメモ。 用意するもの PC コマンドプロンプト インストール(python、sklearn、numpy) 学習時のコ …

pythonのnumpyで遊ぶ

異常に奥が深いnumpyで遊びましょう!! import numpy as np 配列の形状変換 a = np.arange(int(np.floor(np.random.rand()*1000))) …

機械学習の勉強から見えた「間違いだらけのAI認識」

「AI」という字面が新聞にもネットニュースにも数多く出てくるようになりました。 ただ、機械学習を勉強してて思ったんですが・・・・AIの定義が曖昧すぎる 内容が書いてある記事も殆ど無いし…。 AIが行っ …