タイタニックの生存予測ですが、なかなか正解率8割の壁を超えることができなかったので、8割超えのサンプルソースを参考にさせて頂くことにしました。
参考ソースを実行
参考ソースの全体は下記のようになります。
[ソース]
1 | import numpy as np |
[提出結果]
正解率80.622%となっています。さすがです。
こちらの処理を勉強させて頂いて、また出直したいと思っております。
タイタニックの生存予測ですが、なかなか正解率8割の壁を超えることができなかったので、8割超えのサンプルソースを参考にさせて頂くことにしました。
参考ソースの全体は下記のようになります。
[ソース]
1 | import numpy as np |
[提出結果]
正解率80.622%となっています。さすがです。
こちらの処理を勉強させて頂いて、また出直したいと思っております。
今回は特徴量(カラム数)の取捨選択を自動で行います。
SelectKbestを使うと特徴量の取捨選択を自動化することができます。
(データの前処理は省略します。こちらの記事をご参照下さい。)
特徴量を自動で20個に絞り込むためには、select = SelectKBest(k = 20)という形で指定します。(15行目)
特徴量の数を10~903までループしながら、正解率が高くなる特徴量の数を調べます。
[ソース]
1 | import warnings |
[結果]
上記で調べた特徴量の数ごとの正解率をグラフ化します。
[ソース]
1 | import matplotlib.pyplot as plt |
[結果]
明確な最適解は分かりにくいのですが、今回は特徴量の数を420で予測することにしました。
特徴量の数を420に指定して(1行目)、学習・予測を行います。
最後に提出用に出力したCSVファイルをKaggleに提出します。
[ソース]
1 | select = SelectKBest(k = 420) |
[提出結果]
正解率79.18%となりました。
前回結果よりも少々正解率が落ちてしまいました・・・・やっぱり難しいです。
タイタニック生存予測の正解率をあげるために、Random Forestを生成するときのパラメータを調整します。
(データの前処理は前回記事と全く同じなので省略します。)
グリッドサーチを使って、次の3パラメータに対してチューニングを行います。
グリッドサーチはパラメータ候補をリストで指定して、その中でもっとも成績のいいパラメータの組み合わせを導く手法です。
[ソース]
1 | from sklearn import ensemble, model_selection |
[結果]
最も成績のよいパラメータは上記のようになりました。
グリッドサーチで調べたベストパラメータを指定してRandom Forestのインスタンスを作成します。
その後、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるかチェックします。
[ソース]
1 | from sklearn import ensemble, model_selection |
[結果]
正解率は87.31%~88.55%となりました。
分割交差検証で生成したRandom Forestをそのまま使って、学習・予測を行います。
最後に提出用に出力したCSVファイルをKaggleに提出します。
[ソース]
1 | # 学習 |
[提出結果]
正解率79.42%となりました。
パラメータを調整していない前回の正解率と全く同じ結果となりました・・・難しいです。
前回記事では分割交差検証で85%前後となかなかの正解率でしたが、Kaggleへの提出ができませんでした。
理由としてはSurnameカラムをワンホット・エンコーディングすると列数が増えてしまって、訓練データと検証データのカラムの整合性をとりにくくなってしまったためです。
カラム数があっていないと、予測(fit)するときにエラーになりますので。。
前回の失敗を踏まえて、今回はあらかじめ訓練データとテストデータを連結してから、デッドリストとサバイブリストの作成、データの前処理を行います。
データの前処理が終わったら、訓練データとテストデータと分割し、ランダムフォレストでの学習、推測を行います。
まずは前回記事でのデータ前処理全般を修正していきます。
[ソース]
1 | import pandas as pd |
ポイントは109~110行目でのデータ連結処理と118~119行目のデータ分割処理になります。
こうしておくと一括でデータの前処理ができるだけではなく、デッドリスト・サバイブリストを作る時のデータも増やすことができて一石二鳥でした。
これからのデータ分析にも役立ちそうな手法だなーと小さい発見をした気持ちになりました。
データの前処理は全て終わっていますので、Random Forestのインスタンスを作成し、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるかチェックします。
[ソース]
1 | from sklearn import ensemble, model_selection |
[結果]
正解率は86.98%~87.88%となりました。前回の記事を超える正解率です。
少し手ごたえを感じました。
訓練データ全体で学習を行います。
データの前処理は終わっていますので、すんなりと学習・推測処理を行うことができます。
1つ注意する点としては、検証データ(df_test)にはデータ前処理のためにSurvived項目が仮設定されているのでこれを省いておきます。(5行目)
最後に提出用に出力したCSVファイルをKaggleに提出します。
[ソース]
1 | # 学習 |
[提出結果]
正解率79.42%となりました。
・・・おしいです。もう少しで8割の正解率を超えられたのですが。。。
次回は、ランダムフォレストのパラメータを調整して念願の正解率8割超えを狙いたいと思います。
前2回の記事で行ったデータクレンジング処理を踏まえてタイタニックコンペに提出します。
改善内容は以下の通りです。
ランダムフォレストで年齢の欠損値を推定する処理を関数化します。
[ソース]
1 | def age_trans(df): |
名前(Name)から特徴量抽出し、デッドリストとサバイブリストを作成する処理を関数化します。
[ソース]
1 | def make_list(df): |
デッドリストに該当した行(乗客)の場合は、必ず死亡と判断されるようにSex, Age, Titleを典型的な死亡データに書き換え、サバイブリストに該当した行がある場合は、必ず生存と判断されるように Sex, Age, Titleを典型的な生存データに書き換える処理を関数化します。
[ソース]
1 | def trans_by_list(df): |
Kaggleに準備されているタイタニックの訓練データを読み込み、デッドリストとサバイブリストを作成しておきます。
データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)と、正解ラベルとそれ以外にデータを分けます。
データの前処理の中では、ランダムフォレストで年齢の欠損値を推定する処理age_trans)とデッドリストとサバイブリストを作成する処理(trans_by_list)をコールしています。
[ソース]
1 | import pandas as pd |
Random Forestのインスタンスを作成し、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるか調べてみます。
[ソース]
1 | from sklearn import ensemble, model_selection |
[出力]
正解率は全て85%台となりました。
これまでにない高正解率だったので早速Kaggleに提出しようとしたのですが、提出処理に戸惑ってしまったので、明日の記事に持ち越します。すいません。。。
以前名前に含まれる敬称(Mr. Mrs. Miss.など)をパラメータ化しましたが、今回はもう少し名前に関する特徴量に関して深堀りしていきたいと思います。
名前(Name)から敬称(Title)を抽出し、グループ化します。
Officerは乗船員で、Royaltyは王族、貴族といった意味合いです。
Jonkheerはオランダ語で貴族という意味になります。
[ソース]
1 | import pandas as pd |
[出力]
Mrの生存率が一番低く、Mrsの生存率が一番高いことが分かります。
Royalyt(貴族)の生存率も70%を超えていますね。さすがです(?)
名前から苗字を取り出しグループ化します。
家族がいた場合に生存率に影響があったのではないかという視点になります。
[ソース]
1 | # NameからSurname(苗字)を抽出 |
家族を16才以下または女性というグループにすると面白い事実が見えてきます。
[ソース]
1 | # 家族で16才以下または女性の生存率 |
[出力]
1行目の77グループでは生存率100%ですが、2行目の27グループでは生存率0%となっています。
多くのグループは全員生存しているのに、一部のグループだけ全滅しているということになります。
次に16才を超えかつ男性というグループに注目してみます。
[ソース]
1 | # 家族で16才超えかつ男性の生存率 |
[出力]
1行目の70グループは生存率0%で、2行目の14グループでは生存率100%となっています。
多くのグループは全滅しているのに、一部のグループだけ全員生存しているということになります。
上記の結果をまとめると、全体の流れとは逆の運命を辿った少数派がいるということになります。
今回の名前分析を踏まえて、次の2種類のリストを作成しテストデータに反映します。
[ソース]
1 | # デッドリストとサバイブリストの作成 |
[出力]
テストデータの中で、デッドリストに該当した行(乗客)の場合は、必ず死亡と判断されるようにSex, Age, Titleを典型的な死亡データに書き換え、サバイブリストに該当した行がある場合は、必ず生存と判断されるように Sex, Age, Titleを典型的な生存データに書き換えています。
次回はこのデッドリストとサバイブリストの判定を踏まえて、タイタニック生存予測を行いたいと思います。
タイタニック生存予測の精度を上げるためにあらたな分析方法を探していたところ興味深い記事を見つけました。
それは欠損値がない完全なデータ(Pclass, Sex, SibSp, Parch)を使って、ランダムフォレストで年齢(Age)の欠損値を推定するというものです。
ランダムフォレストで年齢の欠損値を推定する手順は下記の通りです。
最後に年齢ごとの生存率と死亡率をグラフ化しています。
[ソース]
1 | import pandas as pd |
[出力]
年齢(Age)の欠損値補完をした結果をグラフにしたのが上の図になります。
10歳未満の場合は生存率が上回っていて、20~30歳の場合は死亡率が上回っていることが確認できます。
「同一のチケット番号だと一緒に旅行していることの指標となり、チケットの重複数と生存率には関係がある」という記事を見かけました。
今回はチケットの重複数をパラメータ化してタイタニックの生存予測を行います。
チケットの重複数をTicketFrequency項目として追加、重複数ごとに平均生存率を表示します。
[ソース]
1 | import pandas as pd |
[出力]
次にチケットの重複数ごとの平均生存率をグラフ化します。
[ソース]
1 | df_train[['TicketFrequency', 'Survived']].groupby('TicketFrequency').mean().plot(kind='bar', figsize=(10,6)) |
[出力]
チケット重複が2から3の場合は、生存率が高いように見受けられます。
Kaggleに準備されているタイタニックの訓練データを読み込みます。
データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)と、正解ラベルとそれ以外にデータを分けます。
データクレンジングの改善6として、チケットの重複数をパラメータとして追加しています。(8行目)
[ソース]
1 | import pandas as pd |
[出力]
チケットの重複数としてTicketFrequencyが追加されていることが確認できます。
Random Forestのインスタンスを作成し、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるか調べてみます。
実行するたびに微妙に正解率が違うことに気づいたので、5回ほど連続実行しています。
[ソース]
1 | from sklearn import ensemble, model_selection |
[出力]
正解率は78%~80%となりました。
訓練データ全体で学習を行います。
その後、検証データを読み込み、推論・提出用のCSVの出力を行い、Kaggleに提出します。
[ソース]
1 | # 学習 |
[提出結果]
正解率76.55%となりました。正解率あげるのってホントに難しいんですね。
パラメータの追加・削除だけではなくて他の切り口でいく必要があると感じ始めています。
名前に含まれる敬称は社会経済的地位に関する情報となりえる可能性があるような気がします。
そこで今回は名前に含まれる敬称(Mr. Mrs. Miss.など)を抽出し、カテゴリパラメータとして追加してみます。
名前から敬称を抽出しTitle項目として追加しています。
同じ敬称の個数が10に満たない場合は’etc’とひとまとめにしました。
[ソース]
1 | # expand=True ⇒ 複数の列に分割してpandas.DataFrameとして取得 |
[出力]
名前から敬称がきちんと抽出できていることが分かります。
各敬称の個数を表示すると下記のようになります。
[ソース]
1 | df_train.groupby('Title')['Title'].count() |
[出力]
メジャーな敬称が問題なく抽出されていると思います。
Kaggleに準備されているタイタニックの訓練データを読み込みます。
データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)と、正解ラベルとそれ以外にデータを分けます。
データクレンジングの改善5として、名前から敬称を抽出しカテゴリパラメータとしています。
[ソース]
1 | import pandas as pd |
Random Forestのインスタンスを作成し、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるか調べてみます。
[ソース]
1 | from sklearn import ensemble, model_selection |
[出力]
正解率は80.25%となりました。
訓練データ全体で学習を行います。
その後、検証データを読み込み、推論・提出用のCSVの出力を行い、Kaggleに提出します。
[ソース]
1 | # 学習 |
[提出結果]
正解率71.53%となりました。
・・・だいぶ正解率が落ちてしまいました。敬称は生存率には影響しないのかもしれません。
ビニングまたは離散化は、連続変数または数値変数をカテゴリカル特徴に変換するための処理です。
年齢(Age)に関してビニング処理を行ってみます。
年齢(Age)に着目してみますと、データのばらつきが大きく外れ値が予測に悪い影響を与えている可能性があります。
年齢データのばらつきを確認するために、箱ひげ図で表示します。
[ソース]
1 | import pandas as pd |
[出力]
65歳以上のデータが外れ値と判断できるかと思います。
年齢をcut関数を使って、ビニングします。cut関数は最大値と最小値の間を等間隔で分割する関数です。
今回はビンの数が5個になるように分割し(5分割)、各範囲のデータ数を表示します。
[ソース]
1 | df_train['Age'] = pd.cut(df_train['Age'], 5, labels=False) |
[出力]
年齢データではなく0~4の数字になっていることが分かります。
次にビニング処理を行った年齢範囲ごとの平均生存率を棒グラフで表示してみます。
[ソース]
1 | df_train.groupby('Age')['Survived'].mean().plot(kind='bar', figsize=(10,6)) |
[出力]
若い人年齢に部類されているほど生存率が高く、年配の人の生存率が10%以下であることが見てとれます。
Kaggleに準備されているタイタニックの訓練データを読み込みます。
データの前処理(不要列の削除・欠損処理・カテゴリ変数の変換)と、正解ラベルとそれ以外にデータを分けます。
データクレンジングの改善4として、年齢データをcut関数を使ってビニング処理を行っています。(18行目)
[ソース]
1 | import pandas as pd |
[出力]
年齢(Age)が、0~4の数字に変換されていることが確認できます。
Random Forestのインスタンスを作成し、cross_val_score関数で分割交差検証を行い、どのくらいの正解率になるか調べてみます。
[ソース]
1 | from sklearn import ensemble, model_selection |
[出力]
正解率は80.36%となりました。
訓練データ全体で学習を行います。
その後、検証データを読み込み、推論・提出用のCSVの出力を行い、Kaggleに提出します。
[ソース]
1 |
[提出結果]
正解率75.11%となりました。