2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Titanic データでAIモデルを徹底比較してみた【pandas × RandomForest × LightGBM × SHAP】

Last updated at Posted at 2025-12-21

Titanic データを使って AIモデルを比較してみた【pandas × RandomForest × LightGBM × SHAP】

📗対象読者:

  • pandas / sklearn を触り始めた人
  • 「モデル比較」や「SHAP」に興味がある人
  • Kaggle Titanic を一度はやったことがある人

💡この記事を読むと分かること:

  • pandas でデータを分析する基本
  • 可視化でデータの傾向をつかむ方法
  • ランダムフォレストで分類モデルを作る流れ
  • LightGBM と他モデルの違い
  • SHAP を使って AI の判断を可視化する方法

使用環境は以下です。

ツール 役割
MacBook Pro(Apple Silicon) 実行マシン
Python 3 データ分析のメイン言語
Anaconda Python パッケージ管理・仮想環境の管理ツール
Jupyter Notebook コードを実行しながら説明を書ける開発環境
pandas データの読み込み・加工・前処理
matplotlib グラフ可視化
scikit-learn AIモデル(ランダムフォレスト / ロジスティック回帰など)
LightGBM 高性能な機械学習モデル(決定木ベース)
SHAP 「AI が何を重視したか」を可視化するライブラリ

仕事用PCは当たり前ですが、入れていいソフトなのか会社の規程や諸々を確認してからインストールしてください。


📦 1. データの読み込み

Titanic のデータは Kaggle などで公開されていますが、今回は GitHub 上の同等データを使用します。

import pandas as pd

url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url)

df.head()

🔍 2. データの概要を確認する

df.info()
df.describe()

主な特徴量は以下:

カラム 意味
Survived 0 = 死亡、1 = 生存
Pclass 客室クラス
Sex 性別
Age 年齢
Fare 運賃
Embarked 乗船港

image.png

📊 3. 生存者の分布を可視化する

import matplotlib.pyplot as plt

df["Survived"].value_counts().plot(kind="bar")
plt.title("Survival Count")
plt.xlabel("Survived (0=Dead, 1=Alive)")
plt.ylabel("Count")
plt.show()

✔ グラフの意味

0 = 死亡者の人数

1 = 生存者の人数

Titanic では死亡者が多いため、0 の棒が高くなります。
image.png

🧪 4. 性別や客室クラスごとの生存率を比較

性別ごとの生存率

df.groupby("Sex")["Survived"].mean()

image.png


Pclass(客室クラス)別

df.groupby("Pclass")["Survived"].mean()

image.png

👉 女性・高級客室ほど生存率が高い傾向があることが分かります。

🤖 5. AI(ランダムフォレスト)で生存予測モデルを作る

まずは必要ライブラリを import:

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

特徴量の選択・前処理

X = df[["Pclass", "Sex", "Age", "Fare"]].copy()
X["Sex"] = X["Sex"].map({"male": 0, "female": 1})
y = df["Survived"]

# Age などの欠損値を平均値で補完する
X = X.fillna(X.mean())

学習用データとテストデータに分割

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

ランダムフォレストの学習

model = RandomForestClassifier()
model.fit(X_train, y_train)

精度確認

accuracy = model.score(X_test, y_test)
print("モデルの正解率:", accuracy)

出力:
image.png

👉 約79%の精度で生存/死亡を予測できた。

🧠 ランダムフォレストとは?

ランダムフォレストは機械学習の分類モデルで、

決定木(if の分岐のようなルール)を多数作り

それらの「多数決」で最終判断を行う

という AI モデルです。

  • まず「決定木」というのは、こんなルール型のモデル:
性別が女性?
     → はい → 生存しそう
     → いいえ(男性) → 年齢が10歳以下?
                             → はい → 生存しそう
                             → いいえ → 死亡しそう

これを ひとつの木(ルール)にしたものが Decision Tree(決定木)。

🌳 ランダムフォレストは、それを「何百本も作ってまとめて判断するAI」

1本の木だと偏った判断になりやすい

でも何百本も違う木を作り

みんなで多数決を取ることで精度が安定する

これが Random Forest(ランダムに作る森) の仕組みらしい

  • 予測が安定していて精度が高い
  • 初心者でも扱いやすい
  • 機械学習の中でも人気がある

🔥 ② ランダムフォレストで何が分析できる?

Titanic の例で言うと

ランダムフォレストは次のような「判断の傾向」を自然に学習する:

性別(女性)が生存に強く影響する

客室等級(Pclass)が高いほど生存しやすい

年齢が若いほど生存率が高い

料金(Fare)が高いほど生存率が高い

つまり、

  • 「どの要素が生存に大きく影響したか」
  • 「その要素を使ってどれくらい正しく予測できるか」

が分析できる。


🔥 6. 他のAIモデルとの性能比較(LR / RF / LightGBM)

ここからは「AIを使った分析」としての完成度を高めるために、
ランダムフォレスト以外のモデルも比較していきます。

比較するモデルは以下の3つです:

  • ロジスティック回帰(基準モデル)
  • ランダムフォレスト
  • LightGBM(勾配ブースティング:高性能AIモデル)

モデルごとの違い(簡単に)

モデル名 特徴
ロジスティック回帰 線形モデル。基準性能として使いやすい
ランダムフォレスト 多数の決定木を使った非線形モデル
LightGBM 高速・高精度で、大規模データにも強い。カテゴリ変数と欠損値にも比較的強い

🧪 比較用コード

※ 本来は標準化(StandardScaler)を行うことが望ましいですが、
 今回はモデル比較のシンプルさを優先しています。

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from lightgbm import LGBMClassifier
from sklearn.metrics import accuracy_score

# ① ロジスティック回帰
model_lr = LogisticRegression(max_iter=1000)
model_lr.fit(X_train, y_train)
pred_lr = model_lr.predict(X_test)
acc_lr = accuracy_score(y_test, pred_lr)

# ② ランダムフォレスト
model_rf = RandomForestClassifier()
model_rf.fit(X_train, y_train)
pred_rf = model_rf.predict(X_test)
acc_rf = accuracy_score(y_test, pred_rf)

# ③ LightGBM
model_lgb = LGBMClassifier()
model_lgb.fit(X_train, y_train)
pred_lgb = model_lgb.predict(X_test)
acc_lgb = accuracy_score(y_test, pred_lgb)

print("ロジスティック回帰:", acc_lr)
print("ランダムフォレスト:", acc_rf)
print("LightGBM:", acc_lgb)

LightGBM 実行時に以下の Warning が出ますが、エラーではなく正常動作です。

[LightGBM] [Warning] No further splits with positive gain, best gain: -inf

これは「これ以上分岐しても精度向上しないため、この木の成長を止めます」という内部処理です。

📈 モデル比較結果(この環境での実行結果)

モデル 正解率(Accuracy)
ロジスティック回帰 0.77
ランダムフォレスト 0.79
LightGBM 0.80

※ 数値は乱数シードや環境によって多少変動しますが、
おおよそ「ロジスティック回帰 < ランダムフォレスト < LightGBM」という関係は保たれている。

🔥 7. SHAP を使って「AIが何を重視したか」を可視化する(Explainable AI)

AIは「答えを出す」だけでなく
どうしてその予測になったのか?を説明できる必要があります。

そこで使うのが SHAP(SHapley Additive exPlanations) です。

  • SHAPの役割

AIがどの特徴をどれだけ重視したか

具体的にどの特徴量が生存確率を上げたのか・下げたのか

モデルの判断理由を人間が理解できる形で可視化

🧪 SHAPコード

まずインストール

pip install shap

Notebookで:

import shap

explainer = shap.TreeExplainer(model_lgb)
shap_values = explainer.shap_values(X_test)

shap.summary_plot(shap_values, X_test)

※ LightGBM(二値分類)の場合、shap_values はクラスごとの配列になるため、
 summary_plot では生存クラス(1)の SHAP 値が使用されます。

結果

※ 下図は本ノートブックで実際に生成した SHAP summary plot です。
image.png

この Warning は、
「LightGBM の二値分類モデルに対する SHAP の出力形式が変わりました」
という 仕様変更のお知らせなので問題ありません。

SHAP では、

  • 横軸:予測への影響度

  • 色:特徴量の値の大きさ
    を表します。

  • Sex の赤い点(= Sex の値が高い=女性)が右側に多い
    → 「女性であること」が生存確率を押し上げている

  • Fare や Age も、色のグラデーションを見ることで
    「どんな値のときに生存確率を上げているのか・下げているのか」がわかります

✨ SHAPの分析結果(解釈例)

一般的に Titanic では以下が上位に来ます:

Sex(性別) → 女性の方が生存確率が高い

Pclass(客室クラス) → 1等客室ほど生存しやすい

Fare(運賃) → 高いほど救命ボートに近かった可能性

Age(年齢) → 子どもは優先的に救助された

➡ AIがどの特性をどう判断したかが“可視化”できるのがSHAPの強み。

🧠 8. (本記事でやったこと)

本記事では Titanic データを使って、以下の分析を行いました。

pandas:データの確認・前処理

matplotlib:生存率の可視化

AIモデル(LR / RandomForest / LightGBM):生存予測

LightGBM が最も高い精度(0.80〜0.81)を達成

SHAP:モデルが重視した特徴(性別・客室クラス・運賃など)を可視化

機械学習の基本フロー(前処理 → モデル構築 → 比較 → 解釈)を一通り体験できる内容になっています。

(おまけ)🔧 9. LightGBM をチューニングして精度を改善してみた

LightGBM はパラメータを調整することで精度が向上することがあります。
ここでは、主要パラメータである n_estimators / learning_rate / num_leaves を調整してみます。

チューニングしたコード↓

from lightgbm import LGBMClassifier

model_lgb_tuned = LGBMClassifier(
    n_estimators=200,
    learning_rate=0.05,
    num_leaves=31,
    random_state=42
)

model_lgb_tuned.fit(X_train, y_train)
print("チューニング後の精度:", model_lgb_tuned.score(X_test, y_test))

※ random_state=42 は「乱数を固定して毎回同じ結果を再現する」ための設定です。

📈 チューニング結果(実測値)

image.png

チューニング後の精度: 0.8100558659217877

🔍 結果の考察

デフォルト LightGBM:0.80

チューニング後 LightGBM:0.81

Titanic のような小規模データでも、
+1% の精度向上 が確認できました。

🌟 チューニング結果の考察(どうして精度が上がった?)

n_estimators を増やした → 木の数が増え、表現力が上がる

learning_rate を下げた → 過学習を防ぎつつ丁寧に学習

num_leaves は適切な 31 を維持 → 木の複雑さを制御

これにより、過学習を避けながら性能を引き出せています。
(※ random_state=42 は「乱数を固定して毎回同じ結果を再現する」ための設定です)

🔍 10. 考察(AIでできること・難しいこと)

■ 今回わかったこと(Titanic の特徴)

性別(Sex)が圧倒的に重要

客室クラス(Pclass)や運賃(Fare)も強い影響

LightGBM のようなブースティング系モデルは
小規模データでも安定して高い精度を出す

■ AIでできること

過去データから高精度の予測

複雑な特徴量関係の自動学習

SHAP による「理由の説明」

モデル比較による最適解の選択

■ AIでも難しいこと

データが少ない場合の限界

災害など未知のケースへの対応

特徴量の質が悪いと精度が上がらない

完璧な予測は存在しない(過学習とのバランス)

Titanic のようなシンプルデータでは、
精度は 80%前後が天井 になることも確認できました。

感想🐈(今後への応用)

Titanic は小規模ながら、
モデル比較 × SHAP × チューニング を学ぶには最高の教材です。

今回の分析フローは、そのまま以下の実データにも応用できます:

家賃予測(不動産オープンデータ)
土地価格分析(地価公示)
電車混雑予測(公共交通オープンデータ)
人口予測(自治体データ)

Titanic で基礎を押さえたので、
次はより実務寄りのテーマで AI 分析をするのもおすすめです。
(未完成なので次回以降の記事にしてみようと思います)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?