<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" >
  <channel>
  <title>いけいけ機械学習</title>
  <link>https://learnms.blog.shinobi.jp/</link>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="https://learnms.blog.shinobi.jp/RSS/" />
  <description>統計、機械学習、AIを学んでいきたいと思います。 お役に立てば幸いです。</description>
  <lastBuildDate>Sat, 04 Apr 2026 22:01:01 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>【DS検定対策】名前のワナを攻略！分類の王道「ロジスティック回帰」</title>
    <description>
    <![CDATA[<p>統計学や機械学習を学び始めると最初にぶつかる「名前の矛盾」。それが「ロジスティック回帰」です。なぜ回帰なのに分類なのか、その仕組みをスッキリ整理しましょう。</p>
<h3 style="color: blue;">1. 【 問題 】</h3>
<p>「ロジスティック回帰」に関する説明として、最も適切なものはどれでしょうか？</p>
<p>① 数値を予測する「回帰」の手法であり、住宅価格の予想などに用いられる。<br />
② データを2つのクラスに分ける「分類」の手法であり、ある事象が起こる確率を予測する。<br />
③ データのグループ化を行う「非教師あり学習」の手法である。<br />
④ 決定木をたくさん組み合わせた「アンサンブル学習」の手法である。</p>
<hr />
<h3 style="color: #d32f2f;">2. 【 解答 】</h3>
<div style="background-color: #eeeeee; border: 2px solid #333; padding: 15px; font-size: 1.2em; font-weight: bold; text-align: center;">正解： ② データを2つのクラスに分ける「分類」の手法</div>
<hr />
<h3 style="color: blue;">3. 整理：確率を計算して「境界線」を引く世界</h3>
<p>ロジスティック回帰は、入力データから「あるクラスに属する確率」を計算し、その値が0.5（50%）を超えたら「合格（1）」、そうでなければ「不合格（0）」のように判定します。</p>
<p>【 ロジスティック回帰の仕組みイメージ 】</p>
<div style="font-family: monospace; border: 1px solid #ccc; padding: 10px; line-height: 1.6;">[ 1. 入力データの計算 ]<br />
年齢や購入履歴などのデータを、線形式で計算する。<br />
<br />
[ 2. シグモイド関数を通す ]<br />
<b>★ ここが核心！</b><br />
どんな大きな値（または小さな値）も、<b>0 から 1 の範囲</b>にギュッと押し込める。<br />
<br />
[ 3. 確率の出力 ]<br />
「この客が購入する確率は <b>0.82 (82%)</b> です」と出力。<br />
<br />
[ 4. 分類 ]<br />
しきい値（0.5など）で区切り、「購入するクラス」に分類する。<br />
<br />
--------------------------<br />
<br />
◎ <b>ポイント： 計算過程で「数値を予測（回帰）」しているため名前に「回帰」と付きますが、目的は「分類」です。</b></div>
<h3 style="color: blue;">4. 覚えておくべき重要キーワード</h3>
<p>1. <b>シグモイド関数</b>: 出力値を0〜1の間に収めるための関数。S字型のカーブを描きます。<br />
2. <b>オッズ比</b>: ある事象が起こる確率と起こらない確率の比率。ロジスティック回帰の解釈に不可欠です。<br />
3. <b>二値分類</b>: 「Yes/No」「合格/不合格」など、2つのクラスに分けるのが基本です。</p>
<hr />
<h3 style="color: orange;">5. DS検定形式：実戦4択クイズ</h3>
<p><b>問：ロジスティック回帰において、出力（確率 $p$）を求める際に用いられる、以下の数式で表される関数を何と呼ぶか。</b><br />
$$f(x) = \frac{1}{1 + e^{-x}}$$</p>
<p>① ソフトマックス関数 &nbsp; ② シグモイド関数 &nbsp; ③ 恒等関数 &nbsp; ④ 階段関数</p>
<p><b>【 正解： ② 】</b></p>
<p><b>解説：</b> この数式は「標準シグモイド関数」と呼ばれ、ロジスティック回帰の心臓部です。$x$ がどんな値でも $f(x)$ は必ず 0 より大きく 1 より小さい値になるため、「確率」として扱うのに非常に適しています。</p>
<hr />
<h3 style="color: blue;">6. まとめ</h3>
<p>DS検定において「回帰という名前だが分類に使われる」「シグモイド関数で確率を出力する」という特徴が出たら、迷わずロジスティック回帰を選びましょう。シンプルながら解釈性が高く、今でもビジネス現場の第一線で使われている強力な手法です！</p>
<br />
<br />
<br />
]]>
    </description>
    <category>DS検定＞1. データサイエンス＞1-3. 機械学習＞1-3-1. 学習モデル</category>
    <link>https://learnms.blog.shinobi.jp/Entry/50/</link>
    <pubDate>Sat, 04 Apr 2026 22:01:01 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/50</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #11：血縁データの統合。「家族サイズ」が0.78の壁を打ち破る</title>
    <description>
    <![CDATA[<p>前回（攻略 #10）のデバッグでは、自作の「子供フラグ」がモデルにとって不純なノイズとなっていた現実を直視しました。今回はその反省を活かし、バラバラに存在していた「血縁データ」をロジカルに統合。ついに 0.78 の壁を突破する強力なヒント <b>FamilySize（家族人数）</b> を導入します。</p>
<h3 style="color: blue;">1. 今回の着眼点：孤立か、連帯か</h3>
<p>タイタニックのデータには、家族に関する項目が2つ用意されています。しかし、これらを別々に見ていては「その人がどれほどの集団で行動していたか」という実態が見えてきません。</p>
<ul>
<li><b>SibSp：</b> 兄弟、配偶者の数</li>
<li><b>Parch：</b> 両親、子供の数</li>
</ul>
<p>避難の際、1人で行動していたのか、あるいは守るべき家族がいたのか。この「群れ」の大きさを一つの指標として統合し、モデルに新たな視点を与えます。自分自身（+1）を足すことで、「1 = 単独客」「2以上 = 家族連れ」という、生存率を分ける明確な境界線が生まれます。</p>
<h3 style="color: blue;">2. 【実装】FamilySize導入とモデル構築の全コード</h3>
<p>属性別Age補完を継承しつつ、FamilySizeを計算してランダムフォレストに投入するまでの全工程です。</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
from sklearn.ensemble import RandomForestClassifier

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

# 2. Age（年齢）を Pclass&times;Sex の中央値で補完
group_cols = ['Pclass', 'Sex']
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))
test_data['Age'] = test_data['Age'].fillna(test_data.groupby(group_cols)['Age'].transform('median'))

# 3. 家族サイズ（FamilySize）の算出
train_data['FamilySize'] = train_data['SibSp'] + train_data['Parch'] + 1
test_data['FamilySize'] = test_data['SibSp'] + test_data['Parch'] + 1

# テストデータの Fare（運賃）の欠損値を中央値で補完
test_data['Fare'] = test_data['Fare'].fillna(test_data['Fare'].median())

# 4. 学習に使用する特徴量の定義
features = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "FamilySize"]

# カテゴリ変数のダミー変数化
X = pd.get_dummies(train_data[features])
y = train_data["Survived"]
X_test = pd.get_dummies(test_data[features])

# 5. モデルの構築と学習（木500本、深さ5）
model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)
model.fit(X, y)

# 6. 予測と提出ファイルの出力
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('submission_family_size.csv', index=False)

print("Score 0.78229 達成用の提出ファイルを保存しました。")
</pre>
<h3 style="color: blue;">3. 実験結果：0.77990 &rarr; 0.78229 へ上昇！</h3>
<p>家族サイズを導入した結果、ついに停滞していたスコアが大きく動きました。</p>
<ul>
<li><b>前回（Age補完のみ）：</b> Score 0.77990</li>
<li><b>今回（FamilySize追加）：</b> <b style="color: #d73a49;">Score 0.78229</b></li>
</ul>
<p><b>エンジニア的な考察：</b><br />
ついに 0.78 の大台に乗りました。単なる数値だった「SibSp」と「Parch」を合計して『家族というひとつの単位』として捉え直したことで、モデルは「独身男性（死亡率高）」や「小家族（生存率高）」という構造を、より正確に切り分けられるようになったと言えます。アルゴリズムをいじるのではなく、データの「見方」を変えることが勝利の鍵であることを証明しました。</p>
<h3 style="color: blue;">4. 次なる一手：名前の「敬称」から社会的地位を暴く</h3>
<p>0.78229 というスコアは一つの通過点に過ぎません。まだ伸び代は十分にあります。次は、これまで手をつけていなかった巨大な情報源 <b>Name（名前）</b> の解析に挑みます。ここから「Mr.」「Miss.」「Master.」といった敬称を抜き出せば、年齢だけでは判別できない「既婚・未婚」や「家柄（社会的地位）」という決定的なヒントが手に入るはずです。</p>
<hr />
<p>「質の高い燃料（特徴量）」を投入することで、ランダムフォレストは見違えるような精度を見せ始めました。この勢いのまま、次はテキストデータの解析に踏み込み、さらなる高みを目指します。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/49/</link>
    <pubDate>Sat, 04 Apr 2026 13:31:56 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/49</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #10：モデルの検証。自作フラグは「ノイズ」だったのか？</title>
    <description>
    <![CDATA[<p>前回（攻略 #9）では、生存予測の精度を上げるため、以下のデータ加工とモデル構築を行いました。</p>
<h3 style="color: blue;">1. 前回の復習：投入データの構成と加工</h3>
<ul>
<li><b>Age（年齢）の精密補完：</b> 単純な平均値ではなく、<code>Pclass</code>（客室階級）と <code>Sex</code>（性別）を掛け合わせたグループごとの中央値で欠損値を補完。</li>
<li><b>IsChild_Final（自作フラグ）：</b> 補完した「Age（年齢）が12歳以下」という条件に、さらに「Name（名前）に Master を含む」という確実性の高い敬称データを組み合わせて作成。</li>
<li><b>投入した特徴量：</b> <code>Pclass</code>, <code>Sex</code>, <code>Age</code>, <code>IsChild_Final</code>, <code>SibSp</code>（兄弟・配偶者数）, <code>Parch</code>（親子数）, <code>Fare</code>（運賃）。</li>
<li><b>モデル：</b> ランダムフォレスト（<code>n_estimators=500</code>）。</li>
</ul>
<p>しかし、結果は <b>0.77751 &rarr; 0.77511</b> へと下落。「子供と女性は優先される」という強力なドメイン知識を反映したはずが、なぜ逆効果になるのか。学習済みモデルの内部数値を直接取り出してデバッグします。</p>
<h3 style="color: blue;">2. 思考のステップ：なぜ「子供フラグ」は失敗したのか</h3>
<ol>
<li><b>「Age」と「Name」から導いた子供フラグはダメだった。</b> <br />
実際に精度が下がった以上、このフラグの設定には致命的な「何か」が足りない。</li>
<li><b>「子供と女性は優先されていた」というドメイン知識は揺るがない。</b> <br />
歴史的事実として、避難優先順位の筆頭は「Women and children」である。</li>
<li><b>モデルには「子供フラグ」と「Sex（女性）」という2つの軸を与えてある。</b> <br />
理論上、これで優先グループを網羅できているはずだ。</li>
<li><b>【核心】ならば、モデル内部で、この2つの軸が「生存を切り分けるための重要度」としてどう扱われているかを確認すべきではないか？</b></li>
</ol>
<h3 style="color: blue;">3. 検証：ランダムフォレストが算出する「重要度」の仕組み</h3>
<p>今回使用しているランダムフォレストは、学習（fit）のプロセスで500本の独立した決定木を作成します。その際、各項目の「重要度（Feature Importance）」は以下のステップで計算されています。</p>
<ul>
<li><b>不純度の減少量を累積：</b> 各決定木がデータを分割する際、「性別」や「子供フラグ」などの軸を使います。その軸で分けた結果、グループ内の「生存・死亡」がきれいに分かれるほど（＝不純度が下がるほど）、その軸に高いスコアが与えられ、500本分累積されます。</li>
<li><b>比率の算出：</b> 全項目が稼いだ累積スコアの総和を <b>1.0 (100%)</b> としたとき、各項目が占める割合を算出します。</li>
</ul>
<h3 style="color: blue;">4. 【実装】モデルが各項目をどれだけ「信頼」したかを確認する</h3>
<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
from sklearn.ensemble import RandomForestClassifier

# 1. 前回のデータ準備（攻略 #9の状態を再現）
train_data = pd.read_csv('train.csv')
group_cols = ['Pclass', 'Sex']

# Ageの補完：PclassとSexごとの中央値
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))

# Age(年齢)とName(敬称Master)から導いた子供フラグ
train_data['IsChild_Final'] = ((train_data['Age'] &lt;= 12) | (train_data['Name'].str.contains('Master'))).astype(int)

# 学習に使用する特徴量の定義
features = ["Pclass", "Sex", "Age", "IsChild_Final", "SibSp", "Parch", "Fare"]
X = pd.get_dummies(train_data[features])
y = train_data["Survived"]

# 2. モデルの学習（500本の決定木を生成し、それぞれの分割性能を記録）
model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)
model.fit(X, y)

# 3. 各項目の重要度（Feature Importance）を抽出
importances = pd.Series(model.feature_importances_, index=X.columns).sort_values(ascending=False)

print("--- [Feature Importance: 500本の木による信頼度の集計結果] ---")
print(importances)

# 4. 補足検証：子供フラグ（IsChild_Final）の実際の生存率
print("\n--- [Actual Survival Rate: 子供フラグ別の生存率（学習データ）] ---")
print(train_data.groupby('IsChild_Final')['Survived'].mean())
</pre>
<h3 style="color: blue;">5. 実行結果：残酷な現実</h3>
<p>検証コードを走らせた結果、以下の数値が返ってきました。</p>
<p><b>■ 500本の木による信頼度の集計結果（Feature Importance）</b></p>
<pre style="background-color: #333; color: #fff; padding: 10px;">Sex_female       0.273813  (27.4%)
Sex_male         0.251328  (25.1%)
Fare             0.146034  (14.6%)
Pclass           0.125932  (12.6%)
Age              0.090933  (9.1%)
SibSp            0.053964  (5.4%)
IsChild_Final    0.029075  (2.9%)  &larr; ★ここ
Parch            0.028921  (2.9%)
</pre>
<p><b>■ 子供フラグ別の実際の生存率（学習データ）</b></p>
<pre style="background-color: #333; color: #fff; padding: 10px;">IsChild_Final
0 (大人など)  : 0.366 (36.6%)
1 (子供)      : 0.575 (57.5%)
</pre>
<h3 style="color: blue;">6. 考察：数字が示す「子供フラグ」の敗北原因</h3>
<ul>
<li><b>【データ：累積貢献度 2.9%】子供フラグは「無視」された：</b><br />
500本の決定木が生存予測の軸として信頼した割合（Feature Importance）は、わずか <b>0.029 (2.9%)</b> でした。これは、運賃（14.6%）や客室階級（12.6%）、さらには生の年齢（9.1%）よりも遥かに低く、モデルが「このフラグは生存を占う上で、ほとんど信用に値しない」と公式に判定したことを示しています。</li>
<li><b>【データ：生存率 57.5%】「6割・4割」では使えない：</b><br />
モデルがこのフラグを信頼しなかった直接の根拠は、実行結果の <code>IsChild_Final = 1</code>（子供グループ）の生存率が <b>57.5%</b> に留まったことです。これは「約6割が生き、<b>42.5%（4割以上）が死亡している</b>」という極めて不純な状態です。モデルが求めているのは生存か死亡かを明確に切り分けられる軸ですが、このフラグで分けても4割以上も死亡者が混ざってしまうため、生存予測の条件（if文）としては不適格と見なされました。</li>
<li><b>【結論】不純な境界線がスコアを落とした：</b><br />
Age（年齢）とName（敬称Master）から導き出した「12歳以下」という人為的な境界線では、モデルが生存を確信できるほどの「純度」を生み出せませんでした。この<b>「6割生存・4割死亡」という分離性能の低さ</b>こそが、累積貢献度を押し下げ、結果として全体の予測精度（スコア）を下落させた正体です。</li>
</ul>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/48/</link>
    <pubDate>Sat, 04 Apr 2026 05:54:52 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/48</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #9：名前（Name）による救出作戦と、裏目に出た結果 </title>
    <description>
    <![CDATA[<p>前回（攻略 #8）では、「12歳以下の子供フラグ（IsChild）」を導入した結果、スコアが <b>0.77990 &rarr; 0.77751</b> へと下落しました。この原因を「中央値補完によって大人扱いされた子供がノイズになった」と仮説を立て、今回は名前（Name）に含まれる確定情報を用いてその矛盾の解消を試みました。</p>
<h3 style="color: blue;">1. 今回のロジック：名前と年齢のハイブリッド判定</h3>
<p>Ageが欠損していた乗客に対し、一律の中央値で補完したことで生じた「誤判定」を上書きするのが今回の狙いです。以下の条件のいずれかを満たす場合に「真の子供（IsChild_Final）」と定義しました。</p>
<ul>
<li><b>条件A：</b> 年齢（Age）が12歳以下である。</li>
<li><b>条件B：</b> 名前（Name）の中に、男の子を示す敬称 <b>"Master."</b> が含まれている。</li>
</ul>
<p>名前に "Master" とあれば、たとえAgeが空欄で中央値（例：25歳）が割り当てられていても、確実に子供として救出できる計算です。論理的には、前回よりも情報の精度は高まっているはずでした。</p>
<h3 style="color: blue;">2. 【実装】コード全文</h3>
<p>前回（#8）からの変更点（OR条件によるフラグ作成）を反映した全文です。</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
from sklearn.ensemble import RandomForestClassifier

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

# 2. Age の中央値補完（攻略 #7 継承）
group_cols = ['Pclass', 'Sex']
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))
test_data['Age'] = test_data['Age'].fillna(test_data.groupby(group_cols)['Age'].transform('median'))
test_data['Fare'] = test_data['Fare'].fillna(test_data['Fare'].median())

# 3. 【攻略 #9 での変更点】真の子供フラグ（IsChild_Final）の作成
# ---------------------------------------------------------
# 年齢(Age)が12歳以下、または名前(Name)に "Master" を含む場合にフラグを立てる
# ---------------------------------------------------------
<b style="color: #d73a49;">train_data['IsChild_Final'] = ((train_data['Age'] &lt;= 12) | (train_data['Name'].str.contains('Master'))).astype(int)</b>
<b style="color: #d73a49;">test_data['IsChild_Final'] = ((test_data['Age'] &lt;= 12) | (test_data['Name'].str.contains('Master'))).astype(int)</b>

# 4. 特徴量の選択
features = ["Pclass", "Sex", "Age", <b style="color: #d73a49;">"IsChild_Final"</b>, "SibSp", "Parch", "Fare"]

X = pd.get_dummies(train_data[features])
y = train_data["Survived"]
X_test = pd.get_dummies(test_data[features])

# 5. モデルの学習（500本維持）
model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)
model.fit(X, y)

predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('submission_master_rescue.csv', index=False)
</pre>
<h3 style="color: blue;">3. 実験結果：さらなるスコア下落（0.77511）</h3>
<p>期待に反し、スコアは前回の 0.77751 からさらに下がり、<b>0.77511</b> となりました。精度を高めるための「Master救出作戦」でしたが、結果としては裏目に出た形です。</p>
<h3 style="color: blue;">4. 考察：なぜ「正しいはずの情報」でスコアが落ちるのか</h3>
<p>論理的に正しいはずのフラグを追加してスコアが落ちる場合、以下の可能性が考えられます。</p>
<ul>
<li><b>過学習（Overfitting）：</b> 「Master ＝ 生存」という強いルールを学習しすぎた結果、テストデータに含まれる「不幸にも助からなかった Master」を正しく予測できなくなった。</li>
<li><b>情報の競合：</b> すでに Age や Parch（親子数）から「子供」であることをモデルが把握していた場合、新しいフラグの追加が判断のノイズになり、木構造が不安定になった。</li>
</ul>
<p>「フラグを立てれば立てるほど良くなる」というわけではないのが、機械学習の難しさです。これまでは「子供」という一点にのみ執着してきましたが、その偏った視点自体が現在の停滞を招いているのかもしれません。</p>
<hr />
<p>次は、子供（Master）だけでなく、未婚女性（Miss）や既婚女性（Mrs）、成人男性（Mr）といった<b>「すべての敬称」を網羅的に数値化</b>し、よりフラットな視点で特徴量エンジニアリングを進めていきます。特定の属性に固執せず、全体像を捉え直すことが 0.78 突破への道かもしれません。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/47/</link>
    <pubDate>Sat, 04 Apr 2026 05:23:03 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/47</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #8：フラグ追加の試みと、見えてきた「欠損値補完」の罠 </title>
    <description>
    <![CDATA[<p>前回（攻略 #7）では、性別と客室クラスを掛け合わせた精緻な Age（年齢）補完を行い、スコアは <b>0.77511 &rarr; 0.77990</b> と微増しました。今回は、さらに「子供」という属性を強調し、0.78 の大台を突破するための特徴量エンジニアリングに挑戦しました。</p>
<h3 style="color: blue;">1. これまでの振り返りと今回の仮説</h3>
<p>現在の私たちの戦績と構成は以下の通りです。</p>
<ul>
<li><b>攻略 #6：</b> パラメータ調整（木の数）ではスコアに<b>変化なし</b>。</li>
<li><b>攻略 #7：</b> Age（年齢）を補完して投入。スコアが <b>0.00479 上昇</b>。</li>
</ul>
<p>現在、Age は連続値としてモデルに渡っています。しかし、生存の鍵は「子供か大人か」という二値的な境界線にあるはず。そこで、<b>「12歳以下（Child）」か「それ以外（Adult）」か</b>というフラグ（IsChild）を明示的に作ることで、モデルの判断を助けるという仮説を立てました。</p>
<h3 style="color: blue;">2. 【実装】子供フラグ（IsChild）の導入とコード全文</h3>
<p>Age が 12 以下の場合は 1、それ以外を 0 とする新しいカラム <code>IsChild</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
from sklearn.ensemble import RandomForestClassifier

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

# 2. 【攻略 #7からの継承】Age の欠損値を「性別&times;客室クラス」ごとの中央値で補完
# ※ここでの中央値補完が、後のフラグ判定に影響を与えた可能性あり
group_cols = ['Pclass', 'Sex']
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))
test_data['Age'] = test_data['Age'].fillna(test_data.groupby(group_cols)['Age'].transform('median'))
test_data['Fare'] = test_data['Fare'].fillna(test_data['Fare'].median())

# 3. 【攻略 #8での追加】子供フラグ（IsChild）の作成
# ---------------------------------------------------------
# 12歳以下を子供(1)、それ以外を大人(0)として新規カラム作成
# ---------------------------------------------------------
<b style="color: #d73a49;">train_data['IsChild'] = (train_data['Age'] &lt;= 12).astype(int)</b>
<b style="color: #d73a49;">test_data['IsChild'] = (test_data['Age'] &lt;= 12).astype(int)</b>

# 4. 【攻略 #8での変更】特徴量の選択
# ---------------------------------------------------------
# 新たに作成した "IsChild" をリストに追加
# ---------------------------------------------------------
features = ["Pclass", "Sex", "Age", <b style="color: #d73a49;">"IsChild"</b>, "SibSp", "Parch", "Fare"]

X = pd.get_dummies(train_data[features])
y = train_data["Survived"]
X_test = pd.get_dummies(test_data[features])

# 5. モデルの構築（攻略 #6 で決めた 500本 を維持）
model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)
model.fit(X, y)

# 6. 予測の実行
predictions = model.predict(X_test)

# 7. 提出用ファイルの作成
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('submission_ischild_added.csv', index=False)
</pre>
<h3 style="color: blue;">3. 実験結果：無情にもスコアは 0.77511 へ下落</h3>
<p>期待に反し、スコアは前回の Age 投入前と同じ <b>0.77511</b> まで落ち込んでしまいました。良かれと思って追加した「子供フラグ」が、なぜ足を引っ張ったのでしょうか。</p>
<h3 style="color: blue;">4. 考察：欠損値補完が「真の子供」を消した可能性</h3>
<p>ここで非常に重要な仮説が浮かび上がりました。<b>「Ageが空欄で、適当な中央値で埋められた人たち」の中に、実は助かったはずの子供（Master）が混ざっていたのではないか？</b> という点です。</p>
<p>攻略 #7 で行った「クラス別の中央値補完」では、たとえば3等客のAge欠損値に対し、一律で「20代半ば」といった大人の数値を割り当ててしまいました。その結果、本来は子供であったはずの乗客が、この <code>IsChild</code> フラグによって<b>「確定的な大人（0）」</b>としてモデルに誤学習されてしまった恐れがあります。</p>
<p>つまり、現在の「Ageベースのフラグ」は、補完データの不正確さを増幅させるノイズになってしまったと言えます。</p>
<hr />
<p>次の一手は、この矛盾を解消するために「名前（Name）」に含まれる情報を使います。年齢が不明でも、名前に <b>"Master."</b> とあればその乗客は確実に男の子です。次回、<b>「名前 ＋ 年齢」による真の子供特定</b>に挑み、0.78 の壁を叩き割ります。<br />
<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/46/</link>
    <pubDate>Sat, 04 Apr 2026 04:53:16 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/46</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #7：データクレンジングの深化（Age の欠損値補完）</title>
    <description>
    <![CDATA[<p>前回（攻略 #6）の実験では、アルゴリズムのパラメータ（木の数）を増やすという「計算側の工夫」を行いましたが、結果は無情にもスコアに変化なし。エンジニアとして、現在の材料（特徴量）だけでは限界に達したことを確認しました。</p>
<h3 style="color: blue;">1. これまでの振り返り</h3>
<p>現在の私たちの立ち位置を整理します。これまでは、極めてシンプルなデータ処理に留まっていました。</p>
<ul>
<li><b>利用した特徴量：</b> Pclass, Sex, SibSp, Parch, Fare（計5項目）</li>
<li><b>利用したアルゴリズム：</b> ランダムフォレスト（Random Forest）</li>
<li><b>前回の実験：</b> 木の数を 100 &rarr; 500 へ増強したが、<b>Score 0.77511（変化なし）</b></li>
</ul>
<p>この結果から導き出されるロジカルな結論は、<b>「計算式をいじくり回すよりも、モデルに与える『新しいヒント（特徴量）』を増やすべきだ」</b>ということです。</p>
<h3 style="color: blue;">2. 今回のターゲット：Age（年齢）の救出</h3>
<p>生存率に大きく関与しているはずなのに、これまで無視してきたデータがあります。それが <b>Age（年齢）</b> です。無視していた理由は、データの約20%が空欄（欠損値）であり、そのままでは機械学習にかけられないからです。</p>
<p>今回は、この欠損値を「単なる全体平均」で埋めるのではなく、データの背景を洞察した<b>「属性別の層別補完」</b>という手法で救い出します。</p>
<h3 style="color: blue;">3. 【戦略】性別 &times; 客室クラス別の中央値で補完</h3>
<p>「1等客の男性」と「3等客の女性」では、明らかに年齢層が異なります。そこで、Pclass（客室クラス）と Sex（性別）を掛け合わせたグループごとに中央値を算出し、より実態に近い値を穴埋めします。</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;"># 【実装】性別&times;客室クラスごとの中央値で Age の欠損値を埋める<br />
group_cols = ['Pclass', 'Sex']<br />
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))<br />
test_data['Age'] = test_data['Age'].fillna(test_data.groupby(group_cols)['Age'].transform('median'))
</pre>
<h3 style="color: blue;">4. 実験結果：0.77511 &rarr; 0.77990 へ上昇！</h3>
<p>Ageを特徴量に加えて再学習させた結果、ついにスコアが動きました。</p>
<ul>
<li><b>前回（Ageなし）：</b> Score 0.77511</li>
<li><b>今回（Ageあり）：</b> <b style="color: #d73a49;">Score 0.77990</b></li>
</ul>
<p><b>エンジニア的な考察：</b><br />
「少ししか上がらないな」というのが正直な感想ですが、前回のパラメータ調整ではピクリとも動かなかったスコアが、データのクレンジングによって確実に前進しました。これは、モデルが「Women and Children First（婦女子優先）」という歴史的背景を、より正しく理解し始めた証拠と言えます。</p>
<hr />
<p>「質の高いヒント」を投入することで、停滞していた壁をわずかながら突破しました。しかし、まだ 0.78 の大台には届いていません。次はさらに踏み込み、名前（Name）に含まれる敬称から「社会的地位」や「未婚・既婚」を抽出する、より高度な特徴量エンジニアリングが必要かもしれません。<br />
<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/45/</link>
    <pubDate>Sat, 04 Apr 2026 04:36:37 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/45</guid>
  </item>
    <item>
    <title>【DS検定対策】統計学の王道！どんな分布も正規分布に導く「中心極限定理」</title>
    <description>
    <![CDATA[<p>統計学の世界で、データの分析を支える最も強力な法則の一つが「中心極限定理」です。なぜ多くのデータ分析で「正規分布」が前提とされるのか、その理由がここにあります。</p>
<h3 style="color: blue;">1. 【 問題 】</h3>
<p>母集団の分布がどのような形であっても、そこから抽出するサンプルサイズ（n）を大きくするにつれて、標本平均の分布はどのような分布に近づくでしょうか？</p>
<p>① ポアソン分布<br />
② 指数分布<br />
③ 正規分布<br />
④ カイ二乗分布</p>
<hr />
<h3 style="color: #d32f2f;">2. 【 解答 】</h3>
<div style="background-color: #eeeeee; border: 2px solid #333; padding: 15px; font-size: 1.2em; font-weight: bold; text-align: center;">正解： ③ 正規分布</div>
<hr />
<h3 style="color: blue;">3. 整理：「平均」を繰り返すと整う世界</h3>
<p>元のデータがバラバラ（一様分布や偏った分布）でも、何度も「平均」をとって集めると、不思議ときれいな山の形（正規分布）になります。</p>
<p>【 中心極限定理のプロセス 】</p>
<div style="font-family: monospace; border: 1px solid #ccc; padding: 10px; line-height: 1.6;">[ 1. 母集団 ]<br />
サイコロの目（1〜6が均等に出る分布）など、形は自由。<br />
<br />
[ 2. 標本抽出（サンプリング） ]<br />
100個のサイコロを振って、その「平均値」を出す。<br />
<br />
[ 3. 試行を繰り返す ]<br />
<b>★ ここが中心極限定理！</b><br />
その「平均値」を何セットも記録してグラフにすると&hellip;&hellip;<br />
<br />
[ 4. 収束 ]<br />
サンプルサイズ（n）が大きいほど、見事な<b>「正規分布（ベルカーブ）」</b>になる。<br />
<br />
--------------------------<br />
<br />
◎ <b>重要： 元の分布が正規分布でなくても、標本平均は正規分布に従うようになります。</b></div>
<h3 style="color: blue;">4. なぜこれが重要なのか？</h3>
<p>1. <b>推測統計の根拠</b>: 母集団の正確な形がわからなくても、正規分布の性質を使って「母平均」を推定できるようになります。<br />
2. <b>検定の基礎</b>: t検定などの統計的検定が成り立つのは、この定理のおかげです。<br />
3. <b>実務での安心感</b>: サンプルサイズが十分に大きければ（一般にn=30以上など）、正規分布を前提とした分析手法が使いやすくなります。</p>
<hr />
<h3 style="color: orange;">5. DS検定形式：実戦4択クイズ</h3>
<p><b>問：中心極限定理の説明として、不適切なものはどれか。</b></p>
<p>① 元の母集団がどのような分布であっても成り立つ。<br />
② サンプルサイズが大きくなるほど、平均の分布は尖った形になる。<br />
③ 標本平均の期待値は、母平均に等しい。<br />
④ 母集団が正規分布でないと、標本平均は決して正規分布にならない。</p>
<p><b>【 正解： ④ 】</b></p>
<p><b>解説：</b> 「母集団が正規分布でなくても、平均の分布は正規分布に近づく」のが中心極限定理の最大のポイントです。したがって④は誤りです。サンプルサイズが大きくなれば、どんな歪んだ分布から取った平均でも正規分布に収束します。</p>
<hr />
<h3 style="color: blue;">6. まとめ</h3>
<p>DS検定において「サンプルが大きくなる」「標本平均の分布」「正規分布に近づく」というキーワードがセットで出たら、それは「中心極限定理」を指しています。統計分析の「免罪符」とも呼ばれるこの定理を、しっかり味方につけましょう！</p>
<br />
z]]>
    </description>
    <category>DS検定＞1. データサイエンス ＞1-1. 数理基礎・統計学 ＞1-1-2. 統計数理</category>
    <link>https://learnms.blog.shinobi.jp/Entry/44/</link>
    <pubDate>Fri, 03 Apr 2026 21:45:22 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/44</guid>
  </item>
    <item>
    <title>【DS検定対策】統計の落とし穴を攻略！極端な値が落ち着く「平均への回帰」</title>
    <description>
    <![CDATA[<p>「前回のテストが満点だったのに、次は下がってしまった」「大活躍した新人が、2年目に成績を落とした」。これらは偶然ではなく、統計的な「平均への回帰」という現象かもしれません。</p>
<h3 style="color: blue;">1. 【 問題 】</h3>
<p>ある変数の測定を繰り返した際、1回目に非常に高い（または低い）といった極端な観測値が出たとしても、2回目以降の測定では、より中心（平均）に近い値が観測されやすくなる現象を何と呼ぶでしょうか？</p>
<p>① 平均への回帰<br />
② 大数の法則<br />
③ 中心極限定理<br />
④ 標本誤差</p>
<hr />
<h3 style="color: #d32f2f;">2. 【 解答 】</h3>
<div style="background-color: #eeeeee; border: 2px solid #333; padding: 15px; font-size: 1.2em; font-weight: bold; text-align: center;">正解： ① 平均への回帰</div>
<hr />
<h3 style="color: blue;">3. 整理：極端な値は「長続きしない」世界</h3>
<p>観測値には「実力」だけでなく「運（偶然の誤差）」が含まれます。極端な値が出たときは、その「運」が最大に振れていた可能性が高いのです。</p>
<p>【 平均への回帰のイメージ 】</p>
<div style="font-family: monospace; border: 1px solid #ccc; padding: 10px; line-height: 1.6;">[ 1回目の測定 ]<br />
実力 ＋ <b>「ものすごい幸運」</b> ＝ 100点（極端な値）<br />
<br />
[ 2回目の測定 ]<br />
実力 ＋ <b>「普通の運」</b> ＝ 75点（平均に近い値）<br />
<br />
[ 3回目の測定 ]<br />
実力 ＋ <b>「少しの不運」</b> ＝ 65点<br />
<br />
--------------------------<br />
<br />
★ <b>「運」は毎回ランダムなので、繰り返すと結局「平均」の方へ引き戻されます。</b></div>
<h3 style="color: blue;">4. 間違いやすいポイント</h3>
<p>1. <b>「実力が落ちた」と誤解する</b>: 2回目の成績が下がったのは、実力が落ちたのではなく、単に1回目の運が良すぎただけかもしれません。<br />
2. <b>因果関係の取り違え</b>: 「叱ったから成績が戻った（平均へ回帰した）」のか、「叱らなくても勝手に平均へ戻った」のかを区別する必要があります。<br />
3. <b>ビジネスでの活用</b>: キャンペーン初日の異常な売上増が、2日目以降に落ち着くのもこの現象の一種です。</p>
<hr />
<h3 style="color: orange;">5. DS検定形式：実戦4択クイズ</h3>
<p><b>問：高い相関がある2つの変数（親の身長と子の身長など）において、親が極端に高身長であっても、子の身長は親ほど極端ではなく、より全体の平均に近い値をとる傾向を指摘した統計学者は誰か。</b></p>
<p>① フィッシャー &nbsp; ② ゴルトン &nbsp; ③ ピアソン &nbsp; ④ ベイズ</p>
<p><b>【 正解： ② 】</b></p>
<p><b>解説：</b> フランシス・ゴルトンは、親子の身長の研究を通じて「平均への回帰」という概念を見出しました。これがのちに「回帰分析」という手法の語源となりました。</p>
<hr />
<h3 style="color: blue;">6. まとめ</h3>
<p>DS検定において「極端な値が中心に近づく」「繰り返すと平均的になる」というキーワードが出たら「平均への回帰」が正解です。データを見る際に、それが「真の変化」なのか「統計的な揺り戻し」なのかを見極める視点を持ちましょう！</p>]]>
    </description>
    <category>DS検定＞1. データサイエンス ＞1-1. 数理基礎・統計学 ＞1-1-2. 統計数理</category>
    <link>https://learnms.blog.shinobi.jp/Entry/43/</link>
    <pubDate>Thu, 02 Apr 2026 21:38:43 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/43</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #6：モデルの「合議制」を強化し、精度向上の実験へ </title>
    <description>
    <![CDATA[<p>前回（攻略 #5）では、生存率と相関の強かった「Fare（運賃）」を特徴量に加え、スコアを <b>0.76749 &rarr; 0.77511</b> へと上昇させることに成功しました。今回は、さらに精度を上げるための「次の一手」を、エンジニアらしく最小の工数で検証します。</p>
<h3 style="color: blue;">1. これまでの復習</h3>
<p>まずは、現在の私たちの武器（モデル構成）を整理しておきます。</p>
<ul>
<li><b>利用した特徴量（5項目）：</b> Pclass, Sex, SibSp, Parch, Fare<br />
（生存に直結する納得感のあるヒントを投入済みです）</li>
<li><b>利用したアルゴリズム：</b> ランダムフォレスト（Random Forest）<br />
（攻略 #4 で中身を覗いた、100本の決定木による「合議制」モデルです）</li>
</ul>
<h3 style="color: blue;">2. 今回の戦略：精度向上の実験</h3>
<p>さらなる精度向上を狙うにあたり、今回は<b>「木の数（n_estimators）」</b>を変更する実験を行います。検討の理由は以下の通りです。</p>
<ol>
<li><b>木の深さ（max_depth）の限界：</b><br />
現在は特徴量が5項目と少なく、これ以上深く掘り下げても学習データへの過剰適合（過学習）を招くリスクが高いと判断しました。</li>
<li><b>多数決（合議制）の強化：</b><br />
判断材料が限られている現状では、個々の木の判断をより多くの「仲間」で補完し、予測のブレを最小限に抑える（多数決の精度を上げる）ほうが、スコア向上への確実な一手になると仮説を立てました。</li>
</ol>
<h3 style="color: blue;">3. 【実験】木の数を 100 &rarr; 500 へ増強</h3>
<p>具体的には、`RandomForestClassifier` を定義している一行にある <b>n_estimators</b> という引数を書き換えます。これは「アンサンブル（合議制）に参加させる木の数」を指定するパラメータです。</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<br />
from sklearn.ensemble import RandomForestClassifier<br />
<br />
# 1. データの読み込み<br />
train_data = pd.read_csv('train.csv')<br />
test_data = pd.read_csv('test.csv')<br />
<br />
# 2. 特徴量の選択（前回と同じ5項目）<br />
features = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]<br />
X = pd.get_dummies(train_data[features])<br />
y = train_data["Survived"]<br />
<br />
X_test = pd.get_dummies(test_data[features])<br />
X_test['Fare'] = X_test['Fare'].fillna(X_test['Fare'].median())<br />
<br />
# 3. モデルの構築（★ここを修正！）<br />
# 【変更前】 model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=1)<br />
<b style="color: #d73a49; font-size: 1.1em;">model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)</b><br />
<br />
# 4. モデルの学習（書き換えた設定で再計算）<br />
model.fit(X, y)<br />
<br />
# 5. 予測の実行<br />
predictions = model.predict(X_test)<br />
<br />
# 6. 提出用ファイルの作成<br />
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})<br />
output.to_csv('submission_n500.csv', index=False)<br />
print("Submission with 500 trees saved!")
</pre>
<p><b>修正のポイント：</b><br />
`n_estimators=100` を <b>`n_estimators=500`</b> に変更しました。これにより、100本の多数決から500本の多数決へと「合議制」がパワーアップします。修正はこの1箇所のみ。極めて手間の少ない「次の一手」です。</p>
<h3 style="color: blue;">4. 考察と実験結果</h3>
<p>ここでエンジニアとして一つの疑問が湧きます。<b>「教師データが約800件しかないのに、木の数を500本にするのは多すぎる（リソースの無駄）ではないか？」</b>という点です。</p>
<p>結論から言うと、アンサンブル学習において「合議の数（木の数）」を増やすことは、計算コスト以外のデメリット（精度低下のリスク）はありません。それぞれの木が重複を許して抽出された異なるデータセットを学習するため、数を増やすほど予測は安定する方向に向かいます。</p>
<p>さて、注目の実験結果は以下の通りでした。</p>
<ul>
<li><b>前回（100本）：</b> Score 0.77511</li>
<li><b>今回（500本）：</b> <b style="color: #d73a49;">Score 0.77511（変化なし）</b></li>
</ul>
<p><b>エンジニア的な結論：</b><br />
残念ながら、今回のパラメータ変更だけではスコアはピクリとも動きませんでした。これは、現在の5つの特徴量から引き出せるパターンは、すでに100本の多数決で「出し尽くされている」ということを意味します。計算式をいじっても限界があることが証明されました。</p>
<hr />
<p>仮説と検証の結果、次なる道が明確になりました。これ以上「既存のヒントの計算」を強化しても意味がありません。次は、いよいよ「Age（年齢）」という新しいヒント（特徴量）の投入、そしてそのための「欠損値処理」という、より高度な前処理へと進みます。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/41/</link>
    <pubDate>Sun, 29 Mar 2026 05:38:02 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/41</guid>
  </item>
    <item>
    <title>【Kaggle挑戦記】Titanic 攻略 #5：特徴量への Fare（運賃）追加と精度向上 </title>
    <description>
    <![CDATA[<p>これまでの攻略を経て、私たちは重要な2つの結論を導き出しました。</p>
<ul>
<li><b>#3 の結論（データ分析）：</b> 相関分析の結果、生存率に最も影響を与えるのは「性別（Sex）」だが、それに次いで<b>「運賃（Fare）」</b>も強い相関があることが判明。</li>
<li><b>#4 の結論（モデル理解）：</b> ランダムフォレストの内部を可視化した結果、100本の木による「合議制（多数決）」が論理的に機能していることを確認。</li>
</ul>
<p>今回の戦略は極めてシンプルです。<br />
<b>「信頼できるアルゴリズム（#4）に、より生存率と関連の深いデータ項目（#3）を投入すれば、予測精度は向上するはずだ」</b><br />
という仮説を検証します。</p>
<h3 style="color: blue;">1. 「特徴量（とくちょうりょう）」への納得感</h3>
<p>AIの予測ヒントにするデータ項目を<b>「特徴量」</b>と呼びますが、今回選んだ項目には人間が見ても直感的な納得感があります。</p>
<ul>
<li><b>Pclass（客室クラス）：</b> 1等客なら避難が優先されたのではないか？</li>
<li><b>Sex（性別）：</b> 女性が優先的に救命ボートに乗ったのではないか？</li>
<li><b>Fare（運賃）：</b> 高い運賃を払ったVIP客ほど、手厚いサポートがあったのではないか？</li>
</ul>
<p>このように、背景にあるストーリーとデータが結びつくことで、AIの予測モデルはより説得力のあるものになります。</p>
<h3 style="color: blue;">2. 【実装】特徴量を 5 項目に増強したソースコード</h3>
<p>これまでの 4 項目に、相関係数の高かった <b>"Fare"（運賃）</b> を追加します。テストデータ（test.csv）に1件だけ存在する「欠損値（空欄）」を中央値で埋める対策も1行追加しています。</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<br />
from sklearn.ensemble import RandomForestClassifier<br />
<br />
# 1. データの読み込み<br />
train_data = pd.read_csv('train.csv')<br />
test_data = pd.read_csv('test.csv')<br />
<br />
# 2. 特徴量の選択（Fare を追加して 5 項目に！）<br />
<b style="color: #d73a49;">features = ["Pclass", "Sex", "SibSp", "Parch", "Fare"]</b><br />
<br />
# カテゴリ変数(Sex)を数値に変換<br />
X = pd.get_dummies(train_data[features])<br />
y = train_data["Survived"]<br />
<br />
# 重要：テストデータの Fare に1件だけある欠損値を中央値で補完する<br />
X_test = pd.get_dummies(test_data[features])<br />
<b style="color: #005cc5;">X_test['Fare'] = X_test['Fare'].fillna(X_test['Fare'].median())</b><br />
<br />
# 3. モデルの構築と学習（#4 で信頼性を確認したランダムフォレスト）<br />
model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=1)<br />
model.fit(X, y)<br />
<br />
# 4. 予測の実行<br />
predictions = model.predict(X_test)<br />
<br />
# 5. 提出用ファイルの作成<br />
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})<br />
output.to_csv('submission_fare.csv', index=False)<br />
print("Submission with Fare saved!")
</pre>
<h3 style="color: blue;">3. 結果の考察：データ項目増加の効果</h3>
<p>実際にこのコードで予測を行い Kaggle に提出したところ、スコアに以下の変化が現れました。</p>
<ul>
<li><b>4 項目（前回）：</b> Score 0.76749</li>
<li><b>5 項目（今回）：</b> <b style="color: #d73a49;">Score 0.77511（微増！）</b></li>
</ul>
<p><b>考察：</b><br />
わずかな向上ですが、エンジニアリングにおける重要な原則<b>「良質なデータを入れれば、良質な結果が出る」</b>ことが実証されました。アルゴリズム自体は変えなくても、納得感のある「特徴量」を正しく追加することで、着実に正解率が上がることが確認できました。</p>
<hr />
<p>仮説は正しかったと言えます。しかし、まだ生存率に大きく関わりそうなデータ項目が残っています。それは「年齢（Age）」です。ただし、年齢データには「欠損値」が非常に多いという大きな壁があります。次回、この欠損値処理（インピュテーション）に挑戦します。<br />
<br />
<br />
</p>]]>
    </description>
    <category>【Kaggle挑戦記】</category>
    <link>https://learnms.blog.shinobi.jp/Entry/40/</link>
    <pubDate>Sat, 28 Mar 2026 22:58:40 GMT</pubDate>
    <guid isPermaLink="false">learnms.blog.shinobi.jp://entry/40</guid>
  </item>

    </channel>
</rss>