今回はカテゴリ変数の変換についてまとめます。
使用するデータはHouse Prices - Advanced Regression Techniquesのtrain.csvです。
また、着目する変数はHouseStyleとします。
以下kaggleのdata_description.txtより
HouseStyle: Style of dwelling
1Story One story
1.5Fin One and one-half story: 2nd level finished
1.5Unf One and one-half story: 2nd level unfinished
2Story Two story
2.5Fin Two and one-half story: 2nd level finished
2.5Unf Two and one-half story: 2nd level unfinished
SFoyer Split Foyer
SLvl Split Level
データについて
df['HouseStyle'].describe()
#以下出力
count 1460
unique 8
top 1Story
freq 726
Name: HouseStyle, dtype: object
#1.なぜ変換を行うのか
上のデータの例から分かるように、変数が文字列で表されているデータはほとんどの場合そのまま分析に使うことができません。そこで、モデルに適した形への変換が必要となります。(*数値型であっても、電話番号、郵便番号などの大小関係や連続的な意味を持たないものはカテゴリ変数として扱う)
#2.変換手法
##2.1.one-hot encoding
one-hot encodingでは、n個(今回のケースではn=8)の水準を持つカテゴリ変数をその水準かどうかを二値変数(0or1)を用いることで表現します。
実際に変換して最初の部分だけ表示すると、以下のようになります。
pd.get_dummies(df['HouseStyle']).head()
1.5Fin | 1.5Unf | 1Story | 2.5Fin | 2.5Unf | 2Story | SFoyer | SLvl | |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
カテゴリ変数の水準名から自動でデータフレーム型を返してくれるので便利です。 | ||||||||
(*使い方に注意が必要、こちらのブログに詳細) |
one-hot encodingの欠点は、特徴量の数がカテゴリ変数の水準数に応じて増えてしまう点にあります。これにより、学習にかかる計算時間や必要なメモリが大きく増えたり、モデルの性能に悪影響を及ぼす可能性が生じます。
この問題に対する対処法は主に3つ考えられます。
1.他の変換手法を試す
2.ある規則でグルーピングして、水準数を減らす
3.頻度の少ないカテゴリを「その他」にまとめる
今回のケースでは直感的に3の対処法が使えそうです。
実際の頻度は以下
df['HouseStyle'].value_counts()
#以下出力結果
1Story 726
2Story 445
1.5Fin 154
SLvl 65
SFoyer 37
1.5Unf 14
2.5Unf 11
2.5Fin 8
Name: HouseStyle, dtype: int64
以上より、SFoyer以下はその他としても良さそうです.
#2.2.label encoding
LabelEncodingとは単純に各水準を数字に置き換えるというものです。
今回のデータではカテゴリ変数が0から7までの数値に置き換えられます。
実際にやってみると以下の通りになります。
from sklearn.preprocessing import LabelEncoder
feature = ['HouseStyle']
for c in feature:
lbl = LabelEncoder()
df[c] = lbl.fit_transform(df[c].values)
df['HouseStyle'].value_counts()
#以下出力結果
2 726
5 445
0 154
7 65
6 37
1 14
4 11
3 8
Name: HouseStyle, dtype: int64
上で述べた通り、インデックスの数値が水準を区別する以外の意味を持たないため、このまま訓練データに用いることはあまり適切ではありません。しかし、決定木をベースとした手法では分岐を繰り返すことでこれらの数値を予測に反映することができるので、学習データとして活用できます。(特にGBDTではよく使われている印象がある)
#参考文献
門脇、阪田、保坂、平松 「Kaggleで勝つデータ分析の技術」 技術評論社 (2019/10/9)