今回はTitanicデータセットを使いながら、「カテゴリ変数を機械学習で扱う方法」を学習した。
これまで特徴量として Sex や Age など数値データを扱ってきたが、今回は氏名(Name)から抽出した敬称(Title)を特徴量として利用する方法を学んだ。
一見すると単なる文字列に見えるデータだが、適切に加工することで有効な特徴量になることが分かった。
今回の学習内容
- Title(敬称)の作成
- Titleごとの件数と生存率の分析
- One-Hot Encodingの考え方
- pd.get_dummies()の利用
- drop_first=True の意味
- pd.concat() と axis の理解
Titleという特徴量を作る
TitanicデータセットのName列には氏名だけでなく敬称も含まれている。
例えば次のようなデータである。
Braund, Mr. Owen Harris Cumings, Mrs. John Bradley Heikkinen, Miss. Laina
ここから正規表現を利用して敬称だけを取り出す。
df["Title"] = df["Name"].str.extract(r",\s*([^.]+)\.")
今回は正規表現そのものよりも、「Nameから新しい特徴量を作る」という考え方を理解することを重視した。
Titleの件数を確認する
まずはどのような敬称が存在するのか確認した。
print(df["Title"].value_counts())
Mr 517 Miss 182 Mrs 125 Master 40 Dr 7 Rev 6 Major 2 Mlle 2 Col 2 Don 1 Mme 1 Ms 1 Lady 1 Sir 1 Capt 1 the Countess 1 Jonkheer 1
Mr・Miss・Mrs・Masterだけでほとんどを占めており、それ以外は数件しか存在しない。
学習を進める中で、件数が極端に少ないカテゴリはモデルが過学習しやすくなるため、「Rare」というカテゴリにまとめることが多いと教えてもらった。
また、MlleやMmeはフランス語表記であり、それぞれMiss・Mrsと同じ意味なのでまとめて扱うことが一般的とのことだった。
Titleごとの生存率を確認する
本当に特徴量として役立つのか確認するため、生存率を集計した。
print(df.groupby("Title")["Survived"].mean())
Master 0.575000 Miss 0.702703 Mr 0.156673 Mrs 0.793651 Rare 0.318182 the Countess 1.000000
結果を見ると、Mrの生存率は非常に低く、MrsやMissは高いことが分かる。
Master(男児)の生存率も比較的高く、「女性と子どもを優先して避難させた」というTitanicの歴史的背景とも一致している。
単なる文字列に見えるName列から、これだけ有益な情報が得られることに驚いた。
One-Hot Encodingとは
ここで疑問が生まれた。
Titleは文字列である。
しかし、機械学習モデルは数値しか扱えない。
ではどうすればよいのだろうか。
その答えがOne-Hot Encodingである。
title_dummies = pd.get_dummies(df["Title"])
実行すると次のような列が生成される。
Master Miss Mr Mrs Rare False False True False False False False False True False False True False False False
それぞれのカテゴリについて列を作り、自分のカテゴリだけをTrue(または1)にする。
これで機械学習モデルが扱える形式へ変換できる。
drop_first=True の意味で詰まった
今回一番理解が深まったのはここだった。
pd.get_dummies(df["Title"], drop_first=True)
実行するとMaster列が削除された。
最初は「Name列から作った情報だから不要なのかな」と考えたが、それは違った。
理由は残り4列がすべて0なら、自動的にMasterだと分かるためである。
例えば次のようなデータなら、Master列が無くてもMasterであることが分かる。
Miss Mr Mrs Rare 0 0 0 0
つまり、情報は失われていない。
これは「ダミー変数トラップ」を防ぐための工夫であり、ロジスティック回帰などでは重要な考え方になる。
pd.concat() と axis を復習
One-Hot Encodingした列は次のように元のDataFrameへ追加した。
df = pd.concat([df, title_dummies], axis=1)
以前学習したaxisの意味もここで復習できた。
- axis=0:縦方向(行方向)
- axis=1:横方向(列方向)
もしaxis=0にすると、列名が一致しないため大量のNaNを含む意味のない表になってしまう。
単に暗記するのではなく、「なぜそうなるのか」を考えながら理解できたのは収穫だった。
ChatGPTを活用して感じたこと
今回は単にコードを書くだけではなく、「なぜこの処理が必要なのか」を対話しながら整理できた。
特にdrop_first=Trueのような、一見すると理解しづらい部分は、自分なりの考えを伝えたうえで補足してもらうことで理解が深まった。
答えだけを教えてもらうのではなく、自分で考えてから確認する進め方は学習効率が高いと感じている。
まとめ
- 文字列はそのままでは機械学習モデルへ入力できない。
- One-Hot Encodingによってカテゴリ変数を数値化できる。
- drop_first=Trueは情報を失わずに不要な列を削除するための仕組みである。
- 特徴量エンジニアリングでは「意味のある情報を作る」ことが重要である。
今回はカテゴリ変数の扱い方を学んだが、今後はこれらの前処理をPipelineでまとめて管理する方法も学習していく予定である。