Python基礎

【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得

機械学習で迷子になる最大の理由は、前処理→学習→評価→改善の順番が曖昧なまま個々のアルゴリズムに飛びつくこと。本記事は、未経験〜初学者が週10時間×2〜3週で到達できるscikit-learnの最短ルートを、実務の型に沿って解説します。
回帰/分類、前処理、パイプライン、交差検証、ハイパラ探索、ベースラインづくりまで、コピペで動くNotebook用コードレビュー観点チェックリスト付きで一気通貫。

この記事で身に付く力

  • 再現性の高いワークフロー(パイプライン+交差検証+ベースライン)
  • 回帰・分類の基本モデル実装力(Ridge/Logistic/RF)
  • 評価設計の勘所(RMSE/AUC、閾値調整、CVの使い分け)
  • 現場ですぐ使える雛形(ディレクトリ構成、保存・再現)

まず“事故の元”を断つ:よくあるつまずき

学習がうまくいかないとき、アルゴリズム選びよりも設計ミスが原因なことがほとんど。ふみとが現場で見てきた“あるある”を、先に潰しておきましょう。

  • データリーク:標準化やエンコードをテストにまで“見せて”しまう。
  • 評価設計の曖昧さ:どの指標で何点を合格とするかが決まっていない。
  • 前処理と学習の分離:Notebook上でバラけて再現できない。
  • ベースライン不在:改善幅の妥当性が判断できない。

解決策は、ベースライン → パイプライン → 交差検証を“標準装備”にすること。これだけで事故らず・盛らず・再現できる状態に近づきます。

10年で残った“現場の型”

筆者(ふみと)は大手企業でデータ/マーケ案件を100件以上担当。評価では1〜2ptの精度差より、再現性・説明可能性・意思決定との接続が重視されました。そこで定着したルーチンが「ベースライン→パイプライン→交差検証→改善」です。以降、そのままポートフォリオに持ち込める手順で解説します。

この記事で使う環境

Python 3.10+ / pandas 2.x / scikit-learn 1.x を想定(pip install scikit-learn 済み)。

  • 回帰サンプル:fetch_california_housing(住宅価格)
  • 分類サンプル:load_breast_cancer(乳がん診断)

Step1:まずは“ベースライン”を作る(回帰/分類)

import numpy as np, pandas as pd
from sklearn.datasets import fetch_california_housing, load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.dummy import DummyRegressor, DummyClassifier
from sklearn.metrics import mean_squared_error, accuracy_score

# 回帰データ

d = fetch\_california\_housing(as\_frame=True)
Xr, yr = d.data, d.target
Xr\_train, Xr\_test, yr\_train, yr\_test = train\_test\_split(Xr, yr, test\_size=0.2, random\_state=42)
base\_r = DummyRegressor(strategy="median").fit(Xr\_train, yr\_train)
rmse\_base = mean\_squared\_error(yr\_test, base\_r.predict(Xr\_test), squared=False)
print(f"回帰ベースライン RMSE={rmse\_base:.3f}")

# 分類データ

d2 = load\_breast\_cancer(as\_frame=True)
Xc, yc = d2.data, d2.target
Xc\_train, Xc\_test, yc\_train, yc\_test = train\_test\_split(Xc, yc, test\_size=0.2, stratify=yc, random\_state=42)
base\_c = DummyClassifier(strategy="most\_frequent").fit(Xc\_train, yc\_train)
acc\_base = accuracy\_score(yc\_test, base\_c.predict(Xc\_test))
print(f"分類ベースライン ACC={acc\_base:.3f}")

判断基準:ベースライン未満のモデルは採用不可。改善幅の妥当性を数値で把握します。

Step2:前処理は必ず“パイプライン”に格納

from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline

num\_cols = Xr.columns  # 例:数値のみ

numeric\_proc = Pipeline(\[
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler())
])

# 例:カテゴリ列がある場合

# cat\_cols = \["gender", "area"]

# categorical\_proc = Pipeline(\[

# ("impute", SimpleImputer(strategy="most\_frequent")),

# ("onehot", OneHotEncoder(handle\_unknown="ignore", sparse\_output=False))

# ])

preprocess = ColumnTransformer(\[
("num", numeric\_proc, num\_cols),
\# ("cat", categorical\_proc, cat\_cols)
], remainder="drop")

判断基準:前処理は必ずPipeline/ColumnTransformerに格納し、学習データのみでfit。

Step3:回帰モデル(Ridge/ランダムフォレスト)

from sklearn.linear_model import Ridge
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_squared_error
from sklearn.pipeline import Pipeline

ridge = Pipeline(\[
("prep", preprocess),
("model", Ridge(alpha=1.0, random\_state=42))
])
rf = Pipeline(\[
("prep", preprocess),
("model", RandomForestRegressor(n\_estimators=300, random\_state=42, n\_jobs=-1))
])

ridge.fit(Xr\_train, yr\_train)
rf.fit(Xr\_train, yr\_train)

for name, mdl in {"Ridge": ridge, "RF": rf}.items():
pred = mdl.predict(Xr\_test)
print(name, "RMSE=", mean\_squared\_error(yr\_test, pred, squared=False), "R2=", r2\_score(yr\_test, pred))

判断基準:単純モデル→非線形モデルの順で比較。過学習はtrain/valの乖離で検知。

Step4:分類モデル(ロジスティック回帰/ランダムフォレスト)

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score, classification_report, accuracy_score

pre\_num\_c = Pipeline(\[("impute", SimpleImputer()), ("scale", StandardScaler())])
prep\_c = ColumnTransformer(\[("num", pre\_num\_c, Xc.columns)])

logit = Pipeline(\[("prep", prep\_c), ("model", LogisticRegression(max\_iter=1000))])
rf\_c = Pipeline(\[("prep", prep\_c), ("model", RandomForestClassifier(n\_estimators=400, random\_state=42, n\_jobs=-1))])

for name, mdl in {"Logit": logit, "RF": rf\_c}.items():
mdl.fit(Xc\_train, yc\_train)
proba = mdl.predict\_proba(Xc\_test)\[:,1]
pred = (proba >= 0.5).astype(int)
print(name, "ACC=", accuracy\_score(yc\_test, pred), "AUC=", roc\_auc\_score(yc\_test, proba))

print(classification\_report(yc\_test, rf\_c.predict(Xc\_test)))

判断基準:クラス不均衡がある場合はAUC/再現率も確認。閾値0.5が最適とは限りません。

Step5:交差検証で“安定度”を測る

from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold

cv\_r = KFold(n\_splits=5, shuffle=True, random\_state=42)
cv\_scores = cross\_val\_score(rf, Xr\_train, yr\_train, scoring="neg\_root\_mean\_squared\_error", cv=cv\_r, n\_jobs=-1)
print("CV RMSE(mean±std)=", -cv\_scores.mean(), "+/-", cv\_scores.std())

cv\_c = StratifiedKFold(n\_splits=5, shuffle=True, random\_state=42)
cv\_auc = cross\_val\_score(rf\_c, Xc\_train, yc\_train, scoring="roc\_auc", cv=cv\_c, n\_jobs=-1)
print("CV AUC(mean±std)=", cv\_auc.mean(), "+/-", cv\_auc.std())

原則:モデル選択はCV平均で決める。テストスコアは最後に一度だけ使う。

Step6:ハイパーパラメータ探索(Grid/Random)

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from scipy.stats import randint

# 例:RF回帰(Grid)

param\_grid = {
"model\_\_n\_estimators": \[200, 400, 800],
"model\_\_max\_depth": \[None, 10, 20],
"model\_\_min\_samples\_split": \[2, 5, 10]
}
rf\_gs = GridSearchCV(rf, param\_grid, scoring="neg\_root\_mean\_squared\_error", cv=3, n\_jobs=-1)
rf\_gs.fit(Xr\_train, yr\_train)
print("best\_params=", rf\_gs.best\_params\_)

# 例:RF分類(Random)

param\_dist = {
"model\_\_n\_estimators": randint(100, 800),
"model\_\_max\_depth": \[None] + list(range(3, 15)),
}
rf\_rs = RandomizedSearchCV(rf\_c, param\_distributions=param\_dist, n\_iter=20, scoring="roc\_auc", cv=3, random\_state=42, n\_jobs=-1)
rf\_rs.fit(Xc\_train, yc\_train)
print("best\_params=", rf\_rs.best\_params\_)

原則:探索はCV内で行い、テストは最後に1回。過適合を防ぐ鉄則です。

Step7:特徴量の重要度(Permutation)

from sklearn.inspection import permutation_importance

rf\_c.fit(Xc\_train, yc\_train)
r = permutation\_importance(rf\_c, Xc\_test, yc\_test, n\_repeats=10, random\_state=42, n\_jobs=-1)
imp = pd.Series(r.importances\_mean, index=Xc.columns).sort\_values(ascending=False)
print(imp.head(10))

重要度は因果ではなく“説明の補助”。リーク検査やモデル妥当性の確認に使いましょう。

Step8:モデルの保存・再現(joblib)

import joblib
from sklearn.metrics import roc_auc_score

joblib.dump(rf\_c, "model\_rf\_class.joblib")
mdl = joblib.load("model\_rf\_class.joblib")
print("loaded AUC:", roc\_auc\_score(yc\_test, mdl.predict\_proba(Xc\_test)\[:,1]))

バージョン固定(sklearn/pandas)はrequirements.txtへ。README再現手順を記載。

Step9:よくある地雷と回避策

地雷 症状 回避策
データリーク CVは高いのに本番で失敗 前処理をPipeline化、fitは学習データのみ
クラス不均衡 高精度でも実務で誤検知 AUC/再現率/適合率を併記、閾値調整/重み付け
評価の誤設計 RMSEとMAEが混在、KPIと非連動 指標を1〜2個に限定しKPIと接続
テスト流出 チューニングにテストを再使用 テストは最後に1回の原則

Step10:読みやすいMLプロジェクトの雛形

project/
  ├─ data/                 # 入出力(追跡対象外も検討)
  ├─ notebooks/            # 実験ノート
  ├─ src/                  # 前処理/学習の関数
  │   ├─ features.py
  │   ├─ models.py
  │   └─ evaluate.py
  ├─ reports/              # 図/スライド
  ├─ requirements.txt
  └─ README.md             # 再現手順

Tips:Notebookはアイデア検証、本流は関数化してsrc/。最小でもデータ検査のテストを書いておくと安全です。

学習の“目的別”おすすめ配分

  • 転職(未経験→DS)パイプライン/交差検証/ベースライン/README厚め。Permutation重要度で妥当性を説明。
  • 副業(納品力)保存・再現手順/Excel出力を重視。運用を意識した閾値調整
  • 在宅(短時間×高頻度)関数化小さい実験の反復RandomizedSearchCVで探索を軽く。

ミニプロジェクト(提出推奨)

課題:「乳がんデータでAUC≥0.98、再現性付きで“説明可能”な分類器を仕上げる」

  • ベースライン(Dummy)→ ロジスティック → ランダムフォレストで比較。
  • パイプライン+StratifiedKFoldでCV計測、AUC平均±stdを報告。
  • RandomizedSearchCVで軽量探索→最終モデルをテスト一度だけ評価。
  • Permutation重要度で主要特徴を確認、示唆を3行で記載。
  • requirements.txtREADME再現手順を明記、joblibでモデル保存。

レビュー観点チェックリスト(コピペ可)

  • [ ] 前処理はPipeline/ColumnTransformerに格納されている
  • [ ] テストは最後に1回しか使っていない
  • [ ] 指標がKPIと連動し、平均±stdで安定性を示している
  • [ ] リークなし(標準化/エンコードは学習データでfit)
  • [ ] README/requirementsで再現できる

付録A:分類の閾値最適化(Youden/Jカットなど)

import numpy as np
from sklearn.metrics import roc_curve

proba = rf\_c.predict\_proba(Xc\_test)\[:,1]
fpr, tpr, thr = roc\_curve(yc\_test, proba)
youden = tpr - fpr
thr\_opt = thr\[np.argmax(youden)]
print("best threshold by Youden:", thr\_opt)

付録B:時系列CV(時間依存データの例)

from sklearn.model_selection import TimeSeriesSplit, cross_val_score

ts = TimeSeriesSplit(n\_splits=5)
scores = cross\_val\_score(ridge, Xr\_train.sort\_index(), yr\_train.sort\_index(), cv=ts,
scoring="neg\_root\_mean\_squared\_error")
print("TimeSeries CV RMSE=", -scores.mean())

次に読むべき記事

モデル評価
【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説

精度が上がらない原因の多くは「評価設計の誤り」にあります。評価とは「何点取れたか」ではなく、意思決定に耐えるかを測る営み。この記事では、回帰/分類/ランキングの指標の選び方、交差検証の正しい使い分け、 ...

ハイパーパラメータ入門
【保存版】ハイパーパラメータ入門:Grid/Random/Optunaの実務チューニング完全ガイド

チューニングのゴールは「スコアの数字遊び」ではありません。意思決定に耐える安定した最適化を短時間で作ること。本記事は未経験〜初学者が週10時間×2週間で、GridSearchCV / Randomiz ...

スキルアップ
【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得

リード(結論)基礎を終えたら次は実務の現場で頻出する処理を“型”で覚える段階です。本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規 ...

可視化
【保存版】可視化入門:Matplotlib/Plotlyの使い分けと“伝わるグラフ設計”10ステップ

結論:可視化は「きれいに描く」ことではなく、意思決定を動かすための設計です。本稿では、未経験〜初学者が 週10時間×1〜2週 で、Matplotlib/Plotlyを軸に “伝わるグラフ”の設計と実装 ...

ポートフォリオ
【保存版】データ職のポートフォリオ完全ガイド|再現性・評価・LTまで

ポートフォリオって「作ったものの置き場」でしょ? いいえ。採用側が見たいのは「意思決定に効いた証拠」と「再現性」です。 本ガイドは、未経験〜初学者が週10時間×4〜6週で、テーマ選定→要件定義→データ ...

FAQ:よくある質問

Q1. どのモデルから始めれば良い?
A. ロジスティック/リッジから。次にツリーモデル(RF/GB)で非線形性を拾う。

Q2. 精度が上がらない
A. まず特徴量とリークを疑う。次に評価設計とデータの質を見直す。 [内部リンク:pandas実践] [内部リンク:モデル評価]

Q3. クラス不均衡がキツい
A. class_weight="balanced"、閾値調整、適切な指標(再現率/PR-AUC)で評価。

Q4. とにかく再現性が欲しい
A. random_state固定・Pipeline・requirements固定・READMEの4点セット。

それでは、また次の記事でお会いしましょう。

最近のコメント

    • この記事を書いた人
    • 最新記事

    ふみと

    このブログでは、データサイエンティストとして市場価値を上げる方法を独自にまとめて発信しています。

    【プロフィール】
    ・大手企業データサイエンティスト/マーケティングサイエンティスト(10年、年収900万円台)/案件100件以上
    ・資格:JDLA E資格(日本ディープラーニング協会主催)/JDLA Community(CDLE会員)/Advanced Marketer/ビジネス統計スペシャリスト/統計検定2級/TOEIC 805
    ・スキル:Python/Tableau/SQL/機械学習/Deep Learning/RPA

    -Python基礎