mcpField
B
build-ml-pipeline

build-ml-pipeline

github.com/probabl-aiデータ・データベース144144 回インストール5 日前に更新
リポジトリ

build-ml-pipeline について

build-ml-pipeline は、機械学習パイプラインを skrub DataOps グラフとして宣言するスキルです。分割器や必要なスコアを設定し、未学習のモデルを作成してスモークテストを行います。学習や評価は実行しません。

主な機能

  1. 01skrub.var からデータグラフを構築
  2. 02特徴量と推定器の追加
  3. 03分割器とスコアの設定
  4. 04未学習モデルのスナップショット作成
  5. 05スモークテストの実行

活用シーン

  1. 01承認済み設計に基づくパイプライン宣言
  2. 02後続の評価に向けたモデル準備
  3. 03交差検証またはホールドアウトの設定
  4. 04学習せずにパイプライングラフを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/probabl-ai/skills --skill build-ml-pipeline

インストール後、Claude Code で/build-ml-pipelineを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
common_patterns.md
custom-splitter.md
layer_examples.md
reproducibility_mechanics.md
snapshot.md
source-binding.md

詳細

ML パイプラインを構築する

skrub の DataOps グラフを宣言し、固定された分割器とデフォルト以外のスコアを設定します。ここでの最後の手順はスモークテストです。skore.evaluate のフィッティング、チューニング、永続化、呼び出しは行わないでください。

ユーザー向けの説明文

詳細:setup-workspace references/human_facing_prose.md。 実験用 Markdown、設計ノートの Method テキスト、# コメントで、このパイプラインについて説明します。質問とチェックポイントでは、スキル ID、G-* 名、ラッパー CLI ではなく、同じデータサイエンス用語を使います。`` はサイト上のマーカーです。 作成時のヒントはこのスキル内にとどめます。

X マーカーは .skb.mark_as_X() です。予測グリッドはスコアリングする行です。行をまたぐステップは、ほかの行を参照します(ラグ、ローリング、グループ集約、サイド結合)。レイヤー 1/2/3は、それぞれソース、グリッドとマーカー、マーカーの後の特徴量です。

手順

  1. python -m skore_skills status を実行します。セットアップが保留中の場合は S0 に進みます。次に python -m skore_skills design consent --stem <stem> を実行します。JSON の action が正式な判断です。ask/stop の場合は宣言しません(「構築して」は承認ではありません)。proceed の場合は続行します。次に --revise を付けずに python -m skore_skills frame show を実行します。proceed 以外の場合は frame-ml-problem を読み込んで停止します。translation が null の proceed の場合も停止します。分割器の翻訳がないためです。
  2. 最初の書き込みの前に、1~3 文で説明します。これは、未フィッティングの build_learner、Method セル、パイプラインのスナップショットをローカルで準備し、その後スモークテストを実行するものです。学習や全データセットの評価は行いません。所要時間を作り上げないでください。この説明は一度だけにします。承認待ちの場合はプレビューのみ行います。
  3. 事前確認を提示します。このターンの根拠がある場合に限り、チェックボックスにチェックを入れます。
  4. build_learner を宣言します(ルール 1~3)。まずソース、特徴量、推定器を指定します。その後、.skb.make_learner() より前に、translation の cv とデフォルト以外のスコアを設定します。新しいシンボルごとに python -m skore_skills api get を実行します。編集後は python -m skore_skills style を実行します。プローブは、env verify の composed-dev Python を使って scratch/ に配置します。インラインの python -c は使いません。ユーザーから求められない限り、警告フィルターは使いません。
  5. 未フィッティングのスナップショット:references/snapshot.md。
  6. この stem の experiments/NN_*.py が存在する場合、このスキルがインストール済みのときに限り smoke-test-ml-pipeline を読み込みます。スキルがない場合は、その旨を 1 行で伝えます。pytest ファイルを作り上げないでください。次に python -m skore_skills smoke run --stem <stem> を実行します。JSON が stop/red/smoke_missing の場合は、この場でグラフを修正します。アサーションを緩めないでください。評価はしません。このコマンドを実行せずに、pytest が成功したと主張しないでください。
  7. smoke run が proceed を返したら、次のチェックポイントを表示し、その後 python -m skore_skills evaluate consent --stem <stem> を実行します。
    • ask — JSON の context(question、experiment、smoke、persisted_report)を 2~4 行で引用し、回答によって何が許可されるか、設計上の質問、この stem にはまだ永続化されたレポートがないことを説明します。続いて AskUserQuestion で Evaluate(推奨)/Modify/Stop を提示し、停止します。skore.evaluate は書き込みません。Modify の場合は編集し、再度 smoke run を実行します。Stop の場合は終了します。
    • proceed — レポートはすでに存在します。このスキルがインストール済みなら evaluate-ml-pipeline を読み込むか、このスキルを呼び出したスキルが model-ml-pipeline の場合は、そちらに戻ります。
    • stop — スモークテストファイルがありません。評価はしません。 ユーザーが Evaluate と回答した場合は、インストール済みであれば evaluate-ml-pipeline を読み込みます。smoke run の proceed は、その回答ではありません。
チェックポイント

smoke run が proceed を返した後、Evaluate メニューの前に表示します。2~6 文で、何を宣言したか、スモークテストが成功したこと、学習器について述べます。Method に基づいて記述します。メトリクスを作り上げないでください。この時点ではリンク先を示しません。

続いてリンクを提示します。このターンで site build を実行した場合は、ウェブサイトが更新されたと伝え、ブラウザーで開くための [report.html](<workspace>/report.html) をリンクします。設計ノートの Markdown や html/<stem>.html の名前は挙げないでください。 それ以外の場合は、ウェブサイトが更新されたと主張せず、Markdown の名前も挙げません。その場合も [experiments/<stem>.py](experiments/<stem>.py) はリンクします。

エントリー契約

承認済みの設計を実装してください。黙ってアップグレードしてはいけません。

  • 固定済みベースライン — ジャーナルのベースラインセルにある1つのトークンです。通常の DataOps グラフでは、dummy は DummyClassifier / DummyRegressor です。これはパスが動作することを確認します。logistic、seasonal_naive、group_mean、production は、その1つの比較モデルです。クラスは api get で確認してください。
  • EDA に基づくもの — Method が引用する調査結果のみです。選択肢が欠けている場合は質問してください。時間に関する調査結果は固定済みの cv であり、Method がその手順を指定していない限り、3層、ラグ、AlignXy を追加する許可ではありません。
  • バックログ/議論 — Method が境界です。

特徴量、変換、リークについて質問された場合、research-ml-practice がインストールされていて、その懸念がスクラッチにすでに記載されていなければ、読み込んでください。問題のクラスを抽象化してください。スクラッチに declare または measure の行がすでにある場合は、research を再度読み込まず、パイプラインコードも書かないでください。停止ルールに違反しない declare の行について、allow_multiple を指定して AskUserQuestion を行い、停止してください。質問の最終行は、正確に次のとおりです。Select each one you want. この行の後には何も続けないでください。各 measure の行は、未解決の EDA の質問として示してください。measure は EDA を再検討するものであり、data_analysis.py は編集しません。 スプリッターは引き続き frame show から取得します。 evaluate は evaluate-ml-pipeline を指定します。confirm はユーザーに確認します。スキルが見つからない場合は、1行だけ返します。

ルール 1 — Skrub DataOps をパイプラインのエントリーポイントにする

ルートには、単独の sklearn.Pipeline ではなく skrub.var(...) を使用してください。 skrub.X / skrub.y はルートではありません(S4)。ユーザーが sklearn.Pipeline または build_pipeline() を求めた場合は、内側の推定器として使う場合も含め、Pipeline をインポートしないでください。skrub.var に誘導し、predictions.skb.make_learner() を返す build_learner を使用してください。拒否の例示に Pipeline([...]) コンストラクターを使わないでください。

import skrub
from sklearn.ensemble import HistGradientBoostingRegressor

from <pkg>.data import TARGET_COL, load_raw


def build_learner(data_dir_preview=None):
    """Return the unfit learner (skrub SkrubLearner)."""
    data_dir = (
        skrub.var("data_dir", value=str(data_dir_preview))
        if data_dir_preview is not None
        else skrub.var("data_dir")
    )
    data = data_dir.skb.apply_func(load_raw)
    X = data.drop(columns=[TARGET_COL]).skb.mark_as_X()
    y = data[TARGET_COL].skb.mark_as_y()
    predictions = X.skb.apply(
        HistGradientBoostingRegressor(random_state=0), y=y
    )
    return predictions.skb.make_learner()

translation.task が multioutput-regression の場合、translation.targets のすべての列をまとめて予測します。それらの列をすべて X から除外してください。y は出力ごとに1列の DataFrame のままにします。

TARGET_COLS = ["load", "temp"]
X = data.drop(columns=TARGET_COLS).skb.mark_as_X()
y = data[TARGET_COLS].skb.mark_as_y()
predictions = X.skb.apply(
    HistGradientBoostingRegressor(random_state=0), y=y
)

HistGradientBoostingRegressor、RandomForestRegressor、Ridge など、数値のターゲット行列に適合する推定器を使用してください。選択した推定器が1つの出力にしか適合しない場合は、MultiOutputRegressor でラップしてください。両方のシンボルを api get で確認してください。このタスクでは MultiOutputClassifier を使用せず、ターゲット列を X に残さないでください。列が1つの場合も、上記のとおり TARGET_COL を使用します。 詳細は references/common_patterns.md を参照してください。

手早く従来型のベースラインを作るには、skrub.tabular_pipeline(または TableVectorizer)と、タスクに適した推定器を1つ使用します。両方を api get で確認してください。ここでは列を手動で調整したり、ハイパーパラメーターを探索したりしないでください。その他の形については、references/common_patterns.md を参照してください。

ルール 2 — X を早い段階で指定し、その後に特徴量化する

行ごとの計算と学習時のエンコーダーでは、読み込んだフレームにマーカーを付けます。行をまたぐ処理では、その処理の上流にマーカーを付けます。ローダーに組み込まれたホライズンの拒否を含む3層分のコードは、references/layer_examples.md にあります。Layer 2 を提案する前に、これを読んでください。

value= はプレビュー専用です。build_learner で data_dir_preview=None を公開してください。pipeline.py に相対パスを埋め込まないでください。

グラフの後に行う分割とスコアリング

proceedを返したframe showからtranslationを読み取ります。既存のXマーカーにアタッチし、その後に.skb.make_learner()を呼び出します。skrubでは、split_kwargsを設定する場合、cv=が必要です。整数のcvはスプリッターではありません。Evaluateではsplitter=を省略して、skoreがこのcvを再利用するようにします(evaluate-ml-pipeline/references/metadata-routing.md)。

このcvは、ロックされたデプロイを再現します。スコアリング対象のfitには、デプロイがすでに参照しているはずの行だけが含まれます。以下は一般的な形式です。デプロイの構造が異なる場合は、references/custom-splitter.mdを開き、その設定用のsplitを記述してください。

  • schemeがdate_timeの場合 — references/custom-splitter.mdの時系列のセクションを開きます。cv=には、そのセクションで説明されているプロジェクト固有のクラスを指定します。translation.horizonsの各エントリについて、スプリッターを1つ作成します。それぞれが1つの予測子です。split_kwargsにはタイムスタンプの値を渡します。タイムスタンプ列には、EDAまたはデータに添付された説明で既に指定されている列を使います。それらの情報源に列の指定がない場合に限り、タイムスタンプを格納する列を確認してください。time_roleがcovariateなら、その列は特徴量に残ります。sort_keyなら、その列は特徴量から除外されますが、引き続きsplit_kwargsに渡されます。
  • splitterがGroupKFoldの場合 — cv=GroupKFold(n_splits=<folds>)とし、split_kwargs={"groups": data["<translation.groups>"]}を指定します。
  • splitterがKFoldの場合 — cv=KFold(n_splits=<folds>)とし、split_kwargsは空にします。
  • splitterがprefitの場合 — データには、学習用テーブルとテスト用テーブルがすでにあります。cvは不要です。グラフでは学習用テーブルのみを読み込みます。テスト用テーブルを2つ目のソースとして追加したり、2つのファイルを連結したりしないでください。両方のテーブルは、ターゲットを含め、ローダーが想定するスキーマを共有しています。実験で後からテスト用テーブルを紐付けます。train_test_splitは呼び出さないでください。
  • ホールドアウト(reportがEstimatorReportで、splitterがnull)またはtranslationがnullの場合 — cvは不要です。このホールドアウトは、単一のテーブルから抽出した1つの分割です。提供された学習用/テスト用のペアとは異なります。

スコアリングにはtranslation.metricを使用します。multioutput-regressionの場合、skoreはMSE、RMSE、MAE、R²の各出力をすでに表示します(multioutput="raw_values")。ロックされた比較は引き続き1つの数値なので、その名前に対して明示的な集約を指定し、.skb.with_scoring(...)をアタッチします。ユーザーがvariance_weightedまたは出力ごとの重みを指定していない限り、uniform_averageを使います。この集約値が主要指標です。出力ごとのメトリクスはレポートに残してください。その他のタスクで、名前がskoreの既存レポートに含まれるもの(回帰:MSE、RMSE、MAE、R²、二値分類:accuracy、precision、recall、F1、ROC-AUC、多クラス分類:macroおよびmicroの各バリエーション、マルチラベル分類:ラベルごとの値と平均値)であれば、スコアラーをアタッチしないでください。それ以外の場合は、この同じ後続ステップで.skb.with_scoring(...)を使います。呼び出し可能オブジェクトの形式については、evaluate-ml-pipeline/references/custom-metrics.mdを参照してください。skore.evaluateにscoring=を渡さないでください。

ここではskore.evaluate(...)を記述しないでください。パイプラインコードからtrain_test_splitを呼び出さないでください。

ルール 3 — アタッチ:ステートレスな関数、ステートフルな推定器

  • .skb.apply_func(fn) — 出力は現在の行と定数のみに依存します。
  • .skb.apply(estimator) — 学習データで学習し、テストデータに再適用します。
  • skrub.deferred — まれに使用します。複数の DataOps を組み合わせる場合で、適合する skrub joiner がないときに限ります。デフォルトは apply_func です。 詳細:references/source-binding.md。

カスタムクラスでは、ミックスインを先に、次に BaseEstimator を指定します。ミックスインを最初の基底クラスにします。この順序が重要です。BaseEstimator を先にすると、BaseEstimator.__sklearn_tags__ が先に解決され、ミックスインへ処理を渡さないため、ミックスインが隠れてしまいます。トランスフォーマーは TransformerMixin, BaseEstimator です。予測器は RegressorMixin, BaseEstimator または ClassifierMixin, BaseEstimator です。BaseEstimator だけでは score がないため、skrub は SkrubLearner.score を公開せず、with_scoring という名前も summarize() に表示されません。 詳細:references/common_patterns.md。

学習サブセットとフレーム全体とで出力は変わりますか?はい → .skb.apply を使用します。平均値、中央値、分位点、語彙、ターゲットエンコーディング、TF-IDF はステートフルです。

STOP — target encoding / apply_func. When the user asks for
`def target_encode` + `.skb.apply_func`: refuse. Do not paste
the leaky function body and then the fix. Propose sklearn
TargetEncoder (or TransformerMixin, then BaseEstimator) via
`.skb.apply`. Name `api get` for the signature.

再現性

done 履歴の行は引き続き実行できます。詳細: references/reproducibility_mechanics.md。

  • オプション 1 — 既存の関数に、デフォルトを維持するフラグを追加します。変更は小規模です。デフォルトにより、既存の呼び出し元への影響はありません(include_calendar_features: bool = False)。
  • オプション 2 — 新しい実験からのみ呼び出す新しい関数を作成します。
  • オプション 3 — モジュールを分岐させます。最終手段です。

フラグが 3 つ以上ある場合、またはフラグによって既存の呼び出し元のデフォルトが変わる場合は、オプション 2 を選択するか、停止します。変更後、tests/smoke/ のすべてのテストを pytest で実行します。

停止条件

S0. セットアップがまだ保留中

まず status を確認します。status.setup.pending が空でなく、status.skills.setup-ml-project が true の場合は、setup-ml-project を読み込んで停止します。このスキルを開始してはいけません。戻ってきたら続行します。このターン中に再度読み込んではいけません。そのスキルがインストールされていない場合は、保留中の項目を 1 行で示して停止します。git init、scaffold、または env init を作り出してはいけません。status.setup.env または status.setup.workspace が declined の場合は、1 行で停止します。git または editable が declined の場合は再度尋ねず、続行します。design が不足している場合は design consent を求めます。ask/stop はこの状態のままにします。データコントラクトが不足している場合は、説明して停止します。

S0b. モデリングの決定が確定していない
  • ルール: 宣言を行う前に、status.modeling_decisions が locked であり、python -m skore_skills frame show が null でない translation とともに proceed を返さなければなりません。
  • 復旧: インストールされている場合は frame-ml-problem を読み込みます。translation が null の場合は、パイプラインを作成せずに停止します。テーブルを作り出してはいけません。
S1. 依存関係が不足している

import skrub/sklearn の失敗、または DataOp の HTML スタブがある場合は、skrub と scikit-learn を対象に add-python-package を読み込みます。ここで env add を実行してはいけません。sklearn.Pipeline で代用してはいけません。

S2. 記憶だけを頼りにしたシンボルの使用は禁止

新たに使用する skrub、sklearn、または skore の名前はすべて、このターン中の api get または一致するキャッシュの読み取りから取得します。

S4. skrub.X/skrub.y はグラフのルートではない

skrub.var("<source>", value=preview) をルートにします。既存の skrub.X グラフがある場合は、代替案を示して確認します。自動で書き換えてはいけません。カタログ:references/source-binding.md。

Refuse: skrub.X / skrub.y are not graph roots (S4).
They bake the marker at the source and defeat Layer 1.

Alternative (refactor — ask before rewriting):
  data = skrub.var("data_dir", value=preview).skb.apply_func(load_raw)
  X = data.drop(columns=[TARGET_COL]).skb.mark_as_X()
  y = data[TARGET_COL].skb.mark_as_y()
S5. 特徴量が行をまたぐ場合に mark_as_X を後から指定する

マーカーは、行をまたぐすべてのステップより上流に配置します。症状:len(predictions) != n_predict_grid_rows、feature_steps=[]、またはパイプラインが生成した NaN をフィルタリングするためのラッパー。復旧方法:references/layer_examples.md。smoke を緩めてはいけません。

y = col.shift(-H) を計算してから X としてマークするローダーは、S5 と S6 に該当します。ホライズンはレイヤー 2 に置きます。シフト、dropna、または null のフィルタリングを行うラッパー推定器を作り出してはいけません。

S6. レイヤー 1 では問いを把握しない

ローダーは、どのようなデータが存在するかを記述します。ホライズン、ラグ、ウィンドウ、タスクフィルターはレイヤー 2 以降に置きます。外部の利用者がタスクを知らなければそのステップを導き出せない場合は、レイヤー 1 より後に移動します。

事前確認 — コードの前に出力してください

Pre-flight (build-ml-pipeline):
- [ ] sklearn, skrub, skore import
      Evidence: scratch/<ts>_check_tier1.py. Not inline python -c.
- [ ] api get for new skrub and sklearn symbols this turn
- [ ] Each skrub.var is a source id, not a baked path
- [ ] mark_as_X placement (loaded frame, or predict grid if cross-row)
- [ ] Layer 1 has no horizon, lag, or task filter
- [ ] cv on mark_as_X matches translation
      (date class | GroupKFold | KFold | no cv on holdout
      | prefit: training table only, test table not joined)
- [ ] Non-default translation.metric uses with_scoring
      before make_learner (n/a for a listed skore default;
      required for a multi-output regression aggregate)
- [ ] data_dir_preview=None; no path literal in pipeline.py

最終メッセージの前に、根拠を添えて再出力してください。

参考資料

  • references/snapshot.md — 未適合の Method レポート、実験 セル、任意のサイトビルド。
  • references/layer_examples.md — 3 つのレイヤー。レイヤー 2 を提案する前に 読んでください。
  • references/source-binding.md — 識別子と実体化された ルートの違い。
  • references/reproducibility_mechanics.md — オプション 1/2/3。
  • references/common_patterns.md — コードを含む表形式のパターン。 カスタム予測器(ミックスインの後に BaseEstimator を使用)も含まれます。
  • references/custom-splitter.md — 分割ではロック済みのデプロイメントをコピーします。時系列のセクションは、 translation.scheme が date_time の場合の日付スプリッターです。
  • evaluate-ml-pipeline/references/metadata-routing.md — evaluate では splitter= が省略されます。
  • evaluate-ml-pipeline/references/custom-metrics.md — skore のデフォルトではないスコア。

コメント