Kaggleコンペに参加してみました。(その3)

Keepdata株式会社 開発Divの瀧田です。
それでは前々回前回に引き続き、kaggleコンペに参加した結果と感想をお伝えします。
今回はモデルの改善をしていきます。

前回のおさらい

前回の記事をもう一度おさらいしますと、 モデルの作成までに大きく分けて3つのことを行いました。

  1. 欠損値に対する処理を行う。
    前回は年齢を例に出しましたが、それ以外にも運賃データなども欠損値がある為、
    チケットのクラス毎に運賃の平均値を計算して補間をしています。
    また、乗船した港のような名義特徴量はpandasライブラリを利用して
    ダミー変数に置換しました。

  2. 機械学習ライブラリに適用するために、文字列データを数値データに変換する。
    今回利用しているscikit-learnという機械学習用ライブラリでは、
    数値データしか扱うことが出来ない為、文字データを数値データに変換しています。

  3. 学習に利用しないデータを削除する。
    学習に利用しなかった名前やキャビン番号などの情報は、ライブラリで学習させる前に削除しました。

今回のやっていくこと

今回は前回作成したモデルの改良を行なっていきます。
モデルの改良では、次の3つのことを行います。

  1. 欠損値の補間方法の変更
  2. 連続した数値データの離散化によるカテゴリ変数化
  3. 特徴量の見直し

拙い説明で、理解の足りない部分もあるかと思いますが宜しくお願いします。

1. 欠損値の補間方法の変更

前回、年齢が存在しないデータを乗客全体の平均年齢で補間しましたが、
これは学習用データに不要な揺らぎを与える可能性があります。
その為、場合によっては欠損しているレコードを削除して学習した結果よりも、
悪い結果をもたらしてしまうこともあります。

また、年代毎に乗客の生死の割合を集計してみると、
0~10歳の生存率は6割弱であるのに対し、70~80歳の生存率は2割程度しかなく、
年代により生存率が大きく変わってくることが分かります。
そうすると全体の平均年齢ではなく、他のデータから年齢を類推出来ないか検討し、
より適切な数値で埋めることでモデルが改善出来そうです。

訓練用データは前回も述べたように、

  • ・乗客ID
  • ・生き残ったか
  • ・チケットのクラス
  • ・名前
  • ・性別
  • ・年齢
  • ・兄弟や配偶者の数
  • ・親、子供の数
  • ・チケットの番号
  • ・運賃
  • ・キャビン番号
  • ・乗船した港

などのデータが含まれます。この中で年齢が類推出来そうなデータというと
チケットのクラスが最適だと思います。
また、チケットのクラス毎に生き残った割合を出すと、
チケットのクラスが高いほど生き残る比率が高いことがわかりました。
よって、チケットのクラスも年齢と同様に生存率に関わる要素になるので、
チケットのクラス毎に平均年齢を計算した上で、
チケットのクラスに応じて年齢を補間するのが良さそうです。

この方法を試したところ、0.71から0.74程度までスコアが上がりました。

2. 連続した数値データの離散化によるカテゴリ変数化

年齢データは、そのままの値を数値データとして扱いましたが、
これも段階で分けて数値に置き換えてみます。
例えば、年齢を
0 ~ 10 => 0
10 ~ 20 => 1
20 ~ 30 => 2
30 ~ 40 => 3
40 ~ 50 => 4
50以上 => 5
のように変換してカテゴリ変数化します。
この変換の後に学習させて予測したモデルでは、0.74から0.75程度までスコアが上がりました。

3. 特徴量の見直し

kaggleでランダムフォレストで学習する際に利用したscikit-learnのライブラリでは、
ランダムフォレストで学習済みのインスタンスから特徴量の重要度を取得することができます。

先ほど離散化したモデルの特徴量の重要度を取得してみると、
下記のような結果になります。

  • ・Pclass 0.1085
  • ・Sex 0.3087
  • ・Age 0.1373
  • ・SibSp 0.0489
  • ・Parch 0.0398
  • ・Fare 0.3155
  • ・Embarked_C 0.0127
  • ・Embarked_Q 0.0123
  • ・Embarked_S 0.0164

Embarked_*は名義特徴量をダミー変数化したものです。
私が作成したモデルでは、性別と、運賃が重要な特徴量になっているようです。
反対に、SibSp(兄弟や配偶者の数)、Parch(親や子供の数)は、
あまり重要ではない特徴量になっています。

ここで、次の場合に分けて集計してそれぞれ生存率を出してみます。

兄弟や配偶者の数が
  • ・0人の場合
  • ・1人の場合
  • ・2人以上の場合
親や子供の数が
  • ・0人の場合
  • ・1人の場合
  • ・2人の場合
  • ・3人以上の場合
この場合、生存率が高いのはそれぞれ
兄弟や配偶者

1人 > 0人 > 2人

親や子供の数

1人 > 2人 > 0人 > 3人以上

という結果でした。この2つの結果から分かる傾向として、
配偶者や家族が居る方が、単身者よりも生存率が高いようです。
(独身の私には辛い結果です。)

これは特徴量として使えそうです。
従って、配偶者も家族も居ない事を示す特徴量として新たにlonelyという列を用意し、
SibSpやParchはlonelyを特徴量として使う代わりに削除します。

この特徴量を加えた結果、0.75から0.76程度までスコアが上がりました。

まとめ

モデルの補間方法や、連続する数値データの離散化、特徴量を見直すことで
スコアが0.71から0.76程度まで伸びました。

機械学習を行う上では、提示されたデータそのまま利用するだけではなく、
提示されたデータの背景を考え、新たに特徴量として使えるものの仮説を立て、
集計結果を見て実際に使えるかを検証する必要があります。
今回のコンペでも利用せずに落としてしまったキャビン番号や、
ダミー変数で置き換えた結果あまり重要でない特徴量となってしまった港の情報など、
仮説を立てる事で特徴量として使えないかを検証してみる必要がありそうです。

予定ではその3まででしたが、スコアが上がったらまたblogに書きたいと思います。

結論:生き残りたければ結婚しよう

以上です。