忍者ブログ
統計、機械学習、AIを学んでいきたいと思います。 お役に立てば幸いです。

【Kaggle挑戦記】Spaceship Titanic 攻略 #3:丸腰で初提出 0.78723。重要度から見えた「金」と「運命」の相関

Titanicでの反省を活かし、今回のSpaceship Titanicでは「最初から作り込まない」Baseline構築作戦を敢行しました。Macのターミナルで最小限の前処理コードを走らせ、いきなり提出まで完走。その結果、驚くべき事実が見えてきました。

1. 【実装】一切の細工を排した初手コード

まずは「機械学習モデルがエラーを吐かずに動くこと」だけを目的とした最短コードです。数値の欠損は中央値で、文字列は"Unknown"で埋め、一気にダミー変数化(数値化)しました。

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier

# 1. データの読み込み
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

# 2. 最小限の前処理(欠損値補完)
for df in [train, test]:
    num_cols = df.select_dtypes(include=['float64']).columns
    df[num_cols] = df[num_cols].fillna(df[num_cols].median())
    obj_cols = df.select_dtypes(include=['object']).columns
    df[obj_cols] = df[obj_cols].fillna('Unknown')

# 3. 特徴量の選択と数値化
features = ["HomePlanet", "CryoSleep", "Destination", "Age", "VIP", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
X = pd.get_dummies(train[features])
y = train["Transported"]
X_test = pd.get_dummies(test[features])
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

# 4. 学習・重要度の算出・予測
model = RandomForestClassifier(n_estimators=100, random_state=1)
model.fit(X, y)

# 重要度の出力
importances = pd.DataFrame({'feature': X.columns, 'importance': model.feature_importances_}).sort_values('importance', ascending=False)
print(importances.head(10))

# 5. 提出用ファイル出力
predictions = model.predict(X_test)
pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions}).to_csv('baseline_submission.csv', index=False)

2. 【実況】初提出スコアとターミナル出力

Macのターミナルを叩き、生成されたファイルをKaggleへ。返ってきたスコアは驚きの数値でした。

Public Score: 0.78723

そして、ターミナルが表示した「予測に貢献した項目(Feature Importances)」がこちらです。

 Feature Importances (Top 10):
              feature  importance
0                 Age    0.170933
4                 Spa    0.128971
5              VRDeck    0.117302
1         RoomService    0.112501
2           FoodCourt    0.110814
3        ShoppingMall    0.101754
10    CryoSleep_False    0.077724
11     CryoSleep_True    0.074114
6    HomePlanet_Earth    0.032070
7   HomePlanet_Europa    0.019907

3. 分析:この宇宙船は「金」と「眠り」が支配している

このランキング結果は、Titanicとは全く異なる宇宙船のルールを教えてくれました。

  • 支出額が運命を分ける: 2位から6位まで、船内の娯楽施設(Spa, VRDeck等)への支払額が独占しています。豪華なサービスを受けていたかどうかが、転送(Transported)に直結しているという生々しい現実が見えます。
  • 年齢(Age)はやはり最強: 最も影響力があるのは年齢でした。これは世代間の何らかの傾向を示唆しています。
  • 冷凍睡眠(CryoSleep)の重要性: 文字通り、寝ていたかどうかも生存に大きく関わっています。
  • 出身星(HomePlanet)の影の薄さ: EarthやEuropaといった出身地の項目は、支出額に比べれば重要度が1/5〜1/10程度しかありません。

4. 次の作戦:貢献度の低い特徴量を「リストラ」する

Baselineが 0.787 という高い位置にセットされた今、次の一手は「引き算の美学」です。 今回の結果で重要度が低かった HomePlanetDestination(目的地)などをあえて外し、モデルから「ノイズ」を排除します。

さらに、バラバラになっている「支出額」を合計した「TotalSpend」という新項目を作ることで、モデルに本質的な判断材料を与える。過学習を避けつつ、スコアを 0.8 の先へ押し上げる戦いが始まります。さあ、頑張ろう!


一切の細工をしないからこそ、データの真実が浮かび上がる。これがKaggleの醍醐味です。次回、特徴量のリストラ編へ。


PR

【Kaggle挑戦記】Spaceship Titanic 攻略 #3:一切の細工なし。最小限の前処理で初提出 0.78723 をマーク!

1. 今回のミッション:最速で「Baseline」を構築せよ

前回、Macのターミナルでデータ構造をスキャンし、敵の正体(大量の欠損値と文字列データ)を把握しました。今回のミッションはシンプルです。「こねくり回さず、とにかくモデルを走らせる」こと。AIが計算できない「文字列」と「空欄(欠損値)」だけを力技で解消し、初提出まで一気に駆け抜けます。

2. 【実装】「動けばいい」の精神で行う最小限の前処理と予測

複雑な分析は後回し。まずは機械学習モデルがエラーを吐かないための最低条件である「欠損値補完」と「数値化(ダミー変数化)」だけを行い、CSV出力まで一気に進めます。

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier

# 1. データの読み込み
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

# 2. 最小限の前処理
# 数値型は中央値で、文字列(object)型は"Unknown"で埋める
for df in [train, test]:
    num_cols = df.select_dtypes(include=['float64']).columns
    df[num_cols] = df[num_cols].fillna(df[num_cols].median())
    
    obj_cols = df.select_dtypes(include=['object']).columns
    df[obj_cols] = df[obj_cols].fillna('Unknown')

# 3. 特徴量の選択と数値化
features = ["HomePlanet", "CryoSleep", "Destination", "Age", "VIP", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
X = pd.get_dummies(train[features])
y = train["Transported"]
X_test = pd.get_dummies(test[features])

X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

# 4. ランダムフォレストで学習
model = RandomForestClassifier(n_estimators=100, random_state=1)
model.fit(X, y)

# 5. 特徴量の重要度を表示
importances = pd.DataFrame({
    'feature': X.columns,
    'importance': model.feature_importances_
}).sort_values('importance', ascending=False)

print("\n Feature Importances (Top 10):")
print(importances.head(10))

# 6. 提出用ファイルの作成
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions})
output.to_csv('baseline_submission.csv', index=False)
print("\n✅ submission file 'baseline_submission.csv' has been saved!")

3. 結果:丸腰で叩き出した驚きのスコア

Macのターミナルで生成されたCSVをKaggleへアップロードした結果、驚くべき数字が返ってきました。

Public Score: 0.78723

Titanicの時にあれほど苦労して到達した 0.78 という壁を、初手の「丸腰状態」であっさりと超えてしまいました。データ量が多いことで、細かな前処理に頼らずともモデルがデータの傾向を正しく掴めている証拠です。

4. 考察:重要度(Importance)が示す次へのヒント

エンジニア的な視点:
今回の前処理は「Object型を数字に変える」「欠損値を埋める」の2点のみ。それだけでこれほどのスコアが出るなら、今後の伸び代は計り知れません。
ターミナルに出力された「Feature Importances」を見ると、どの項目が生存(転送)を分けたのかが明白になります。もし特定の娯楽施設の利用額が強烈に効いているなら、そこを深掘りし、逆に全く効いていない項目があれば、それはノイズとして排除すべき「リストラ候補」です。


基準点(Baseline)が 0.78723 という高い位置にセットされました。次回の攻略では、この重要度ランキングを元に、不要な特徴量を削ぎ落とす「引き算」のプロセスに入ります。宇宙船の謎を解く戦いは、最高の滑り出しを記録しました。さあ、頑張ろう!


【Kaggle挑戦記】Spaceship Titanic 攻略 #2:まずは「丸腰」で挑む。Baseline構築作戦

1. 今回の作戦:なぜ「何もしない」から始めるのか?

Titanicでの試行錯誤を経て、今回のSpaceship Titanicでは「最初から作り込まない」という戦略をとります。名付けて『Baseline(基準点)構築作戦』です。

あえて高度な前処理や欠損値の精査をスキップし、まずは最小限の手間で予測モデル(ランダムフォレスト)を走らせます。その狙いは以下の通りです。

  • 基準(Baseline)の測定: 何もしていない状態のスコアを把握し、後で行う加工に「どれだけ意味があったか」を数値で比較可能にする。
  • 不要な特徴量の早期リストラ: ランダムフォレストの「特徴量の重要度(Feature Importance)」を算出し、予測に寄与していない項目をあらかじめ特定して排除する。
  • 過学習の抑制: Titanicでは項目を増やしすぎて自爆した反省を活かし、今回は「引き算」の思考で必要最低限のデータを見極める。

まずは現状把握のため、Macのターミナルから乗客名簿のデータ構造を確認します。

2. 【実装】データ構造の基本スキャン

作業はすべてMacのターミナル上で行い、Pythonでデータの概要を抽出しました。

import pandas as pd

# 1. データの読み込み
train = pd.read_csv('train.csv')

print("\n Spaceship Titanic Data Scan Started...\n")

# 2. データ項目(カラム)の一覧と型を確認
print("--- [1] Data Columns & Types ---")
print(train.info())

print("\n" + "="*50 + "\n")

# 3. 欠損値の有無を確認
print("--- [2] Missing Values Scan ---")
null_counts = train.isnull().sum()
print(null_counts[null_counts > 0]) # 欠損がある項目だけを表示

print("\n" + "="*50 + "\n")

# 4. ターゲットの分布を確認
print("--- [3] Target Distribution (Transported) ---")
print(train['Transported'].value_counts())

3. 【実行結果】ターミナルから得られたログ

Macのターミナルで実行した結果、以下の情報が得られました。これが今回の分析のスタート地点となります。

 Spaceship Titanic Data Scan Started...

--- [1] Data Columns & Types ---
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8693 entries, 0 to 8692
Data columns (total 14 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   PassengerId   8693 non-null   object 
 1   HomePlanet    8492 non-null   object 
 2   CryoSleep     8476 non-null   object 
 3   Cabin         8494 non-null   object 
 4   Destination   8511 non-null   object 
 5   Age           8514 non-null   float64
 6   VIP           8490 non-null   object 
 7   RoomService   8512 non-null   float64
 8   FoodCourt     8510 non-null   float64
 9   ShoppingMall  8485 non-null   float64
 10  Spa           8510 non-null   float64
 11  VRDeck        8505 non-null   float64
 12  Name          8493 non-null   object 
 13  Transported   8693 non-null   bool   
dtypes: bool(1), float64(6), object(7)

--- [2] Missing Values Scan ---
HomePlanet      201
CryoSleep       217
Cabin           199
Destination     182
Age             179
VIP             203
RoomService     181
FoodCourt       183
ShoppingMall    208
Spa             183
VRDeck          188
Name            200

--- [3] Target Distribution (Transported) ---
Transported
True     4378
False    4315

4. データの「素顔」をどう読み解くか?

出力されたログの注目すべきポイントを整理します。

① 謎の「Object型」の正体

Dtype 列にある object。これはデータが「文字列(テキスト)」であることを意味します。 AIモデルは数値しか扱えないため、この object 項目はそのままでは学習に使用できません。「Earth→1、Europa→2」のように数値に置き換えるか、ダミー変数化する処理が必須となります。全14項目のうち半分を占めるこれら7項目の扱いが、最初の関門です。

② 欠損値(Missing Values)の特異性

--- [2] Missing Values Scan --- の数値が示す通り、今回は非常に特徴的な欠落をしています。

  • 「均一な欠損」: 特定の項目に穴が集中しているのではなく、ほぼすべての項目において 200件前後(約2.3%)が欠落しています。これはシステム的な要因で一律にデータが欠落した可能性を示唆しています。
  • 連動性の仮説: 欠損数が全項目で近いことから、ある項目が欠けている乗客は、他の項目も同時に欠けているといった「欠損の連動」があるかもしれません。

③ ターゲット(Transported)のバランス

「飛ばされた(True)」のが 4,378人、「残った(False)」のが 4,315人。比率はほぼ 50%:50%。非常にバランスの良いデータであり、純粋にモデルの識別能力がスコアに反映されやすい環境です。

5. 今後のステップ:丸腰での初予測へ

約8,700件というデータ量は、Titanicの10倍近いです。まずはこれらの欠損を中央値や定数で一括補完し、文字列(object)をダミー変数化して、ランダムフォレストによる「Baseline」を叩き出します。最短ルートで予測を完了させ、次の一手を見極めます。


ターミナルに表示されたログを元に、離陸の準備を整えました。次はいよいよ、一切の細工を排除した「丸腰予測」へと向かいます。さあ、頑張ろう!

【DS検定対策】文章生成の舞台裏!「自己回帰モデル」の仕組みを解明

ChatGPTなどの大規模言語モデルが、滑らかな文章を書けるのはなぜでしょうか?その核心にあるのは、過去の自分の出力を次の入力に使う「自己回帰モデル」という考え方です。

1. 【 問題 】

生成モデルの一種で、過去の生成データ(自分が出力した単語など)を次の入力として利用し、時系列に従って順番に次のデータを予測・生成していくモデルを何と呼ぶでしょうか?

① 拡散モデル(Diffusion Model)
② 自己回帰モデル(Autoregressive Model)
③ 敵対的生成ネットワーク(GAN)
④ 変分オートエンコーダ(VAE)


2. 【 解答 】

正解: ② 自己回帰モデル(Autoregressive Model)

3. 整理:一つ前の単語が次の単語を呼ぶ

自己回帰モデルは、前の状態に依存して次の状態が決まる「しりとり」のような仕組みでデータを生成します。

【 自己回帰による文章生成のイメージ 】

[ ステップ 1 ]
入力:「今日は」 → 予測:「天気」

[ ステップ 2 ]
入力:「今日は 天気」 → 予測:「が」

[ ステップ 3 ]
入力:「今日は 天気が」 → 予測:「良い」

★ ここが自己回帰!
自分が生み出した「天気」や「が」を、次の予測の材料として再利用(回帰)しています。

--------------------------

特徴: 文頭から文末に向かって、一度に一つずつ順番に生成していく(逐次生成)のが大きな特徴です。

4. 代表的なモデルとメリット

1. GPT(Generative Pre-trained Transformer): まさに「自己回帰型」の代表格です。左から右へと単語を予測することに特化しています。
2. 文脈の維持: 直前までの流れをすべて考慮して次の単語を選ぶため、非常に自然で一貫性のある文章が作れます。
3. 推論コスト: 1単語出すたびに計算を繰り返す必要があるため、一度に全体を出すモデルに比べると生成に時間がかかる側面もあります。


5. DS検定形式:実戦4択クイズ

問:自己回帰モデル(ARモデル)の性質として、最も適切なものはどれか。

① 画像全体を一気に同時に生成する手法である。
② 現在の値を、過去の自分自身の値の線形結合などで表すモデルである。
③ 正解ラベルを予測する「分類」にのみ特化した手法である。
④ ノイズを少しずつ除去することでデータを復元する手法である。

【 正解: ② 】

解説: 自己回帰(Auto-Regressive)の「自己」は自分自身を、「回帰」は過去の値から現在の値を予測することを指します。統計学の時系列分析から発展し、現在の言語モデルの基盤となりました。


6. まとめ

DS検定において「過去の出力を次の入力に使う」「順番に予測する」というキーワードが出たら「自己回帰モデル」が正解です。GPTの「G(Generative)」の仕組みそのものであるこの概念を、しっかりマスターしておきましょう!

【DS検定対策】直線では分けられない!?「線形分離不可能」を攻略せよ

データを「○」と「×」に分けるとき、定規で一本の線を引くだけで完璧に分類できるとは限りません。この「一本の線ではどうにもならない状態」を理解しましょう。

1. 【 問題 】

2つのクラスに属するデータ群において、直線(または平面や超平面)を引くことだけでは、それらを完全に2つに分けることができない状態を何と呼ぶでしょうか?

① 線形分離可能
② 線形分離不可能
③ 特徴量不足
④ 多重共線性


2. 【 解答 】

正解: ② 線形分離不可能

3. 整理:一本の線では限界がある世界

単純な「線形モデル」は、境界線が真っ直ぐである必要があります。しかし、現実のデータはもっと複雑に絡み合っています。

【 線形分離不可能な例:XOR(排他的論理和)問題 】

[ データの配置イメージ ]
(0,1)は○ 、(1,0)は○
(0,0)は× 、(1,1)は×

[ 分類に挑戦 ]
・横に線を引いても、どちらかに○と×が混ざる。
・縦に線を引いても、やはり混ざる。
・斜めに引いてもダメ。

★ これが線形分離不可能!
どうしても「曲がった線」や「囲むような線」でないと分けられません。

--------------------------

重要: 単層パーセプトロンという初期のモデルは、この「線形分離不可能」な問題を解けないことが大きな壁となりました。

4. どうやって解決するのか?

1. 多層化(ディープラーニング): ニューラルネットワークを何層にも重ねることで、複雑な「曲がった境界線」を作り出します。
2. カーネル法: データを高次元の空間に飛ばすことで、元の空間では曲がっていた境界線を、高次元空間で真っ直ぐな面(超平面)として扱えるようにします(SVMなどで利用)。
3. 特徴量エンジニアリング: データの組み合わせを変えることで、分離しやすく加工します。


5. DS検定形式:実戦4択クイズ

問:線形分離不可能な問題を解決するために、ニューラルネットワークに導入される「非線形な変化」を生み出すための関数を何と呼ぶか。

① 損失関数   ② 活性化関数   ③ 目的関数   ④ 線形関数

【 正解: ② 】

解説: シグモイド関数やReLUなどの「活性化関数」を通すことで、ネットワークに非線形な表現力が加わります。これによって、線形分離不可能な複雑なデータも分類できるようになるのです。


6. まとめ

DS検定において「直線や平面で分割できない」という定義が出たら「線形分離不可能」です。この限界を知ることで、なぜ今のAIが「多層(ディープ)」である必要があるのか、その理由がより明確に見えてきます!