和風ましらに

機械学習とか勉強したことを書き認めるブログ

カテゴリ変数の取り扱い方法

都道府県の名称など、値自体に意味が無い変数を扱う場合は、そのまま機械学習にかけてしまうと意味不明な結果が出る。

図1 都道府県と目的変数
そこで、よく使うカテゴリ変数の対処方法をまとめた。

ダミー変数化

変数を各種類ごとのカラムに分けて、0,1表記にしよう。と言うもの
一番ポピュラーなカテゴリ変数の扱い。

図2 ダミー変数化後のイメージ

ターゲットエンコーダー

各カテゴリ変数の各値で、正解である割合を各変数の持つ変数値として持たせる方法

図3 ターゲットエンコーダーのイメージ

参考資料 Feature Engineering

somoothing_encoder

図 3の「埼玉」みたいに、ターゲットエンコーダーを実際の現場で活用すると、たまたま少ない数の目的変数が全て1であった場合、ターゲットエンコーダーの値が1になって信頼性が疑わしい。

ので、パラメーターとして、学習データの中の「埼玉の割合」を重み付けする係数を追加する。
式は以下の感じ。

smoothing_encoder
smoothing_encoder

これを通じて、目的変数の発生確率を重み付け、たまたま「埼玉」が1になる時に、信頼性を重み付けられるようにしている。

詳しくは参考資料を
A Preprocessing Scheme for High-Cardinality Categorical Attributes in Classification and Prediction Problems

light gbmのカテゴリ変数の扱い

種類がめっちゃ多いカテゴリ変数を、ダミー化して変数を構築すると、カテゴリ変数の種類の分だけ列が増え計算量が増大してしまうし、最適化がされにくいらしい。

Particularly for high-cardinality categorical features, a tree built on one-hot features tends to be unbalanced(ドキュメントより引用)

とりあえず、カテゴリ変数を、各分岐点での (sum_gradient / sum_hessian)の値でヒストグラムを構築し、損失関数が最小になるところで分岐させる

documentによると、大体はダミー化するよりいいモデルができるらしい。

CatBoost

上記に書いたみたいに、lightGBMでは分岐させるときに、データの勾配を使って学習を行わせる。 ただ、これだと真のデータ分布に従うか分からないのに、観測データだけでモデルを作るようなものなので、バイアスが掛かって過学習してしまう。 (ちょっといい感じに日本語に訳せないので、論文の原文を引用。)

This leads to a shift of the distribution of estimated gradients in any domain of feature space in comparison with the true distribution of gradients in this domain, which leads to overfitting.

解決策としては、勾配の分布をモデリングするモデルを別途作りましょう。と言う感じ。 カテゴリ変数を扱う上では有用らしいが、全体の精度としては正直LightGBMとかと変わらない気がする。

とりあえず、CatBoostではカテゴリ変数を数値に変換しており、方法は以下の式のようになる。

catboost

  • CountInclass :ターゲットエンコーダーと同じ
  • propr:ユーザー側で指定するパラメーター
  • totalCount:該当の値の数

参考資料
CatBoost: gradient boosting with categorical features support
Transforming categorical features to numerical features