<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" >
  <channel>
  <title>いけいけ機械学習</title>
  <link>http://learnms.blog.shinobi.jp/</link>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://learnms.blog.shinobi.jp/RSS/" />
  <description>統計、機械学習、AIを学んでいきたいと思います。 お役に立てば幸いです。</description>
  <lastBuildDate>Tue, 28 Apr 2026 10:37:21 GMT</lastBuildDate>
  <language>ja</language>
  <copyright>© Ninja Tools Inc.</copyright>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" />

    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #13：IDに隠された「絆」を解く。グループ人数と転送率の意外な相関&lt;</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. PassengerId の仕様から「集団」を定義する</h3>
<p>これまで乗客一人ひとりのスペック（年齢や支出）に注目してきましたが、今回は視点を広げ、乗客が属する「グループ」に着目しました。<code>PassengerId</code> の前半4桁を抽出し、同じIDを持つメンバーの数をカウント。新特徴量 <b>GroupSize</b> としてモデルに投入しました。</p>
<h3 style="color: blue;">2. 【実装】グループ解析機能付き・フルソースコード</h3>
<p>支出の論理補完、Cabinの物理分解、そして今回のグループサイズ抽出を統合したコードです。最後に、データの裏側を暴くための分析ログを出力するように設計しています。</p>
<pre style="border: 1px solid #ccc; padding: 15px; background-color: #f4f4f4; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; font-size: 13px; color: #333;">import pandas as pd
import numpy as np
import lightgbm as lgb

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

# グループサイズを正確に測るため全データを結合
all_df = pd.concat([train, test], axis=0)
all_groups = all_df['PassengerId'].apply(lambda x: x.split('_')[0]).value_counts()

# 2. 特徴量エンジニアリング
spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]

for df in [train, test]:
    # --- A. 支出の論理補完 ---
    df[spend_cols] = df[spend_cols].fillna(0)
    total_spend = df[spend_cols].sum(axis=1)
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend &gt; 0), 'CryoSleep'] = False
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend == 0), 'CryoSleep'] = True
    df['Age'] = df['Age'].fillna(df['Age'].median())

    # --- B. Cabinの物理分解 ---
    df['Cabin'] = df['Cabin'].fillna('U/U/U')
    df['Cabin_Deck'] = df['Cabin'].apply(lambda x: x.split('/')[0])
    df['Cabin_Side'] = df['Cabin'].apply(lambda x: x.split('/')[-1])

    # --- C. GroupSize（グループ人数）の抽出 ---
    df['Group_ID'] = df['PassengerId'].apply(lambda x: x.split('_')[0])
    df['GroupSize'] = df['Group_ID'].map(all_groups)

# 3. 学習の準備
features = ["CryoSleep", "Age", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck", "Cabin_Deck", "Cabin_Side", "GroupSize"]
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"].astype(int)
X_test = pd.get_dummies(test[features], drop_first=True)
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

# 4. モデル学習
model = lgb.LGBMClassifier(n_estimators=100, learning_rate=0.05, random_state=1)
model.fit(X, y)

# 5. 予測と保存
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions.astype(bool)})
output.to_csv('sub_v13_groupsize.csv', index=False)

# 6. 分析ログの出力
print("\n グループサイズ別 統計データ")
analysis = train.copy()
analysis['GroupSize'] = analysis['PassengerId'].apply(lambda x: x.split('_')[0]).map(all_groups)
summary = analysis.groupby('GroupSize')['Transported'].mean()
for size, rate in summary.items():
    print(f"グループ人数 {int(size)}人 : 転送率 {rate:.2%}")

print("\n 特徴量寄与度 (Importance)")
importances = pd.DataFrame({'Feature': X.columns, 'Importance': model.feature_importances_}).sort_values(by='Importance', ascending=False)
print(importances.head(15)) # 傾向把握のため上位15件を表示
</pre>
<h3 style="color: blue;">3. 結果と考察：データが語る「家族の運命」</h3>
<p>リーダーボードの結果は <b>0.80243</b>。前回のベストスコア（0.80406）には一歩届きませんでしたが、コンソールが出力した統計データには驚くべき事実が隠されていました。</p>
<pre style="border: 1px solid #ddd; padding: 15px; background-color: #eef2f7; color: #2c3e50; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #3498db;"> グループサイズ別 統計データ
グループ人数 1人 : 転送率 45.24%
グループ人数 2人 : 転送率 53.80%
グループ人数 3人 : 転送率 59.31%
グループ人数 4人 : 転送率 64.08%
グループ人数 8人 : 転送率 39.42%
</pre>
<p>1人旅の転送率が約45%なのに対し、4人家族（グループ）では64.08%と跳ね上がっています。一方で、8人の大家族になると39.42%まで急落します。「中規模な家族ほど、何らかの理由で揃って異次元へ転送されやすかった」というドラマチックな偏りが見て取れます。</p>
<h3 style="color: blue;">4. Importanceが示す「支出データの壁」</h3>
<p>スコアが伸び悩んだ理由は、モデルが弾き出した <b>Importance（重要度）</b> の数値に如実に表れていました。</p>
<pre style="border: 1px solid #ddd; padding: 15px; background-color: #f9f9f9; color: #333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;"> 特徴量寄与度 (Importance)
1. Spa           : 436
2. VRDeck        : 429
3. FoodCourt     : 414
4. Age           : 375
...
10. Cabin_Deck_E : 89
(GroupSize は圏外)
</pre>
<p>上位を占めるのは依然として <b>Spa, VRDeck, FoodCourt</b> といった「個人の状態」を示す支出データです。今回投入した <code>GroupSize</code> は、統計的な傾向（4人組は危ない、など）こそあるものの、LightGBMが「Spaに金を使っているかどうか」以上に優先すべき判断基準とは見なさなかったようです。</p>
<h3 style="color: blue;">5. まとめ：0.8突破のその先にある「壁」</h3>
<p>今回の実験で、宇宙船内の「社会的な繋がり」が運命を左右している確証は得られました。しかし、単なる「人数」という数字だけでは、支出データが持つ圧倒的な情報量には勝てないことも浮き彫りになりました。</p>
<p>「傾向はあるが、決め手にならない」。このジレンマを解消するには、次は単なる人数だけでなく、グループ内での「全員寝ていたか？」「全員同じデッキか？」といった、より深い関係性の抽出――つまり、集団としての「文脈」をさらに深掘りする必要がありそうです。</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/99/</link>
    <pubDate>Tue, 28 Apr 2026 10:37:21 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/99</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #12：最強タッグ「LGBM × XGBoost」結成。しかし、正解は一つとは限らない</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 次なる一手：二大巨頭のアンサンブル</h3>
<p>前回、物理情報「Cabin」の導入により、ついに 0.80406 という大台を突破しました。 さらなる高みを目指し、今回は Kaggle の定石である<b>「アンサンブル（学習器の平均化）」</b>に挑戦します。 単独で高スコアを出した鋭い LightGBM に、手堅い XGBoost を組み合わせることで、予測の「揺らぎ」を抑え、さらなる精度向上を狙いました。</p>
<h3 style="color: blue;">2. 【実装】アンサンブル・ハイブリッドモデル全文</h3>
<p>性格の違う2つのAIに「確率」を出させ、その平均をとる合議制ロジックです。Macのターミナルで実行した、今回のフルコードを公開します。</p>
<pre style="border: 1px solid #ccc; padding: 15px; background-color: #f4f4f4; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; font-size: 13px; color: #333;">import pandas as pd
import numpy as np
import lightgbm as lgb
import xgboost as xgb

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

# 2. 特徴量エンジニアリング（最高スコア時のロジックを継承）
spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]

for df in [train, test]:
    # 支出の論理補完
    df[spend_cols] = df[spend_cols].fillna(0)
    total_spend = df[spend_cols].sum(axis=1)
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend &gt; 0), 'CryoSleep'] = False
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend == 0), 'CryoSleep'] = True
    df['Age'] = df['Age'].fillna(df['Age'].median())

    # Cabinの分解（物理情報の追加）
    df['Cabin'] = df['Cabin'].fillna('U/U/U')
    df['Cabin_Deck'] = df['Cabin'].apply(lambda x: x.split('/')[0])
    df['Cabin_Side'] = df['Cabin'].apply(lambda x: x.split('/')[-1])

# 3. 特徴量の選定と整形
features = ["CryoSleep", "Age", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck", "Cabin_Deck", "Cabin_Side"]
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"].astype(int)
X_test = pd.get_dummies(test[features], drop_first=True)
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

# 4. モデル1：LightGBM の学習と確率予測
model_lgb = lgb.LGBMClassifier(n_estimators=100, learning_rate=0.05, random_state=1)
model_lgb.fit(X, y)
prob_lgb = model_lgb.predict_proba(X_test)[:, 1]

# 5. モデル2：XGBoost の学習と確率予測
model_xgb = xgb.XGBClassifier(n_estimators=100, learning_rate=0.05, max_depth=6, random_state=1)
model_xgb.fit(X, y)
prob_xgb = model_xgb.predict_proba(X_test)[:, 1]

# 6. アンサンブル（二人の予測確率を平均する）
final_prob = (prob_lgb + prob_xgb) / 2

# 7. 最終判定（0.5を閾値とする）
final_predictions = (final_prob &gt;= 0.5)

# 8. 保存
output = pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': final_predictions.astype(bool)})
output.to_csv('sub_v12_ensemble.csv', index=False)
</pre>
<h3 style="color: blue;">3. コンソールが示した「完璧な調和」</h3>
<p>実行後、コンソールに出力された数字は驚くほど均衡が取れていました。</p>
<pre style="border: 1px solid #ddd; padding: 15px; background-color: #eef2f7; color: #2c3e50; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #3498db;"> Ensemble Complete!
LGBM Mean Prob: 0.5029
XGB Mean Prob: 0.5039
</pre>
<p>学習データの正解割合 0.5036 に対して、両モデルとも極めて近い数値を算出。二つのAIが、どちらもデータの全体像（分布）を正確に捉えていたことがわかります。</p>
<h3 style="color: blue;">4. 結果と考察：安定を選んだ代償</h3>
<p>リーダーボードの結果は <b>0.80360</b>。前回（0.80406）からわずか 0.00046 の微減となりました。 なぜ「最強の二人」を混ぜたのに下がったのか？ここにはエンジニアリングの面白い側面があります。</p>
<ul>
<li><b>「尖った正解」がマイルドになった：</b> LightGBMがギリギリの判断で正解していた難問を、XGBoostの慎重な判断が打ち消してしまった可能性があります。</li>
<li><b>汎化性能の向上：</b> スコアは僅かに下がりましたが、平均確率が安定したことで、未知のデータに対して「大外し」しにくい、より頑健なモデルになったと言えます。</li>
</ul>
<h3 style="color: blue;">5. まとめ：次なるフロンティアへ</h3>
<p></p>
<p>「混ぜれば上がる」という神話を、自分のコードで検証した今回の実験。 0.8台を安定して出せるようになったことは大きな前進です。現在の特徴量においてアンサンブルが「安定」に寄ったということは、さらなるスコアアップには<b>「新たな特徴量」</b>が必要であるというサインでもあります。</p>
<hr />
<p>次は、もう一つの物理情報、<b>「グループ（PassengerId）」</b>の解析に切り込み、さらなる高みを目指します。<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/96/</link>
    <pubDate>Sun, 26 Apr 2026 21:17:55 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/96</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #11：ついに0.8突破！物理情報「Cabin」の導入が運命の分かれ道となった</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 前回の敗北から原点回帰へ</h3>
<p>前回、統計的な分布調整による「閾値最適化」に挑みましたが、結果は 0.79003 へのダウン。 エンジニアとしての仮説「学習データとテストデータの分布は同じはず」は間違っていないと確信しつつも、AIに与える「判断材料（特徴量）」そのものを強化する必要性を痛感しました。 そこで今回、満を持して投入したのが、船内の物理的な位置を示す <b>Cabin（客室番号）</b> です。</p>
<h3 style="color: blue;">2. 実装：ドメイン知識と物理情報の融合</h3>
<p>これまでの最高得点（0.79611）を出した「支出データからの睡眠状態逆算」というドメイン知識に基づく論理補完に、Cabinからパースした「Deck（デッキ）」と「Side（右舷・左舷）」を掛け合わせました。 Macのターミナルで実行した、今回の決定版コードがこちらです。</p>
<pre style="border: 1px solid #ccc; padding: 15px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; font-size: 13px;">import pandas as pd
import numpy as np
import lightgbm as lgb

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

# 2. 特徴量エンジニアリング（論理補完 ＆ Cabin分解）
spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]

for df in [train, test]:
    # --- A. 支出実績から CryoSleep を論理的に推論 ---
    df[spend_cols] = df[spend_cols].fillna(0)
    total_spend = df[spend_cols].sum(axis=1)
    
    # 支出があれば起きている(False)、なければ寝ている(True)
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend &gt; 0), 'CryoSleep'] = False
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend == 0), 'CryoSleep'] = True
    
    # 年齢の欠損値を中央値で補完
    df['Age'] = df['Age'].fillna(df['Age'].median())

    # --- B. Cabin（客室）を Deck/Num/Side に分解 ---
    df['Cabin'] = df['Cabin'].fillna('U/U/U')
    df['Cabin_Deck'] = df['Cabin'].apply(lambda x: x.split('/')[0])
    df['Cabin_Side'] = df['Cabin'].apply(lambda x: x.split('/')[-1])

# 3. 学習に使用する特徴量の選定
features = [
    "CryoSleep", "Age", "RoomService", "FoodCourt", 
    "ShoppingMall", "Spa", "VRDeck", "Cabin_Deck", "Cabin_Side"
]

# 4. データの整形（ダミー変数化）
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"].astype(int)
X_test = pd.get_dummies(test[features], drop_first=True)

# 列の整合性を整える
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

# 5. モデル学習（LightGBM）
model = lgb.LGBMClassifier(
    n_estimators=100, 
    learning_rate=0.05, 
    random_state=1
)
model.fit(X, y)

# 6. 予測と提出ファイルの出力
predictions = model.predict(X_test)
output = pd.DataFrame({
    'PassengerId': test['PassengerId'], 
    'Transported': predictions.astype(bool)
})
output.to_csv('submission_v11.csv', index=False)
</pre>
<h3 style="color: blue;">3. リーダーボードの結果：歓喜の瞬間</h3>
<p>Kaggleにファイルをアップロードし、リーダーボードが更新された瞬間、思わずガッツポーズが出ました。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #5cb85c;"> Previous Best : 0.79611
 New Score     : 0.80406 (0.8の壁を突破！)
</pre>
<h3 style="color: blue;">4. 考察：なぜ「Side」が効いたのか</h3>
<p>今回追加した「Cabin_Side（右舷・左舷）」は、事故の被害がどちらから来たかという物理的な衝突面をモデルに示唆しました。 「寝ていたか、起きていたか（状態）」&times;「船のどちら側にいたか（位置）」。 このミクロな情報の掛け合わせが、これまでのマクロな調整を凌駕し、ついに 0.80 の大台へと連れて行ってくれました。</p>
<hr />
<p>一つ一つの仮説を積み上げ、データで検証する。エンジニアとしての地道なアプローチが報われた瞬間でした。<br />
しかし、まだ上には上がいます。この勢いを止めることなく、さらなる高みを目指します。<br />
<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/92/</link>
    <pubDate>Sun, 26 Apr 2026 12:05:08 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/92</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #10：統計的補正の罠。AIの「楽観」を抑えた結果、見えてきたもの</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 独自の仮説：分布不変の原則</h3>
<p>LightGBMで 0.796 まで到達した今、次なる一手として<b>「学習データとテストデータの分布は同じはずだ」</b>という統計的な仮説を立てました。 AIが一律「0.5」という閾値で判断するなら、その結果としての True（転送された）の割合は、学習データの事実（50.36%）に一致すべき。もしズレているなら、閾値を動かして矯正すべきではないか、と考えたのです。</p>
<h3 style="color: blue;">2. 実装と、Macのターミナルが示した驚愕の数字</h3>
<p>AIに「確率」を出させ、上位50.36%だけを True と判定するように閾値を調整したところ、コンソールには衝撃的なログが流れました。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #5bc0de;"> 学習データの True 割合 (目標): 0.5036
...
[LightGBM] [Info] [binary:BoostFromScore]: pavg=0.503624 -&gt; initscore=0.014495
⚙️ 算出された最適な閾値: 0.5950
   (デフォルトの 0.5 から +0.0950 調整されました)
------------------------------
 調整後の予測 True 割合: 0.5036 (目標との差: 0.0000)
</pre>
<p>なんと、AI（LightGBM）をそのまま信じると、True の割合が統計的予測を大きく上回ってしまっていたのです。私は判定ラインを約10%引き上げ、<b>0.5950</b> という厳しい基準で「選別」を行いました。</p>
<h3 style="color: blue;">3. リーダーボードの結果：無情な 0.79003</h3>
<p>結果は、自己ベスト更新ならず。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #d9534f;"> Current Best (LightGBM) : 0.79611
 Ratio Adjusted Result    : 0.79003 (▼ 0.00608)
</pre>
<p>あえて統計に寄せた判断が、スコアを落とす結果となりました。</p>
<h3 style="color: blue;">4. 考察：なぜ「正論」が通じなかったのか？</h3>
<p>エンジニアとして、この結果から2つの教訓を得ました。</p>
<ul>
<li><b>テストデータの分布差：</b> 「学習用」と「テスト用」のデータ分布は、必ずしも完全一致するとは限らない。今回の事故では、テストデータ側の転送率は 50.36% より高かった可能性があります。</li>
<li><b>確率は「相対的」なもの：</b> AIが出す確率は「確信度」であって、絶対的な数値ではない。AIが 0.6 と言っても、それは「0.5の人よりは可能性が高い」という順位付けには有効ですが、その数値そのものを統計に当てはめるのは時期尚早だったのかもしれません。</li>
</ul>
<h3 style="color: blue;">5. それでも、方向性は間違っていない</h3>
<p>「0.5」というデフォルト設定を疑い、マクロな視点で補正を試みたことは、今後の複雑なコンペティションにおいて必ず活きる経験です。 AIに盲従せず、エンジニアとしての仮説をぶつけ、その反応をデータで確認する。 この試行錯誤こそが、0.8 への唯一の道。次はいよいよ、物理情報である<b>「Cabin（客室）」</b>のパースに挑みます。<br />
<br />
<br />
</p>
<hr />
<p>データは正直だ。そして、だからこそ面白い。<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/87/</link>
    <pubDate>Sun, 26 Apr 2026 08:04:50 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/87</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #9：最強の刺客 XGBoost 投入。しかし、LightGBM の牙城は崩せず</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 今回の挑戦：勾配ブースティングの「二大巨頭」対決</h3>
<p>LightGBMで <b>0.79611</b> という自己ベストを更新した前回。次なる一手として、Kaggleで不動の人気を誇るもう一つの最強エンジン、<b>XGBoost</b> を投入しました。 同じ「勾配ブースティング」という系譜に属しながら、計算の進め方（木の育て方）が異なるこの2つのアルゴリズム。どちらが今回の宇宙船タイタニックのデータと相性が良いのか、真剣勝負です。</p>
<h3 style="color: blue;">2. 【実装】XGBoost 換装モデル</h3>
<p>Macのターミナルで <code>pip install xgboost</code> を実行し、環境を構築。最高スコア時の前処理ロジックはそのままに、学習器だけを差し替えました。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">import xgboost as xgb

# 特徴量と前処理は最高スコア時を継承
model = xgb.XGBClassifier(
    n_estimators=100,
    learning_rate=0.05,
    max_depth=6,
    random_state=1,
    use_label_encoder=False,
    eval_metric='logloss'
)

model.fit(X, y)
# 予測結果を sub_xgboost_v1.csv として出力
</pre>
<h3 style="color: blue;">3. 実行結果：LightGBM の底力</h3>
<p>期待を込めて提出した結果、リーダーボードに刻まれた数字は意外なものでした。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #d9534f;"> LightGBM (Current Best) : 0.79611
 XGBoost (New Trial)    : 0.79448 (▼ 0.00163)
</pre>
<p>わずかな差ではありますが、XGBoostは前回の記録に届かず。今回のデータセットにおいては、LightGBMの方が「急所（重要な分岐）」をより的確に捉えていたようです。</p>
<h3 style="color: blue;">4. 考察：なぜ「同じ手法」で差が出たのか？</h3>
<p>どちらも「勾配ブースティング」ですが、その違いが結果に現れました。</p>
<ul>
<li><b>木の育て方の違い：</b> LightGBMは「誤差が大きい部分をピンポイントで掘り下げる（Leaf-wise）」のに対し、XGBoostは「層ごとにバランスよく育てる（Level-wise）」。今回のデータでは、LightGBMの尖った学習スタイルが有利に働いたと考えられます。</li>
<li><b>アルゴリズムの相性：</b> 特定の数値（支出額など）が重要な意味を持つこのコンペでは、LightGBMの高速で柔軟な分岐がフィットしたのでしょう。</li>
</ul>
<h3 style="color: blue;">5. 次なる一手：最強の「合体（アンサンブル）」へ</h3>
<p>XGBoostが負けたからといって、無駄だったわけではありません。エンジニアには<b>「アンサンブル（平均化）」</b>という必殺技が残されています。 LightGBMの予測とXGBoostの予測。性格の違う2つの知性を組み合わせることで、単体では届かなかった 0.8 の壁を突破できるかもしれません。</p>
<hr />
<p>失敗はデータの蓄積。次は「二人の知才」を一つに合わせて、大台を狙います。<br />
<br />
<br />
</p>]]>
    </description>
    <category>DS検定＞1. データサイエンス ＞1-1. 数理基礎・統計学 ＞1-1-2. 統計数理</category>
    <link>http://learnms.blog.shinobi.jp/Entry/84/</link>
    <pubDate>Sun, 26 Apr 2026 02:32:42 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/84</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #8：アルゴリズムの「換装」。LightGBM投入で自己ベストを更新せよ</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 今回の戦略：データの加工ではなく「エンジン」を変える</h3>
<p>前回、外れ値を削りすぎてスコアを落とすという「情報の欠損」を経験しました。そこから得た教訓は、<b>「複雑なデータは、より強力なアルゴリズムに委ねるべき」</b>ということ。 今回は、データのクリーニングは最高得点（0.792）時の最小限に留め、学習器を「ランダムフォレスト」から、現代のKaggle三種の神器の一つ<b>「LightGBM」</b>へと載せ替えました。</p>
<h4 style="background-color: #f0f0f0; padding: 10px;">なぜ LightGBM なのか？</h4>
<ul>
<li><b>勾配ブースティングの威力：</b> 一度に学習するランダムフォレストと違い、前のミスを修正するように段階的に学習するため、より緻密な境界線を見極められます。</li>
<li><b>外れ値への耐性：</b> データの「歪み」を無理に直さなくても、アルゴリズム側で最適に処理してくれます。</li>
</ul>
<h3 style="color: blue;">2. 【実装】最高得点ロジック ＋ LightGBM</h3>
<p>支出の論理補完は維持しつつ、学習エンジンを最新鋭に積み替えたコードです。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">import pandas as pd
import lightgbm as lgb

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

# 支出補完とCryoSleepの推論（最高スコア時のロジックを継承）
spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
for df in [train, test]:
    df[spend_cols] = df[spend_cols].fillna(0)
    total_spend = df[spend_cols].sum(axis=1)
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend &gt; 0), 'CryoSleep'] = False
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend == 0), 'CryoSleep'] = True
    df['Age'] = df['Age'].fillna(df['Age'].median())

# 特徴量準備
features = ["CryoSleep", "Age", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"].astype(int)
X_test = pd.get_dummies(test[features], drop_first=True)

# アルゴリズム変更：LightGBM
model = lgb.LGBMClassifier(n_estimators=100, learning_rate=0.05, random_state=1)
model.fit(X, y)

# 予測・提出
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions.astype(bool)})
output.to_csv('sub_lightgbm_v1.csv', index=False)
</pre>
<h3 style="color: blue;">3. 実行結果：壁を突き抜ける一撃</h3>
<p>Macのターミナルで実行し、生成されたファイルをKaggleへ。結果は、これまでの停滞を吹き飛ばすものでした。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #5cb85c;"> Random Forest (Best) : 0.79214
 LightGBM (New)       : 0.79611 (UP! )
</pre>
<p>ついに **0.796**。0.8という大台まで、あとわずか **0.004** ポイント。データの切り分け方を変えるのではなく、計算の「深さ」と「正確性」を上げたことが、この微差にして大きな前進を生みました。</p>
<h3 style="color: blue;">4. まとめ：エンジニアとしての決断</h3>
<p>「データの質」を追及することも大切ですが、時には「使う道具」を進化させることも重要だと痛感しました。LightGBMという新しい武器を手に入れた今、視界が開けました。 次は、この強力なエンジンに、これまで温めてきた<b>「Cabin（客室）の分解データ」</b>を流し込みます。物理的な位置情報が加われば、0.8突破は確実です。</p>
<hr />
<p>道具を磨き、知識を積み、一歩ずつ。Kaggleの頂は見え始めてきた。<br />
<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/83/</link>
    <pubDate>Sun, 26 Apr 2026 02:21:43 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/83</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #7：良かれと思った「外れ値除外」でスコアが急降下した話</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 今回の仮説：外れ値は「毒」である</h3>
<p>前回までで 0.79214 という自己ベストを記録していました。しかし、支出項目のデータ分布を見ると、ごく一部の乗客が数万ドルという極端な金額を使っています。 「これほどの外れ値は、モデルの判断を狂わせるノイズ（毒）に違いない」&mdash;&mdash;そう考えた私は、外れ値の基準を厳格化し、<b>上位5%（95パーセンタイル）で数値を一律カット</b>する強硬策に出ました。</p>
<h3 style="color: blue;">2. 実装した「徹底排除」コード</h3>
<p>以下が、あえて「失敗」を招くことになったコードの全文です。支出の上限をかなり低く設定しました。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier

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

# 支出項目の欠損値を0で埋め、合計を算出
spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
for df in [train, test]:
    df[spend_cols] = df[spend_cols].fillna(0)
    df['TotalSpend'] = df[spend_cols].sum(axis=1)

# 【ここが失敗の種】外れ値を95%タイルで厳格にクリッピング
for col in spend_cols:
    # 上位5%をカット。Spaなら1600ドル程度が上限に
    upper_limit = train[col].quantile(0.95)
    train[col] = train[col].clip(upper=upper_limit)
    test[col] = test[col].clip(upper=upper_limit)
    print(f"✂️ {col} の上限を {upper_limit:.1f} (95%) に設定")

# CryoSleepの論理補完とAgeの中央値補完
for df in [train, test]:
    df.loc[(df['CryoSleep'].isnull()) &amp; (df['TotalSpend'] &gt; 0), 'CryoSleep'] = False
    df.loc[(df['CryoSleep'].isnull()) &amp; (df['TotalSpend'] == 0), 'CryoSleep'] = True
    df['Age'] = df['Age'].fillna(df['Age'].median())

# 特徴量選択と学習
features = ["CryoSleep", "Age", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"]
X_test = pd.get_dummies(test[features], drop_first=True)
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)

model = RandomForestClassifier(n_estimators=100, random_state=1)
model.fit(X, y)

# 予測・提出
predictions = model.predict(X_test)
pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions}).to_csv('sub_clip_95.csv', index=False)
</pre>
<h3 style="color: blue;">3. 実行結果：Macのターミナルに突きつけられた現実</h3>
<p>意気揚々とKaggleに提出した結果、リーダーボードに表示された数字に目を疑いました。</p>
<pre style="border: 1px solid #dcdcdc; padding: 15px; background-color: #ffffff; color: #333333; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5; border-left: 5px solid #d9534f;"> Previous Score : 0.79214
 New Score      : 0.78185 (▲0.01029)
</pre>
<p>なんと、自己ベストから一気に **0.01 ポイントもの急落**。これまでの積み上げを台無しにするような、手痛い敗戦となりました。</p>
<h3 style="color: blue;">4. 考察：なぜ「外れ値」は必要だったのか？</h3>
<p>この失敗から、このコンペティションにおける重要な真実が見えてきました。 「超高額な支出をしている乗客」というのは、単なるノイズではありませんでした。<b>「高額な施設を頻繁に利用していた＝事故の瞬間に特定のエリアにいた」</b> という、転送（Transported）されるか否かを決める極めて重要なシグナルだったのです。</p>
<p>それを95%という低いラインで丸めてしまったことで、モデルは「重要人物」と「普通の客」の区別がつかなくなってしまった。ランダムフォレストは元々外れ値に強いアルゴリズムであり、人間が余計な手出しをするべきではありませんでした。</p>
<h3 style="color: blue;">5. 次なる一手</h3>
<p>「外れ値＝悪」という先入観は捨てました。次回は、この「数値の大きさ」という情報を残しつつ、まだ手付かずの<b>「Cabin（客室）」</b>データを分解し、物理的な位置関係から0.8の壁に再挑戦します。</p>
<hr />
<p>Kaggleは、自分の思い込みをデータが粉砕してくれる場所。この敗北を糧に、次はもっと賢いコードを書こう。攻略は続く。</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/80/</link>
    <pubDate>Sat, 25 Apr 2026 09:59:48 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/80</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #5：ドメイン知識の投入。支出額から「冷凍睡眠」を逆算せよ</title>
    <description>
    <![CDATA[<h3 style="color: blue;">1. 今回の作戦：欠損値を「推理」で埋めるハイブリッド戦略</h3>
<p>前回、項目を削ることで 0.79120 まで到達しました。さらなる高みを目指すため、今回は<b>「データの裏側にある事実」</b>をコードに落とし込みます。ターゲットは、最重要項目である「支出額」と「CryoSleep（冷凍睡眠）」の連動性です。</p>
<h4 style="background-color: #f0f0f0; padding: 10px;">宇宙船の物理法則（ドメイン知識）</h4>
<ul>
<li><b>事実1：</b> 施設利用（Spa等）のデータが欠損しているのは、単に「使っていない（0円）」からではないか？（中央値で埋めるのは不自然）</li>
<li><b>事実2：</b> 冷凍睡眠（CryoSleep）中の乗客はカプセル内で眠っており、物理的に1円も使えないはず。</li>
<li><b>結論：</b> まず支出額の欠損を「0」で埋め、その合計額が1円でもあれば「起きていた（False）」、0円なら「寝ていた（True）」と推論して、CryoSleepの欠損を埋める。</li>
</ul>
<h3 style="color: blue;">2. 【実装】支出と睡眠をセットで補完する「論理補完」コード全文</h3>
<p>「とりあえず埋める」から「根拠を持って埋める」へ。Macのターミナルで実行した、論理的整合性を重視したコードです。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">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. 支出系とCryoSleepの同時補完ロジック
for df in [train, test]:
    spend_cols = ["RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]
    
    # 【処理A】支出の欠損は「使っていない（0円）」とみなす
    df[spend_cols] = df[spend_cols].fillna(0)
    
    # 支出の合計を計算
    total_spend = df[spend_cols].sum(axis=1)
    
    # 【処理B】支出額からCryoSleep（冷凍睡眠）を逆算
    # 1円でも使っていれば、寝ているはずがない（False）
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend &gt; 0), 'CryoSleep'] = False
    # 合計0円なら、寝ていた可能性が極めて高い（True）
    df.loc[(df['CryoSleep'].isnull()) &amp; (total_spend == 0), 'CryoSleep'] = True

    # その他の項目（Ageなど）は中央値で補完
    df['Age'] = df['Age'].fillna(df['Age'].median())

# 3. 特徴量の選択（筋肉質な7項目）
features = ["CryoSleep", "Age", "RoomService", "FoodCourt", "ShoppingMall", "Spa", "VRDeck"]

# 学習データの準備（CryoSleepをTrue/Falseの2値に絞り込む）
X = pd.get_dummies(train[features], drop_first=True)
y = train["Transported"]
X_test = pd.get_dummies(test[features], drop_first=True)

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. 提出用ファイル出力
predictions = model.predict(X_test)
pd.DataFrame({'PassengerId': test['PassengerId'], 'Transported': predictions}).to_csv('sub_logic_hybrid.csv', index=False)
</pre>
<h3 style="color: blue;">3. 結果：論理の正しさが生んだ「微増」の意味</h3>
<p>Macのターミナルを叩き、運命の結果を確認しました。</p>
<div style="background-color: #f8f9fa; border-left: 5px solid #28a745; padding: 15px; margin: 20px 0;"><b style="font-size: 1.2em;">Public Score: 0.79214</b>（前回比 +0.00094）</div>
<p>数値としての伸びはわずかですが、エンジニアとしてこの結果には大きな意味を感じています。</p>
<ul>
<li><b>確信に変わった「0円」の意味：</b> これまで適当に埋めていた欠損値を論理的に埋めた上でスコアが上がったということは、この宇宙船のルール（ドメイン知識）を正しく捉え始めている証拠です。</li>
<li><b>逃げ道の封鎖：</b> 「Unknown」という不純物を消してなお精度が向上したことは、モデルがより普遍的なパターンを学習できていることを意味します。</li>
</ul>
<h3 style="color: blue;">4. 次のフェーズ：限界の先へ</h3>
<p>「引き算」も「欠損値の論理補完」もやり遂げました。Baselineは今、極限まで磨かれています。これ以上の精度向上を狙うには、いよいよ新しい情報の創造、つまり<b>「特徴量エンジニアリング（足し算）」</b>が必要です。</p>
<p>「個別の支出」ではなく「合計支出」はどう効くのか？あるいは「家族」の存在は？ 0.8の壁を突破するための、本質的なクリエイティビティの戦いが始まります。</p>
<hr />
<p>データの向こう側にある真実を一つずつ拾い集め、コードに落とし込む。地道な作業ですが、これが確実な勝利への唯一の道。さあ、頑張ろう！<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/79/</link>
    <pubDate>Sat, 25 Apr 2026 07:49:22 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/79</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #4：引き算の勝利！項目を削って 0.79120 へスコアアップ</title>
    <description>
    <![CDATA[【Kaggle挑戦記】Spaceship Titanic 攻略 #4：引き算の勝利！項目を削って 0.79120 へスコアアップ
<h3 style="color: blue;">1. 今回の作戦：ノイズを削り、モデルを研ぎ澄ませる</h3>
<p>前回の初提出で、0.78723というBaselineを記録しました。しかし、重要度を分析すると「HomePlanet」や「Destination」といった項目が足を引っ張っている（ノイズになっている）可能性が浮上しました。</p>
<p>そこで今回、あえて<b>「新しく何も足さず、効いていない項目を削るだけ」</b>というリストラ作戦を敢行。不純物を排除し、モデルが真に重要なデータだけに集中できる環境を作りました。</p>
<h3 style="color: blue;">2. 【実装】一切の無駄を省いた「リストラ実行コード」全文</h3>
<p>重要度の低かった <code>HomePlanet</code>, <code>Destination</code>, <code>VIP</code> を削除し、予測精度に寄与する「主力メンバー」だけに絞り込んだコードです。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">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. 特徴量の選択（重要度の低かった3つをリストラ）
# 予測のノイズになっていた HomePlanet, Destination, VIP を排除
features = ["CryoSleep", "Age", "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. ランダムフォレストで学習（100本の木で構築）
model = RandomForestClassifier(n_estimators=100, random_state=1)
model.fit(X, y)

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

print("\n New Feature Importances:")
print(importances)

# 6. 提出用ファイルの作成（CSV出力）
predictions = model.predict(X_test)
output = pd.DataFrame({
    'PassengerId': test['PassengerId'],
    'Transported': predictions
})
output.to_csv('sub_reduced_features.csv', index=False)
print("\n✅ Submission file 'sub_reduced_features.csv' saved.")
</pre>
<h3 style="color: blue;">3. 【実行結果】研ぎ澄まされた重要度とスコア</h3>
<p>結果は予想を上回るポジティブなものでした。MacのターミナルからKaggleへ提出した結果です。</p>
<div style="background-color: #f8f9fa; border-left: 5px solid #28a745; padding: 15px; margin: 20px 0;"><b style="font-size: 1.2em;">Public Score: 0.79120</b>（前回比 +0.00397）</div>
<p>そして、ターミナルに出力された「主力メンバー」たちの重要度がこちら。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #222; color: #0f0; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.2;"> New Feature Importances:
              feature  importance
4                 Spa    0.148013
0                 Age    0.139252
2           FoodCourt    0.133334
1         RoomService    0.127555
5              VRDeck    0.124744
7      CryoSleep_True    0.112372
6     CryoSleep_False    0.105997
3        ShoppingMall    0.105874
8   CryoSleep_Unknown    0.002859
</pre>
<h3 style="color: blue;">4. 考察：引き算がモデルを「覚醒」させた</h3>
<p>今回の実験で、<b>「情報の質」が「量」を凌駕する</b>ことが証明されました。項目を減らしたにも関わらずスコアが上がったのは、モデルがノイズに惑わされなくなり、真に影響力のある「支出額」や「年齢」の境界線をより正確に引けるようになったためです。</p>
<p>特にSpaやVRDeckなどの支出項目の重要度が軒並み上がり、モデルの武器が鋭利になったことがわかります。何も足さずに 0.791 を突破。いよいよ 0.8 の大台が射程圏内に入りました。</p>
<hr />
<p>「まず削る」。このシンプルなエンジニアリングが、宇宙船のデータに潜む真実を一つ暴きました。次回、筋肉質になったこのモデルに、「新たな筋肉（特徴量）」を足すフェーズへ。攻略は続きます。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/78/</link>
    <pubDate>Sat, 25 Apr 2026 07:33:50 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/78</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Spaceship Titanic 攻略 #3：丸腰で初提出 0.78723。重要度から見えた「金」と「運命」の相関</title>
    <description>
    <![CDATA[<p>Titanicでの反省を活かし、今回のSpaceship Titanicでは「最初から作り込まない」Baseline構築作戦を敢行しました。Macのターミナルで最小限の前処理コードを走らせ、いきなり提出まで完走。その結果、驚くべき事実が見えてきました。</p>
<h3 style="color: blue;">1. 【実装】一切の細工を排した初手コード</h3>
<p>まずは「機械学習モデルがエラーを吐かずに動くこと」だけを目的とした最短コードです。数値の欠損は中央値で、文字列は"Unknown"で埋め、一気にダミー変数化（数値化）しました。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #f9f9f9; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.5;">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)
</pre>
<h3 style="color: blue;">2. 【実況】初提出スコアとターミナル出力</h3>
<p>Macのターミナルを叩き、生成されたファイルをKaggleへ。返ってきたスコアは驚きの数値でした。</p>
<div style="background-color: #f8f9fa; border-left: 5px solid #28a745; padding: 15px; margin: 20px 0;"><b style="font-size: 1.2em;">Public Score: 0.78723</b></div>
<p>そして、ターミナルが表示した「予測に貢献した項目（Feature Importances）」がこちらです。</p>
<pre style="border: 1px solid #ccc; padding: 10px; background-color: #222; color: #0f0; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; line-height: 1.2;"> 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
</pre>
<h3 style="color: blue;">3. 分析：この宇宙船は「金」と「眠り」が支配している</h3>
<p>このランキング結果は、Titanicとは全く異なる宇宙船のルールを教えてくれました。</p>
<ul>
<li><b>支出額が運命を分ける：</b> 2位から6位まで、船内の娯楽施設（Spa, VRDeck等）への支払額が独占しています。豪華なサービスを受けていたかどうかが、転送（Transported）に直結しているという生々しい現実が見えます。</li>
<li><b>年齢（Age）はやはり最強：</b> 最も影響力があるのは年齢でした。これは世代間の何らかの傾向を示唆しています。</li>
<li><b>冷凍睡眠（CryoSleep）の重要性：</b> 文字通り、寝ていたかどうかも生存に大きく関わっています。</li>
<li><b>出身星（HomePlanet）の影の薄さ：</b> EarthやEuropaといった出身地の項目は、支出額に比べれば重要度が1/5〜1/10程度しかありません。</li>
</ul>
<h3 style="color: blue;">4. 次の作戦：貢献度の低い特徴量を「リストラ」する</h3>
<p>Baselineが 0.787 という高い位置にセットされた今、次の一手は<b>「引き算の美学」</b>です。 今回の結果で重要度が低かった <code>HomePlanet</code> や <code>Destination</code>（目的地）などをあえて外し、モデルから「ノイズ」を排除します。</p>
<p>さらに、バラバラになっている「支出額」を合計した「TotalSpend」という新項目を作ることで、モデルに本質的な判断材料を与える。過学習を避けつつ、スコアを 0.8 の先へ押し上げる戦いが始まります。さあ、頑張ろう！</p>
<hr />
<p>一切の細工をしないからこそ、データの真実が浮かび上がる。これがKaggleの醍醐味です。次回、特徴量のリストラ編へ。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>http://learnms.blog.shinobi.jp/Entry/77/</link>
    <pubDate>Sat, 25 Apr 2026 05:44:52 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/77</guid>
  </item>

    </channel>
</rss>