build-ml-pipeline について
build-ml-pipelineは、データサイエンティスト向けに、skrub DataOpsグラフを宣言し、分割器や既定以外のスコアを設定するワークフロースキルです。スモークテストを含みますが、構築時の学習や全データ評価は行いません。
主な機能
- 01skrub DataOpsグラフの宣言
- 02特徴量のマークと推定器の追加
- 03分割器とカスタムスコアの設定
- 04未学習学習器のスナップショット作成
- 05パイプラインのスモークテスト
活用シーン
- 01承認済みMLパイプラインの構築
- 02デプロイ方式に沿った交差検証の設定
- 03既定以外の評価スコアの追加
- 04評価前のパイプライン確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ probabl-ai/ skore-skills --skill build-ml-pipelineインストール後、Claude Code で/build-ml-pipelineを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/common_patterns.mdcustom-splitter.mdlayer_examples.mdreproducibility_mechanics.mdsnapshot.mdsource-binding.md詳細
ML パイプラインの構築
skrub の DataOps グラフを宣言し、ロック済みの分割器と
デフォルト以外のスコアがあれば追加します。ここでの最後の手順は Smoke です。skore.evaluate の
fit、チューニング、永続化、呼び出しは行わないでください。
ユーザー向けの文章
詳細:setup-workspace references/human_facing_prose.md。
実験の Markdown、設計メモの Method テキスト、# コメントで
このパイプラインを説明します。質問とチェックポイントでは、
スキル ID、G-* 名、ラッパー CLI ではなく、同じデータサイエンス用語を使います。
``はサイトマーカーです。
作成時のヒントはこのスキル内にあります。
X マーカーは.skb.mark_as_X()です。予測グリッドはスコアリング対象の行です。
行間ステップは他の行を読み取ります(ラグ、ローリング、グループ集計、サイド結合)。
レイヤー 1 / 2 / 3は、ソース、グリッドとマーカー、マーカー後の特徴量です。
手順
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の場合は停止します。分割器の翻訳がありません。- 最初の書き込みの前に、1~3 文を出力します。これは、未学習の
build_learner、 Method セル、パイプラインのスナップショットをローカルで準備し、その後 Smoke を行う作業です。 学習もデータセット全体の評価も実行しません。所要時間を作り上げないでください。一度だけ述べます。 承認が保留中の場合は、プレビューのみ行います。 - Pre-flight を出力します。このターンの根拠がある場合にのみチェックボックスにチェックを入れます。
build_learnerを宣言します(ルール 1~3)。まずソース、特徴量、推定器を用意します。 その後、.skb.make_learner()の前に、translationからcvとデフォルト以外のスコアがあれば追加します。 新しいシンボルごとにpython -m skore_skills api getを実行します。編集後はpython -m skore_skills styleを実行します。 プローブはenv verifyの合成開発用 Python を使ってscratch/に保存します。 インラインのpython -cは使わないでください。ユーザーから依頼がない限り、警告フィルターは使わないでください。- 未学習のスナップショット:
references/snapshot.md。 - この stem の
experiments/NN_*.pyが存在する場合は、そのスキルがインストールされているときに限りsmoke-test-ml-pipelineを読み込みます。スキルがない場合は 1 行だけ伝え、pytest ファイルを作り上げないでください。 次にpython -m skore_skills smoke run --stem <stem>を実行します。JSON がstop/red/smoke_missingの場合は、ここでグラフを修正します。 アサーションを緩めないでください。評価は行わないでください。 このコマンドを実行せずに pytest が成功したと主張しないでください。 smoke runがproceedの場合は、以下のチェックポイントを経て、python -m skore_skills evaluate consent --stem <stem>を実行します。ask— JSON のcontext(question、experiment、smoke、persisted_report)を引用し、 回答によって許可される内容、設計上の質問、この stem にはまだ永続化されたレポートがないことを 2~4 行で説明します。その後、AskUserQuestion を使い、Evaluate(推奨)/Modify/Stop の選択肢を示して停止します。skore.evaluateは記述しないでください。Modify の場合は編集してから、再度smoke runを実行します。 Stop の場合は終了します。proceed— レポートはすでに存在します。そのスキルがインストールされていればevaluate-ml-pipelineを読み込むか、このスキルを呼び出したスキルがmodel-ml-pipelineならそこに戻ります。stop— Smoke ファイルがありません。評価しないでください。 ユーザーが Evaluate と回答した場合は、インストールされていればevaluate-ml-pipelineを読み込みます。smoke runのproceedはその回答ではありません。
チェックポイント
smoke run の proceed の後、Evaluate メニューの前に出します。2~6
文で、何を宣言したか、Smoke が成功したこと、学習器を説明します。
Method の内容を根拠にしてください。メトリクスを作り上げないでください。まだロケーターはありません。
続いてリンクを示します。このターンに site build を実行した場合は、ウェブサイトが更新されたと伝え、
その出力にある file:// 行をそのまま貼り付けます。
設計メモの 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 のデフォルトではないスコア。