初めてKaggleに挑戦した話2 特徴量エンジニアリングをしてみた
「初めてKaggleに挑戦した話1」を書いた後、特徴量エンジニアリングなどをしたりしてもう少しTitanicに取り組んだのでまとめます。
精度が低く、順位も下から数えてすぐだったので、ひとまずTop50%に入ることを目標に取り組みました。
やったこと
前回からやったこととしては、
- 特徴量エンジニアリング
・史実を参考にした特徴量生成
・似た特徴量の結合と細かすぎる特徴量の再構成 - 特徴選択とパラメータチューニング
- 学習結果から得られた正解ラベルを用いて学習データを追加
辺りを行いました。
学習では前回と同じくLightGBMを用いました。
特徴量エンジニアリング
前回の時点で使用する特徴量のパターンをいろいろ試しましたが、Accuracyはあまり高くありませんでした。そこで、史実を基にデータを分割したり結合、再構成など特徴量エンジニアリングをすることで精度向上を図りました。
史実を参考にした特徴量生成
まず当日のことを知るために、wikiのタイタニック号沈没事故についてのページを読みました。すると、その中で救命ボート乗船時の状況について、
「ライトラーは左舷側のボートを担当し、マードックは右舷側のボートを担当した。一等航海士マードックと二等航海士ライトラーはそれぞれ「ウィメン・アンド・チルドレン・ファースト」について異なる解釈をした。マードックは女性と子供から乗せると解釈したが、ライトラーは女性と子供を乗せると解釈した。そのため、ライトラーは女性と子供が全員乗り込んだのを確認すると、スペースに余裕があっても救命ボートを降ろしたが、マードックは女性と子供の他にわずかだが男性も乗せた」
という記述がありました。このため、避難時、船の左舷右舷どちらに向かったかによって生存率が変化したことが考えられ、広い船内でどちら寄りに自分の客室があったかに影響されたと考えました。そして、船の客室番号は左舷と右舷でそれぞれ偶数と奇数に分かれていることも分かりました。
さらに、客室のある階層 (A~G) によって救命ボートまでの距離が異なり、特に下の方の階層である3等客室は1, 2等客室との間に障壁があるなど、階層も大きく影響していることが分かりました。
コンペで渡されている"Cabin"にはそれぞれの客室番号が書かれており、左舷よりか右舷よりかと階層が分かるようになっていました。そこで、客室番号を分割して右舷左舷情報を"RoomLorR"、階層情報を"RoomLayer"として特徴量を生成しました。このとき、"Cabin"は欠損値が多かったので、存在しないものに対しては存在しないことを示すラベルを付与しました。
それぞれ生成したデータをグラフ化すると、下のようになりました。
1枚目が"RoomLorR"、2枚目が"RoomLayer"で、オレンジ色の部分が生存者、一番右がデータの存在しなかった人です。これを見ると、まず客室番号データが無かった人の生存率が低いことが分かります。また、左舷右舷や階層によっても有意差があると言えるかは怪しいですが違いがあることが分かりました。
似た特徴量の結合と細かすぎる特徴量の再構成
SibSpとParchの結合
基から存在するデータのうち、"SibSp"及び"Parch"は
- SibSp: 同乗している兄弟・配偶者の人数
- Parch: 同乗している親・子供の人数
と似た内容のデータであることが分かりました。そこで、これらを「同乗している身内の人数」として一つに結合し、"SibSpParch"としました。
グラフ化すると、身内が1~3人いると生存率が高いことが分かりました。
AgeとFareの再構成
"Age"及び"Fare"について、それぞれ値が細かく示されていることが分かりました。
そこで、Ageは10歳ごと、Fareは50ごとで区切ってまとめることで、細分化されたまま学習されないようにし、それぞれ"aboutAge"、"aboutFare"としました。
特徴選択とパラメータチューニング
特徴選択
今回試した特徴量をすべてまとめると、下の通りです。
- Pclass - チケットクラス
- Sex - 性別
- RoomLorR - 客室の左舷右舷
- RoomLayer - 客室の階層
- SibSpParch - 同乗している身内の人数
- Age - 年齢
- AboutAge - 年齢を10歳ごと区切ったもの
- Fare - 料金
- aboutFare - 料金を50ポンドずつ区切ったもの
- Embarked - 出航地
- (Title) - 上では省略した、Qiitaの記事で見かけたMr. や Ms. などで分類したもの
これらを試していくと、最終的に精度が良かったのは
- Pclass
- Sex
- RoomLorR
- Age
- Fare
- SibSpParch
の6つの特徴量を用いたときでした。このときのFeature importanceは下のようになりました。"RoomLorR"の寄与度は思ったより低かったです。
パラメータチューニング
パラメータを最適化するため、GridSearchCVを使ってパラメータチューニングを行いました。ただ、仕組みをあまり理解できておらず、手作業で調整したときの方が精度が良く、過学習などしてたわけでもないようなのでもう少し学んでいきたいです。
学習結果から得られた正解ラベルを用いて学習データを追加
当たり前と言えばその通りなんですが、上記の方法で学習して予測を行うことで、testデータのSurvivedに関するラベルが生成されたので、それを学習データに追加することで合計1308人分のデータを用いて学習を行い、予測をしました。
Accuracy
結果として、0.78947の精度を出すことができ、目標だったTop50%入りは楽々超えることができました!(2018年9月16日時点での結果です)
(画像の0.79425は間違って参考にした方のプログラムで実行してしまった方の結果です…すぐ下が0.78947なので25%辺りに入れたのかなと思います…)
まとめ
Top50%に入るまでやると宣言したはいいものの、51%からなかなか上がらず苦しみました…
いや、研究やらなきゃそろそろ相当まずいのは分かってるんですけどね、先週始めたKaggleでTitanicをTop50%に入ったら始めようと思ってたら51%から上がらないんですよ
— セーター (@re_sweater) 2018年9月15日
一方で、先日言われつつも実感が湧かなかった特徴量エンジニアリングの必要性について理解でき、GridSearchCVなど様々なツールについても知ることができました。ただ、グラフ化するときの表示方法が今のやり方だと見にくいのでもう少し慣れて上手く表示できるようにしていきたいです。
次はDeep Learning系を使ってコンペに参加したい…