コンテンツにスキップ

5.1.3 Scikit-learn ハンズオン:fit、transform、Pipeline

Scikit-learn Estimator と Pipeline の図解

Scikit-learn は古典的な機械学習でよく使われる Python ライブラリです。このページは短くします。先に流れを見て、次に完全なスクリプトを動かします。

統一された sklearn fit-predict ワークフロー

sklearn の多くの作業はこのループです。

データ読み込みtrain/test 分割train で fittest で predictscore証拠を保存

まず 4 つの動詞を覚えます。

動詞意味よく使う対象
fit学習データからパラメータを学ぶestimator または transformer
transform学んだ前処理を適用するtransformer
predictラベルや数値を出すestimator
score簡単な指標を返すestimator または pipeline

sklearn Pipeline の部品分解

役割仕事
Estimator学習して予測するLogisticRegressionDecisionTreeClassifier
Transformerデータの形、尺度、表現を変えるStandardScalerOneHotEncoderPCA
Pipeline前処理とモデルを再利用できる流れにするscaler -> classifier

初心者ルール:前処理の fit は学習データだけで行うPipeline はこの順序を守りやすくしてくれます。

Terminal window
python -m pip install --upgrade scikit-learn joblib
python - <<'PY'
import sklearn
print(sklearn.__version__)
PY

期待される出力は、たとえば次のようなバージョン番号です。

Terminal window
1.8.0

scikit-learn はインストール名、sklearn は Python で import する名前です。

ch05_sklearn_workflow.py を作成します。

from pathlib import Path
from joblib import dump, load
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data,
iris.target,
test_size=0.25,
random_state=42,
stratify=iris.target,
)
models = {
"logistic": Pipeline([
("scale", StandardScaler()),
("model", LogisticRegression(max_iter=1000, random_state=42)),
]),
"tree": Pipeline([
("model", DecisionTreeClassifier(max_depth=3, random_state=42)),
]),
"knn": Pipeline([
("scale", StandardScaler()),
("model", KNeighborsClassifier(n_neighbors=5)),
]),
}
scores = {}
for name, pipe in models.items():
pipe.fit(X_train, y_train)
pred = pipe.predict(X_test)
scores[name] = accuracy_score(y_test, pred)
print(f"{name:<8} accuracy={scores[name]:.3f}")
best_name = max(scores, key=scores.get)
best_model = models[best_name]
print(f"best={best_name}")
print("first_prediction=", iris.target_names[best_model.predict(X_test[:1])][0])
print("report_for_best:")
print(classification_report(
y_test,
best_model.predict(X_test),
target_names=iris.target_names,
zero_division=0,
))
output_path = Path("iris_pipeline.joblib")
dump(best_model, output_path)
reloaded = load(output_path)
print("reloaded_prediction=", iris.target_names[reloaded.predict(X_test[:1])][0])

実行します。

Terminal window
python ch05_sklearn_workflow.py

期待される出力:

Terminal window
logistic accuracy=0.921
tree accuracy=0.895
knn accuracy=0.921
best=logistic
first_prediction= setosa
report_for_best:
precision recall f1-score support
setosa 1.00 1.00 1.00 12
versicolor 0.86 0.92 0.89 13
virginica 0.92 0.85 0.88 13
accuracy 0.92 38
macro avg 0.92 0.92 0.92 38
weighted avg 0.92 0.92 0.92 38
reloaded_prediction= setosa

sklearn 実験結果の読み方

sklearn のバージョンによって、同点のときに選ばれる best model が変わることがあります。それでも問題ありません。重要な証拠は、各モデルが fit、predict、score でき、保存した Pipeline が再読み込み後も予測できることです。

Pipeline がよくある失敗を防ぐ理由

Section titled “Pipeline がよくある失敗を防ぐ理由”

StandardScaler の fit と transform の比較漫画

間違った流れ:

全データで scaler を fit分割評価

なぜ間違いか:テストデータが前処理に影響してしまい、スコアが甘くなります。

正しい流れ:

先に分割学習データだけで scaler を fittest を transform評価

Pipeline([("scale", StandardScaler()), ("model", ...)]) を使うと、学習時も予測時も同じ安全な流れになります。

このページを終えたら、この evidence card を残します。

ML 問題
教師あり、教師なし、評価、または特徴量エンジニアリングのタスク
ベースライン
まずは最も簡単な sklearn/モデリングループと固定の train/test 分割
出力
prediction、metric、chart、またはmodel decision note
失敗確認
データリーク、不明確なターゲット、弱いベースライン、または指標不一致
期待される成果
指標と1件の失敗観察を含む最小限のMLループ
症状最初に確認よくある修正
ModuleNotFoundError: sklearn有効な Python 環境python -m pip install scikit-learn で入れる
毎回スコアが変わるrandom_state がない分割と対応モデルに random_state=42 を入れる
テストスコアは良いが実運用で悪いデータリークPipeline を使い、分割してから前処理を fit する
モデルを保存/読込できないjoblib 不足またはパス違いjoblib を入れ、Path.cwd() を表示する
モデル比較が不公平前処理の流れが違う各モデルを比較可能な Pipeline に入れる
  1. test_size0.25 から 0.2 に変えて、スコア差を記録する。
  2. KNeighborsClassifier(n_neighbors=5)n_neighbors=3 に変える。
  3. 同じ Pipeline パターンで SVC などのモデルを一つ追加する。
  4. 端末出力と iris_pipeline.joblib を証拠として保存する。
操作例と確認ポイント
  1. test_size=0.2 にすると学習データは増え、テストデータは減ります。random_state を固定していてもスコアは少し変わりますが、1 回の結果だけで良し悪しを決めないことが大切です。
  2. n_neighbors=3 はより近い近傍に敏感になるため、決定境界が柔軟になります。テストスコアが上がることもありますが、ノイズに弱くなって下がることもあります。
  3. SVC を追加するなら、同じ Pipeline に入れます。たとえば StandardScaler()SVC() を組み合わせ、同じ train/test split で比較すると公平です。
  4. 合格ラインの証拠は、端末のモデルスコア、保存された iris_pipeline.joblib、再読み込み後に predict が動く短い確認です。

次を説明できれば、次のレッスンへ進めます。

  • fittransformpredictscore がそれぞれ何をするか。
  • 前処理が学習データだけから学ぶべき理由。
  • Pipeline が手作業の前処理より安全な理由。
  • 同じ train/test split で二つのモデルを比較する方法。
  • 最終モデルを保存し、再読み込みする方法。