Kaggle初心者入門】タイタニックで学ぶデータ分析!スコアアップへの航海日誌

こんにちは。ゆうせいです。

突然ですが、あなたは「データサイエンス」という言葉にどんなイメージを持っていますか?なんだか難しそう、数学やプログラミングが得意な人たちの世界…そんな風に感じているかもしれませんね。確かに、奥が深い世界ではありますが、正しい地図と羅針盤があれば、誰でもその冒険に旅立つことができるんですよ!

この記事は、まさにその冒険への「招待状」です。一緒にデータサイエンスという未知なる大海原へ漕ぎ出してみませんか?

冒険の始まり:Kaggleって何?データサイエンスの甲子園へようこそ!

まず、私たちの冒険の舞台となる「Kaggle(カグル)」を紹介させてください。

Kaggleとは、一言でいうと「データサイエンティストたちのための競技場」のようなものです。世界中の企業や研究機関が「このデータを分析して、こんなことを予測してほしい!」という課題を出題します。そして、世界中のデータサイエンティストたちが、その課題に対して最も精度の高い予測モデルを作るために、腕を競い合うのです。

例えるなら、そう、「データサイエンス界の甲子園」や「頭脳のオリンピック」でしょうか。世界中の猛者たちが集い、日々熱い戦いを繰り広げている、とても刺激的なプラットフォームなんです!参加することに費用はかかりませんし、自分の実力を客観的なスコアで知ることができる最高の場所ですよ。

最初の船出は「タイタニック号」で!なぜこのコンペが初心者におすすめなの?

Kaggleには、それこそ星の数ほどのコンペティション(コンペと呼ばれる、個々の課題のことです)が存在します。画像から病気を発見するもの、文章の意味を読み解くもの、株価を予測するもの…。

では、数あるコンペの中で、なぜ私たちは最初に「タイタニック号」に乗船すべきなのでしょうか?

その理由は大きく3つあります。

  1. 目的がとっても分かりやすいからタイタニックの課題は「乗客の年齢や性別、乗船クラスなどのデータから、その人が生存したか、それとも亡くなってしまったか」を予測することです。ゴールが非常に明確で、直感的にも理解しやすいですよね。
  2. データが扱いやすいからデータサイエンスの現場では、何百万、何千万行という巨大なデータを扱うことも珍しくありません。しかし、タイタニックのデータはそこまで大きくなく、個人のパソコンでも十分に扱えるサイズです。データ分析の基本的な流れを学ぶには、まさにうってつけの教材なんです。
  3. 先人たちの知恵(航海日誌)が豊富だからタイタニックは「初心者向けコンペの登竜門」として、あまりにも有名です。そのため、世界中の先輩データサイエンティストたちが、たくさんの解説記事やソースコードを「航海日誌」として残してくれています。道に迷ったとき、いつでも参考にできる素晴らしい資料がたくさんあるのは、初心者にとって、とても心強いことだと思いませんか?

料理に例えるなら、いきなりフランス料理のフルコースに挑戦するのではなく、まずは美味しいカレーライスの作り方をマスターするようなもの。カレー作りには、野菜の切り方、炒め方、煮込み方といった料理の基本が詰まっていますよね。タイタニックも同じで、データ分析の基本となる要素がギュッと詰まった、最高の練習問題なのです!

この航海で手に入る宝物:この記事で学べること

この一連の記事は、単にソースコードを解説するだけのものではありません。

あなたが一人の船乗りとして、Kaggleという大海原に漕ぎ出し、タイタニックという最初の航海で試行錯誤を繰り返しながら、少しずつ成長していく…そんな「冒険の物語」として進めていきたいと思っています。

この航海を終えるころ、あなたの手にはきっとこんな宝物が握られているはずです。

手に入る宝物(スキル)説明
データ分析の基本的な流れデータを読み込み、中身を理解し、予測するまでの一連のプロセスがわかります。
Pythonを使ったデータ加工技術汚れたデータをきれいにしたり、分析しやすい形に整えたりする力がつきます。
機械学習モデルの作り方コンピュータにデータを学習させ、未来を予測させる方法の初歩を学べます。
試行錯誤して成果を出す楽しさ自分の工夫でスコアが上がっていく、あの最高の瞬間を体験できます!

もちろん、最初からうまくいくことばかりではないでしょう。エラーの嵐に見舞われたり、スコアが伸び悩んで座礁しそうになったりすることもあるかもしれません。

でも、心配しないでください!私があなたの航海士として、すぐ隣でサポートします。

さあ、準備はいいですか?羅針盤は確かに、未来を指しています。

次の章から、いよいよ具体的な冒険の始まりです。まずはKaggleにアカウントを登録し、最初の提出を体験してみましょう!

第一章:初めての出航 - とにかく提出してみよう!

さあ、いよいよ冒険の始まりです!序章で手に入れた「Kaggleへの招待状」を握りしめ、私たちは今、タイタニック号が待つ港に立っています。

この第一章の目的は、とにかく「船出を経験すること」。完璧な航海の準備なんて、まだ必要ありません。まずはコンパスも海図も持たずに、一度海へ出てみましょう。そう、「Kaggleのコンペに参加して、結果を提出する」という一連の流れを体験することが、この章最大のゴールです!失敗を恐れずに、いきましょう!

旅の準備:Kaggleへの登録と冒険の地図(データ)を手に入れよう

何はともあれ、冒険には準備が必要です。まずはKaggleという船に乗るための「乗船券」を手に入れましょう。

  1. Kaggleの公式サイトにアクセスし、右上の「Register」からアカウントを作成してください。Googleアカウントなどを使えば、すぐに登録できますよ。
  2. 登録が完了したら、検索窓に「Titanic」と入力して、「Titanic - Machine Learning from Disaster」というコンペティションのページに移動します。(https://www.kaggle.com/competitions/titanic)
  3. ページのメニューから「Data」というタブをクリックしてください。ここに、私たちの冒険の地図となる「データ」がすべて用意されています。

いくつかのファイルがありますが、特に重要なのは以下の3つです。今のうちにダウンロードしておきましょう!

ファイル名役割例えるなら…
train.csv訓練データ。乗客の情報と、その人が生存したか(Survivedが1)否か(Survivedが0)という「答え」がセットになったデータです。レシピと完成品の写真
test.csvテストデータ。乗客の情報は入っていますが、「答え」であるSurvivedの列がありません。この人たちの生死を予測するのが目的です。食材だけが入った箱
gender_submission.csv提出ファイルのサンプル。Kaggleに提出するファイルはこういう形式で作ってくださいね、という見本です。料理の盛り付け例

train.csvという「レシピ」を使って、コンピュータに生存予測のルールを学習させ、test.csvという「食材」を使って、本番の予測(料理)を行う。そして、gender_submission.csvという「盛り付け例」と同じ形式で結果を提出する。これがKaggleコンペの基本的な流れです。なんとなくイメージは掴めましたか?

羅針盤も海図もなし!「性別だけで予測する」という最初の挑戦

さて、データも手に入りました。普通ならここからデータをじっくり分析して…となるところですが、今回は違います。

なんと、ダウンロードしたgender_submission.csvを、そのまま提出してみましょう!

「え、何もしないで提出するの?」と思いますよね。はい、それでいいんです!これには二つの大切な意味があります。

一つは、「提出というゴールまでの流れに慣れること」。せっかく良い予測モデルを作っても、提出方法がわからなければスコアは出ません。まずはゴールテープの切り方を体験しておくことが重要です。

もう一つは、「基準点(ベースライン)を知ること」gender_submission.csvの中身は、実は「女性は全員生存、男性は全員死亡」という、非常にシンプルなルールで作られた予測結果です。タイタニック号の事故では「女性と子供を優先的に」という救助活動が行われた歴史的事実に基づいているため、これは意外と悪くない予測だったりします。このスコアを最初の「基準点」として覚えておくことで、これから私たちが工夫を凝らした結果、どれだけ成長できたのかを測る物差しになるのです。

さあ、コンペページの「Submit Predictions」ボタンをクリックして、ダウンロードしたgender_submission.csvをアップロードしてみてください。簡単な説明を添えて提出ボタンを押せば、完了です!

初めてのスコアは?ここが君のスタート地点だ!

提出後、少し待つと「My Submissions」ページであなたのスコアが確認できます。どうでしたか?

おそらく「0.76555」といった数字が表示されているはずです。これは何を意味するのでしょうか?

この数字は、Accuracy(正解率) と呼ばれる指標です。

専門用語が出てきましたが、難しくありません。これは「あなたが予測した結果が、実際の答えとどれくらい一致していたか」を示す割合のことです。

正解率=正しく予測できた乗客の数​÷予測した乗客の総数

つまり、スコアが0.76555ということは、約76.5%の乗客の生死を正しく言い当てられた、ということになります。性別だけで判断した割には、かなり高い精度だと思いませんか?

このスコアを見て、「意外とすごい!」と感じた人も、「まだまだ上を目指したい!」と燃えてきた人もいるでしょう。どちらの気持ちも大正解!

この「0.76555」というスコアが、私たちの長い航海のスタート地点を示す灯台の光です。ここから、私たちはデータという羅針盤を手に、もっともっと高いスコアを目指す旅に出るのです。

そして、その冒険はKaggleのサイト内で直接始めることができるんですよ!外部のツールを使う代わりに、このコンペ専用のコーディング環境「Kaggle Notebook(ノートブック)」を使ってみましょう。

コンペページの「Code」タブをクリックし、「New Notebook」を選択してみてください。すると、あなた専用の分析環境が立ち上がります。便利なことに、このノートブックには分析に必要なライブラリ(Pandasなど)が初めから用意されていて、先ほど確認したデータも既に読み込める状態になっています。とっても手軽ですよね!

今後のために、このノートブック上でPythonを使い、提出ファイルの中身を確認する方法だけ見ておきましょう。ノートブックのセルに、以下のコードを打ち込んで実行してみてください。

# データ分析に必須のライブラリ、pandasをインポートします
import pandas as pd

# ノートブックに用意されている提出サンプルファイルを読み込みます
# このファイルパス '/kaggle/input/titanic/...' は環境に応じて書き換えてください。
submission_df = pd.read_csv('/kaggle/input/titanic/gender_submission.csv')

# 最初の5行を表示して、中身を確認してみましょう
print(submission_df.head())

このコードを実行すると、gender_submission.csvの中身、つまり乗客ID(PassengerId)とその人の生存予測(Survived)の組み合わせが表示されるはずです。

   PassengerId  Survived
0          892         0
1          893         1
2          894         0
3          895         0
4          896         1

これであなたも、Kaggleのコンペに参加し、スコアを手にした立派な「Kaggler(カグラー)」の仲間入りです!最初の大きな一歩を踏み出した自分を、ぜひ褒めてあげてください!

しかし、本当の冒険はここから始まります。このスコアを超えるためには、私たちが手に入れたtrain.csvという宝の地図を、じっくりと読み解く必要があります。

次の章では、いよいよデータの中身を深く探る「探索的データ分析(EDA)」という航海術を学んでいきましょう!お楽しみに!

第二章:航海の必需品 - データの声を聞く「探索的データ分析(EDA)」

第一章では、無事にKaggleの海へ船出し、最初のスコアという名の「現在地」を知ることができましたね。おめでとうございます!

しかし、あのスコアは言わば、闇雲に船を漕いで偶然たどり着いた場所に過ぎません。ここからさらに先へ、もっと良い成績へと進むためには、信頼できる「海図」と「羅針盤」が必要不可欠です。

その海図こそが、私たちが手にした「データ」に他なりません。この章では、データという海図をじっくりと読み解き、隠された宝のありか(スコアアップのヒント)を見つけ出すための航海術、「探索的データ分析(EDA)」を学んでいきましょう!

探索的データ分析(EDA)ってなんだろう?- データの健康診断をはじめよう!

探索的データ分析(Exploratory Data Analysis、略してEDA)。また新しい専門用語が出てきましたが、まったく怖がる必要はありませんよ。

EDAを例えるなら、「データの健康診断」のようなものです。本格的な手術(機械学習モデルの構築)に臨む前に、まずは患者さん(データ)の身長や体重、血液型を調べたり、どこか悪いところがないか問診したりしますよね?それと全く同じです。

データ全体が何件あるのか、どんな項目(列)が含まれているのか、数字のデータはどんな範囲に分布しているのか、そして何より「データに欠けている部分はないか?」といったことを、本格的な分析の前にじっくりと観察する。このプロセスがEDAです。

これをやることで、データの全体像を掴み、この後の分析の方針を立てることができる、非常に重要なステップなのです。さあ、データのお医者さんになったつもりで、最初の問診を始めてみましょう!

データの中身を覗いてみよう

ここからは、Pythonとデータ分析の強力な相棒であるpandasライブラリを使って、実際にtrain.csv(答えの書いてある訓練データ)の中身を見ていきます。Google Colaboratoryなどを開いて、一緒にコードを打ち込んでみてください!

まずはデータを読み込んで、最初の5行をチラ見してみましょう。head()という命令を使います。

# データ分析ライブラリ「pandas」を使えるように準備します
import pandas as pd

# train.csvファイルを読み込み、train_dfという名前の変数に格納します
# このtrain_dfが、私たちの分析の土台となるデータ表です
train_df = pd.read_csv('train.csv')

# データの最初の5行を表示して、どんな列があるか確認します
print(train_df.head())

どうでしょうか?PassengerId(乗客ID)、Survived(生存結果)、Pclass(客室クラス)、Name(名前)、Sex(性別)…など、乗客に関する様々な情報が表形式で並んでいるのがわかりますね。

   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   
3            4         1       1   
4            5         0       3   

                                                Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1   
2                             Heikkinen, Miss. Laina  female  26.0      0   
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   
4                           Allen, Mr. William Henry    male  35.0      0   

   Parch            Ticket     Fare Cabin Embarked  
0      0         A/5 21171   7.2500   NaN        S  
1      0          PC 17599  71.2833   C85        C  
2      0  STON/O2. 3101282   7.9250   NaN        S  
3      0            113803  53.1000  C123        S  
4      0            373450   8.0500   NaN        S  

次に、もっと詳しく「データのカルテ」を見てみましょう。info()という命令が非常に役立ちます。

# データの基本的な情報を表示します
print(train_df.info())

この結果は、情報の宝庫です!いくつか重要なポイントを読み解いてみましょう。

  • RangeIndex: 891 entries, 0 to 890: このデータには891人分の乗客情報が記録されていることがわかります。
  • Data columns (total 12 columns): 項目(列)は全部で12個ありますね。
  • Non-Null Count: ここが最重要ポイントです!各列に、データがちゃんと入っている(欠けていない)数が表示されています。見てください!891人分あるはずなのに、Age(年齢)は714、Cabin(客室番号)は204しかありません。
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

最後に、数値データの基本的な統計量を表示してくれるdescribe()という命令も使ってみましょう。平均値や最大値・最小値などが一目でわかります。

# 数値データに関する基本的な統計量を表示します
print(train_df.describe())

この結果から、例えば「乗客の平均年齢は約29.7歳だったんだな」「運賃(Fare)は無料の人から512ドルという高額な人まで、幅が広いんだな」といったことが読み取れますね。

       PassengerId    Survived      Pclass         Age       SibSp  \
count   891.000000  891.000000  891.000000  714.000000  891.000000   
mean    446.000000    0.383838    2.308642   29.699118    0.523008   
std     257.353842    0.486592    0.836071   14.526497    1.102743   
min       1.000000    0.000000    1.000000    0.420000    0.000000   
25%     223.500000    0.000000    2.000000   20.125000    0.000000   
50%     446.000000    0.000000    3.000000   28.000000    0.000000   
75%     668.500000    1.000000    3.000000   38.000000    1.000000   
max     891.000000    1.000000    3.000000   80.000000    8.000000   

            Parch        Fare  
count  891.000000  891.000000  
mean     0.381594   32.204208  
std      0.806057   49.693429  
min      0.000000    0.000000  
25%      0.000000    7.910400  
50%      0.000000   14.454200  
75%      0.000000   31.000000  
max      6.000000  512.329200

最初の発見!データに空いた穴「欠損値」との遭遇

さて、先ほどの健康診断で、私たちは非常に重大な問題を発見しました。覚えていますか?

そうです。Age(年齢)やCabin(客室番号)のデータが、全員分そろっていないのです。このように、データが入力されていない空白の状態を、専門用語で「欠損値(けっそんち)」と呼びます。

なぜ欠損値が問題なのでしょうか?

それは、ほとんどの機械学習モデルが、この欠損値をうまく扱えないからです。例えるなら、計算式の中に「10 + 5 + (空欄)」と書かれているようなもの。コンピュータは「(空欄)に何を入れたらいいかわからないよ!」とエラーを起こしてしまうのです。

パズルのピースがいくつか足りていない状態では、全体の絵を完成させることができませんよね。スコアを上げる予測モデルを作るためには、この欠損値という「穴」を、何らかの方法で適切に埋めてあげる必要があるのです。

おめでとうございます!あなたはEDAという航海術を使って、データという海図に隠された最初の課題、「欠損値の存在」を自力で発見しました。これはデータサイエンティストとしての、ものすごく大きな一歩ですよ!

さあ、問題が見つかれば、次はその解決策を考える番です。

次の章では、この厄介な欠損値をどう処理していくか、そして、データをさらにモデルが使いやすい形に加工していく「特徴量エンジニアリング」という、さらに面白い世界に足を踏み入れていきましょう!

第三章:船を改造せよ! - 予測精度を上げる「特徴量エンジニアリング」

こんにちは!ゆうせいです。前回の航海では、EDA(探索的データ分析)という名の「健康診断」を行い、私たちのデータに「欠損値」という治療が必要な箇所があることを見つけ出しましたね。

名医が患者の状態を正確に把握するように、私たちもデータの状態を理解しました。さあ、今度は腕利きのエンジニアやシェフに変身する時です!見つけた課題を解決し、元のデータ(食材)をさらに素晴らしい形(料理)へと加工していく、データサイエンスで最も創造的で面白いプロセス、「特徴量エンジニアリング」の世界へようこそ!

特徴量エンジニアリングとは? - データという食材を美味しく料理する技術

特徴量エンジニアリング (Feature Engineering)。なんだか難しそうな名前ですが、やっていることは非常にシンプルです。これは、「元のデータを使って、機械学習モデルがもっと理解しやすく、予測に役立つような新しいデータ(特徴量)を作り出す技術」のことです。

一番しっくりくる例えは、やっぱり「料理」ですね。

ニンジンやジャガイモといった生の食材(元のデータ)も、それなりに食べられます。しかし、皮をむき、適切な大きさに切り、炒めたり煮込んだり、スパイスで味付けをしたり(特徴量エンジニアリング)することで、栄養満点で美味しいカレーライス(精度の高い予測モデル)が完成しますよね?

データ分析の世界には「Garbage In, Garbage Out(ゴミを入れれば、ゴミしか出てこない)」という有名な言葉があります。どんなに高性能な機械学習モデル(最新式のオーブン)を使っても、元となる特徴量(食材)の質が悪ければ、決して良い予測結果(美味しい料理)は生まれません。この章で行う作業が、最終的なスコアを大きく左右するのです!


改造計画1:データの穴「欠損値」を埋める応急処置

それでは、さっそく前章で見つけたデータの穴、欠損値の修復作業に取り掛かりましょう!今回は、欠損が多かったAge(年齢)とEmbarked(乗船港)の2つを扱います。

年齢(Age)の穴を埋める

年齢がわからない乗客のデータ、どうすればいいでしょうか?一番簡単な方法は、乗客全体の年齢の「代表的な値」で埋めてしまうことです。この処理を専門用語で補完 (Imputation) と言います。

代表的な値として「平均値」と「中央値」がよく使われますが、今回は中央値を使いましょう。

なぜ平均値ではないのでしょう?例えば、9人の乗客の年齢がみんな30歳だったとします。そこに90歳の乗客が1人加わると、10人の平均年齢は約36歳に跳ね上がってしまいます。たった1人の極端な値に、全体の代表値が大きく影響されてしまうのですね。

一方、中央値はデータを年齢順に並べたときの「真ん中の人」の年齢なので、極端な値の影響を受けにくい、より安定した代表値と言えるのです。

それでは、コードを見てみましょう!

# Age列の中央値を計算します
age_median = train_df['Age'].median()

# print(f'年齢の中央値: {age_median}') # 計算結果を確認したい場合はこの行を実行

# Age列の欠損値(NaN)を、計算した中央値で埋めます
train_df['Age'] = train_df['Age'].fillna(age_median)

# ちゃんと埋まったか、もう一度info()で確認してみましょう
print(train_df.info())

info()の結果を見ると、AgeのNon-Null Countが891になっているはずです。見事に穴が埋まりましたね!

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          891 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

乗船港(Embarked)の穴を埋める

EmbarkedはS、C、Qという文字のデータです。このような文字のデータ(カテゴリカルデータと言います)の欠損値は、最も多く出現する値で埋めるのが一般的です。これを最頻値 (Mode) と言います。

# Embarked列の最頻値(一番多く出現する港)を計算します
embarked_mode = train_df['Embarked'].mode()[0] # mode()は複数の値を返すことがあるので、最初の[0]を指定します

# print(f'乗船港の最頻値: {embarked_mode}') # 計算結果を確認

# Embarked列の欠損値を、計算した最頻値で埋めます
train_df['Embarked'] = train_df['Embarked'].fillna(embarked_mode)

# 再度info()で確認します
print(train_df.info())

これでEmbarkedの穴も綺麗に塞がりました!

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          891 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     891 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

改造計画2:「文字」を「数字」に!コンピュータが理解できる言葉に翻訳しよう

欠損値の問題が解決しましたが、まだ課題は残っています。Sex列の'male'や'female'、Embarked列の'S'や'C'といった文字データです。

機械学習モデルは、その実態が数学的な計算の塊です。そのため、人間が使う「文字」を直接理解することはできません。これらの文字データを、計算できる「数値」に変換してあげる必要があります。この作業をカテゴリカルエンコーディングと呼びます。

性別(Sex)を数字に変換

'male'と'female'の2種類しかないので、これは簡単ですね。例えば、'male'を0、'female'を1に置き換えてみましょう。

# Sex列を数値に変換します
# 'male'を0に、'female'を1に置き換える辞書を作成
sex_map = {'male': 0, 'female': 1}
train_df['Sex'] = train_df['Sex'].map(sex_map)

# 変換できたか最初の5行を見て確認してみましょう
print(train_df.head())

Sexの列が0と1に変わっているのが確認できますね。

   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   
3            4         1       1   
4            5         0       3   

                                                Name  Sex   Age  SibSp  Parch  \
0                            Braund, Mr. Owen Harris    0  22.0      1      0   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...    1  38.0      1      0   
2                             Heikkinen, Miss. Laina    1  26.0      0      0   
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)    1  35.0      1      0   
4                           Allen, Mr. William Henry    0  35.0      0      0   

             Ticket     Fare Cabin Embarked  
0         A/5 21171   7.2500   NaN        S  
1          PC 17599  71.2833   C85        C  
2  STON/O2. 3101282   7.9250   NaN        S  
3            113803  53.1000  C123        S  
4            373450   8.0500   NaN        S  

乗船港(Embarked)を数字に変換

EmbarkedにはS, C, Qの3種類があります。これを単純にS=0, C=1, Q=2と置き換えてしまうと、モデルが「Q(2)はS(0)よりも2倍偉い」のように、数値の大小関係に意味があると誤解してしまう可能性があります。港の間に優劣はありませんよね。

こんな時に使うのがOne-Hotエンコーディングという手法です。これは、元のEmbarked列を「Embarked_S」「Embarked_C」「Embarked_Q」という3つの新しい列に分解する方法です。そして、乗船港がSの乗客は「Embarked_S」の列だけが1で他は0、Cの乗客は「Embarked_C」の列だけが1で他は0、といった具合に表現します。

アンケートで「あなたの出身地は? [ ]関東 [ ]関西 [ ]九州」のように、一つだけチェックを入れる形式に似ていますね。pandasなら、get_dummies()という命令で一瞬で変換できます。

# Embarked列をOne-Hotエンコーディングします
embarked_dummies = pd.get_dummies(train_df['Embarked'], prefix='Embarked')

# 元のデータ表に、新しく作成した3つの列を連結します
train_df = pd.concat([train_df, embarked_dummies], axis=1)

# 不要になった元のEmbarked列は削除します
train_df = train_df.drop('Embarked', axis=1)

# 変換後のデータを確認します
print(train_df.head())

表の右側にEmbarked_C, Embarked_Q, Embarked_Sという列が追加され、乗客ごとに出発した港の列だけが1になっているはずです。

   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   
3            4         1       1   
4            5         0       3   

                                                Name  Sex   Age  SibSp  Parch  \
0                            Braund, Mr. Owen Harris    0  22.0      1      0   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...    1  38.0      1      0   
2                             Heikkinen, Miss. Laina    1  26.0      0      0   
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)    1  35.0      1      0   
4                           Allen, Mr. William Henry    0  35.0      0      0   

             Ticket     Fare Cabin  Embarked_C  Embarked_Q  Embarked_S  
0         A/5 21171   7.2500   NaN           0           0           1  
1          PC 17599  71.2833   C85           1           0           0  
2  STON/O2. 3101282   7.9250   NaN           0           0           1  
3            113803  53.1000  C123           0           0           1  
4            373450   8.0500   NaN           0           0           1  

お疲れ様でした!これで私たちの船(データ)は、欠損値の穴が塞がり、文字の荷物もきちんと数字のコンテナに整理されました。いよいよ、新しいエンジン(機械学習モデル)を搭載する準備が整ったのです!

次の章では、このピカピカに磨き上げたデータを使って、いよいよ本格的な予測モデルを構築していきます。私たちのスコアは、最初の基準点からどれだけ向上するのでしょうか?ご期待ください!

第四章:より強力な船を造る - 機械学習モデルの選択

さあ、いよいよこの航海のハイライトです!前章までの丁寧な作業で、私たちの船(データ)はピカピカに整備されました。欠損値という穴は塞がれ、文字だった積み荷はすべて数字という頑丈なコンテナに詰め替えられています。

準備は万端。今こそ、この船に強力なエンジン、すなわち「機械学習モデル」を搭載する時です!この章では、整備したデータを使って実際に予測を行い、最初の基準点だったスコア「0.76555」からどれだけ成長できるのかを体感していきましょう!

機械学習モデルってなんだろう?

そもそも「機械学習モデル」とは何者なのでしょうか?

これは、データの中から自動的に「ルール」や「パターン」を学習し、未知のデータに対して予測を行うための、いわば「賢い頭脳」のようなものです。

私たちはtrain.csvという、答え(生存したか否か)が書かれた教科書を持っていますよね。機械学習モデルは、この教科書を隅から隅まで読み込み、「こういう特徴(客室クラスが上で、女性で、子供で…)を持つ人は生存しやすい」「こういう特徴の人は亡くなりやすい」といった無数の法則を、自らの中に蓄積していきます。そして、その学習した知識を使って、答えが書かれていないtest.csvという名の「本番の試験問題」に挑むのです。

最初のモデルからの卒業:「決定木」という新しいエンジン

私たちが最初に搭載するエンジンは「決定木(Decision Tree)」という、非常にポピュラーで分かりやすいモデルです。

決定木を例えるなら、「質問形式のフローチャート」そのものです。

モデルは、乗客のデータに対して「その乗客は女性ですか?」というような質問を投げかけます。「YES」なら次の質問へ、「NO」なら別の質問へ…と、木の枝が分かれていくように質問を繰り返します。そして、最終的に「生存」または「死亡」という結論の葉にたどり着くのです。

このモデルの素晴らしい点は、モデルがどんなルールを学習したのかを人間が目で見て理解しやすいことです。まさに「ガラス張りのエンジン」と言えるでしょう。

さあ、この決定木エンジンを私たちの船に組み込んでみましょう!ここからは、scikit-learnという、Pythonで機械学習を行う際の超強力なライブラリを使います。

ステップ1:データ(エンジン燃料)の準備

まず、モデルに学習させる「特徴量(説明変数)」と、予測したい「目的(目的変数)」をはっきりさせます。

  • 特徴量 (X): 予測の手がかりとなるデータ。今回はPclassSexAgeなどを使います。(これが「試験問題」です)
  • 目的 (y): 予測したい答え。今回はSurvivedです。(これが「模範解答」です)
# scikit-learnから決定木モデルをインポートします
from sklearn.tree import DecisionTreeClassifier

# 今回予測に使う特徴量(列)を選びます
# NameやTicketなど、まだ処理していない列は一旦除外します
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked_C', 'Embarked_Q', 'Embarked_S']

# 訓練データから、特徴量(X_train)と目的(y_train)を取り出します
X_train = train_df[features]
y_train = train_df['Survived']

# 決定木モデルのインスタンス(実体)を作成します
# random_stateは、実行のたびに結果が変わらないようにするための「おまじない」です
model = DecisionTreeClassifier(random_state=42)

# モデルに訓練データを学習させます!fitという命令が「学習せよ!」という指示です
model.fit(X_train, y_train)

たったこれだけです!今、modelという変数の中には、タイタニックの生存ルールを学習した賢い頭脳が出来上がりました。

ステップ2:本番の試験に挑戦!

次に、学習済みのモデルを使って、test.csvの乗客たちの運命を予測させます。

ここで超重要! テストデータにも、訓練データと全く同じ特徴量エンジニアリング(欠損値の補完、文字の数値化)を施してあげなければ、モデルは混乱してしまいます。料理のレシピと同じで、下ごしらえは同じ手順で行う必要があります。

(※ここではコードは省略しますが、第三章で行ったAgeの中央値での補完やSexの数値化などを、test.csvを読み込んだデータフレームに対しても同様に行ってください。)

# (test_dfにも同様の前処理を行ったと仮定します)
# X_test = test_df[features] のようにテストデータの特徴量を用意

# 学習済みモデルで、テストデータの生存予測を行います
# predictions = model.predict(X_test)

ステップ3:結果を提出しよう!

予測が完了したら、第一章でやったように提出用のファイルを作成し、Kaggleに提出してみましょう!

どうでしたか?スコアは上がりましたか?おそらく、0.77〜0.78あたりの、ベースラインを上回るスコアが出たはずです!自分で行ったデータの前処理と、選んだモデルが、確かに成果として現れた瞬間です。素晴らしい!

「三人寄れば文殊の知恵」作戦?もっと強力な「ランダムフォレスト」

決定木は素晴らしいモデルですが、一つの木だけで判断すると、少し不安定だったり、データの特定のパターンにこだわりすぎてしまったりする(過学習という状態です。これは次の章で詳しく!)弱点があります。

そこで、もっと強力なエンジン「ランダムフォレスト(Random Forest)」を試してみましょう。

これは、「たくさんの決定木(森-Forest)を作って、それぞれの木の予測結果を多数決で決める」という手法です。これをアンサンブル学習と呼びます。

例えるなら、一人の専門家(一本の決定木)に意見を聞くのではなく、たくさんの専門家に意見を聞いて、最終的に一番多かった意見を採用するようなものです。「三人寄れば文殊の知恵」ということわざの通り、一つのモデルよりも、はるかに賢く、安定した予測が期待できるのです!

実装は驚くほど簡単です。scikit-learnがすべてよしなにしてくれます。

# ランダムフォレストモデルをインポートします
from sklearn.ensemble import RandomForestClassifier

# モデルをランダムフォレストに変えるだけ!
# n_estimatorsは、森の中に作る木の数です
forest_model = RandomForestClassifier(n_estimators=100, random_state=42)

# 同じデータで学習させます
forest_model.fit(X_train, y_train)

# 同じようにテストデータを予測し、提出します
# forest_predictions = forest_model.predict(X_test)

さあ、この結果を提出してみてください。おそらく、決定木よりもさらに良いスコアが出たのではないでしょうか?

おめでとうございます!あなたはついに、データの前処理からモデルの選択、学習、予測、そして提出という、データサイエンティストが行う一連のプロセスをすべて自分の手でやり遂げました。スコアが上がっていく喜びは、何物にも代えがたいですよね。

しかし、私たちの航海はまだ終わりません。今のスコアは、どれくらい信頼できるものなのでしょうか?もしかしたら、たまたま運が良かっただけかもしれません。

次の章では、モデルの性能を正しく評価するための航海術と、「過学習」というデータサイエンスの海に潜む危険なワナについて学んでいきましょう。

第五章:航海図の精度を上げる - モデルの評価と改善

やりましたね!前章では「決定木」そして「ランダムフォレスト」という強力なエンジンを搭載し、ついにベースラインを大きく超えるスコアを叩き出しました。自分の手でスコアが上がっていく、あの瞬間は本当に嬉しいものですよね!🥳

しかし、ここで一流の船乗りはこう考えます。「このスコアは、本当に信頼できるものだろうか?」「毎回Kaggleに提出して結果を確認するのは、少し効率が悪いな…」そして何より、「このモデル、もしかして目の前の訓練データにだけ詳しくなりすぎて、未知のデータに対応できない『井の中の蛙』になっていないだろうか?」

この章では、そんな疑問に答えるための、より高度な航海術を学びます。モデルの真の実力を測る「評価」の方法と、データサイエンスの海に潜む最も危険なワナ「過学習」について探検していきましょう!


危険なワナ!「過学習」に気をつけろ!

まず、私たちが最も警戒すべき過学習(Overfitting、かがくしゅう)という現象についてお話しします。

過学習とは、機械学習モデルが訓練データをあまりにも熱心に学習しすぎた結果、データに含まれる偶然のノイズや細かい特徴まで「完璧に」記憶してしまい、未知の新しいデータに対して全く対応できなくなってしまう状態を指します。

これは、学校のテスト勉強に例えると非常に分かりやすいです。

  • 良い学習者:教科書の本質的な概念や公式を理解しようとします。そのため、練習問題とは少し違う形式で出題される本番の試験でも、柔軟に応用を利かせて高得点を取ることができます。
  • 過学習の学習者:練習問題の「問題と答えのペア」を丸暗記してしまいます。その練習問題と全く同じ問題が出れば100点を取れますが、数字や聞き方が少しでも変わった応用問題が出た途端、全く手も足も出なくなってしまうのです。

私たちが目指すのは、もちろん前者ですよね。Kaggleのスコアは、私たちが持っていない未知のテストデータで採点されます。訓練データ(練習問題)で完璧なスコアを出せても、それが過学習の結果であれば、本番のスコアは惨憺たるものになってしまうのです。これは本当に恐ろしいワナなんです!


モデルの真の実力を測る羅針盤:「交差検証」

では、どうすれば「過学習」のワナを避け、モデルの本当の実力を知ることができるのでしょうか?毎回Kaggleに提出するのは大変ですし、提出回数には制限もあります。

そこで登場するのが交差検証(Cross-Validation、こうさけんしょう)という、非常に賢くて信頼性の高い評価手法です。

これは、手元にある訓練データ(train.csv)を、わざと「訓練用」と「ミニテスト用」に分割して、モデルの性能を疑似的にテストする方法です。

最も一般的なのが「5分割交差検証」です。以下の手順で行います。

  1. まず、訓練データ全体をランダムに5つのグループに分割します。
  2. 最初の4つのグループを訓練用データとしてモデルを学習させ、残りの1グループをミニテスト用データとしてスコアを計算します。
  3. 次に、ミニテストに使うグループを別のものに入れ替えて、同じように学習とテストを行います。
  4. これを5つのグループ全てが1回ずつミニテスト用データになるまで、合計5回繰り返します。
  5. 最後に、5回分のテストスコアの平均値を算出します。

どうでしょう?1回だけのテストよりも、5回分のテストの平均を取った方が、はるかに信頼性の高いスコアになりそうだと思いませんか?この平均スコアこそが、私たちのモデルが持つ「真の実力」に近い数値なのです。Kaggleに提出する前にこのスコアを見ることで、「よし、このモデルならスコアが上がりそうだ!」とか「うーん、この改善はあまり意味がなかったな…」といった判断ができるようになります。

scikit-learnを使えば、この交差検証も非常に簡単に行えます。

from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier

# 前の章で準備したX_train, y_trainを使います
# forest_model = RandomForestClassifier(n_estimators=100, random_state=42)

# cv=5と指定することで、5分割交差検証を実行します
scores = cross_val_score(forest_model, X_train, y_train, cv=5, scoring='accuracy')

# 5回分のスコアを見てみましょう
print(f'各分割のスコア: {scores}')

# 平均値と標準偏差(ばらつき具合)を見てみましょう
print(f'平均スコア: {scores.mean():.4f}')
print(f'スコアの標準偏差: {scores.std():.4f}')

この平均スコアが、あなたのモデルの信頼できる性能指標です。Kaggleのスコアとかなり近い値になることも多いですよ!


最後の仕上げ!「ハイパーパラメータチューニング」

さて、私たちの船には今や、強力なエンジン(ランダムフォレスト)と、その性能を正確に測る診断装置(交差検証)が備わりました。最後に、エンジンの性能を極限まで引き出すための「微調整」について触れておきましょう。

モデルには、私たちが事前に設定できる「つまみ」のようなものがいくつかあります。これをハイパーパラメータと呼びます。ランダムフォレストで言えば、森の中に作る木の数(n_estimators)や、一つ一つの木の最大の深さ(max_depth)などがこれにあたります。

ハイパーパラメータチューニングとは、この「つまみ」を色々と調整してみて、交差検証のスコアが最も高くなる最適な組み合わせを探し出す作業のことです。

料理に例えるなら、レシピ(アルゴリズム)通りに作るだけでなく、オーブンの温度や焼き時間(ハイパーパラメータ)を微調整して、最高のケーキを焼き上げる作業に似ていますね。このチューニングを行うことで、モデルの性能をさらに0.01、0.02と向上させることが可能になります。


お疲れ様でした!これであなたは、ただモデルを作るだけでなく、その性能を客観的に評価し、改善していくための高度な技術を手に入れました。これは、データサイエンティストとして非常に重要なスキルです。

私たちの船は今や、頑丈な船体を持ち、強力なエンジンと精密な診断装置を備えた、最高の一隻に仕上がりました。

さあ、いよいよ最後の章です。これまでの長い航海を振り返り、私たちがどれだけ成長したかを確認し、そして、この先に広がる広大なデータサイエンスの海を眺めてみることにしましょう。

終章:そして、新たな大海原へ - これからの君へ

私たちの、タイタニック号を巡る長かった航海も、いよいよこの記事の終着点にたどり着きました。ここまで本当にお疲れ様でした。もしあなたが、各章のステップを一つずつ踏みながらここまでたどり着いたのなら、あなたはもう、かつてのあなたではありません。

あなたは今、データサイエンスという大海原を自力で進むための、基本的な航海術をすべて身につけた、立派な船乗りなのですから。


これまでの旅路の振り返り

少しだけ、私たちが辿ってきた航路を振り返ってみましょう。

  • 序章と第一章では、私たちは期待と少しの不安を胸に、Kaggleという港から初めて船を出しました。海図も羅針盤も持たず、ただ「性別」だけを頼りに最初の提出を行い、0.76555という名の「現在地」を知りましたね。
  • 第二章では、データ探偵に変身しました。EDAという名の虫眼鏡を手に、データという名の海図を隅々まで調査し、「欠損値」という名の暗礁を発見しました。
  • 第三章では、腕利きのエンジニアになりました。特徴量エンジニアリングという名の工具を使い、暗礁を修復し、文字という不揃いな積み荷を、数字という規格化されたコンテナへと見事に整理整頓しました。
  • 第四章では、ついに船の心臓部であるエンジンを換装しました。「決定木」から、より強力な「ランダムフォレスト」へ。自分の手でスコアがぐんぐん上がっていく、あの興奮を覚えていますか?
  • そして第五章では、私たちはベテランの航海士へと成長しました。目に見えるスコアだけを信じる危うさを学び、「過学習」という嵐を避けるための「交差検証」という名の精密なレーダーを手に入れました。

この一連の旅を通じて、あなたは単にプログラミングのコードを学んだだけではありません。「課題を発見し、仮説を立て、データを加工し、モデルを構築し、客観的に評価する」という、データサイエンティストの思考プロセスそのものを、身をもって体験したのです。これこそが、この航海で得られた何よりの宝物です。


タイタニックの先にあるもの:今後の学習への道しるべ

タイタニック号での冒険は、チュートリアルとしては最高の教材ですが、データサイエンスの広大な世界は、ここからが本番です。この船旅を終えたあなたが、次に目指すべき新たな大陸や航路をいくつかご紹介しますね。

1. さらなる特徴量エンジニアリングの深淵へ

私たちの船には、まだ眠っているお宝が隠されています。

  • 名前(Name)から敬称を抽出する:'Mr.', 'Mrs.', 'Miss', 'Master.' といった敬称は、年齢や社会的地位、性別と強く関連していそうです。ここから新しい特徴量を作れないでしょうか?
  • 家族のサイズを計算するSibSp(兄弟姉妹/配偶者の数)とParch(親/子供の数)を足し合わせて、「家族の人数」という新しい特徴量を作れば、生存率と何か関係が見えてくるかもしれません。
  • チケット(Ticket)や客室番号(Cabin)の謎を探る:一見するとただの文字列に見えるこれらのデータにも、実はグループや客室の位置など、隠れた情報が眠っているかもしれません。

このように、既存のデータから新しい意味を見つけ出す創造的な作業は、特徴量エンジニアリングの醍醐味です。

2. より強力なエンジン(モデル)を求める旅

ランダムフォレストは強力なモデルですが、Kaggleの上位ランカーたちが愛用する、さらに強力なモデルが存在します。その代表格が勾配ブースティング(Gradient Boosting)です。

これは、一つのか弱い決定木から始め、その決定木が間違えた部分を次の決定木が一生懸命修正し…というプロセスを繰り返して、徐々に賢いモデルを育てていくアンサンブル学習の一種です。XGBoostLightGBMといったライブラリが有名で、多くのコンペで圧倒的な性能を誇ります。ぜひ、次の冒険の武器として調べてみてください。

3. 新たなコンペティションという大海原へ

タイタニック(分類問題)をマスターしたなら、次は「住宅価格の予測(回帰問題)」など、少し毛色の違うコンペに挑戦してみるのがおすすめです。Kaggleには、面白くて学びの多いコンペがたくさんあります。怖がらずに、どんどん新しい海へ漕ぎ出してみてください!


データサイエンスの冒険はまだ始まったばかり!

このシリーズを最後まで読んでくださり、本当にありがとうございました。

データサイエンスの旅は、一つの答えを暗記する旅ではありません。常に新しい問いを見つけ、試行錯誤を繰り返し、昨日よりも少しだけ賢い自分に出会う、終わりのない冒険です。あなたがこのタイタニックの航海で手に入れた羅針盤は、Kaggleの世界だけでなく、きっとあなたのこれからの人生においても、物事を論理的に考え、データに基づいて判断するための、力強い道しるべとなってくれるはずです。

データサイエンスの海図は、まだ白い部分ばかりです。そこには、あなたにしか発見できない宝島が、無数に眠っています。

またいつか、この広大な海のどこかで、成長したあなたとお会いできる日を楽しみにしています。

それでは、素晴らしい冒険を!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。