開催前に分かっている情報を定める

PythonIntermediate
オンラインで実践に進む

はじめに

地域のスタジオでは、各ワークショップの7日前に材料を準備します。開催後の入場スキャンを使えば見栄えのよい予測ができても、その締め切りには役立ちません。まず単純なベースラインを作り、実際の事前予測で使用できる行と列を判断します。

Python の関数、基本的なターミナル入力、pandas の選択と結合、回帰と訓練・テスト分割の入門知識が必要です。Python と科学計算ライブラリは準備済みです。すべての表は独自に作成した合成教材データです。小標本で手順を示すもので、本番の予測性能を保証しません。55分は、読解と通常の修正を含む著者の見積もりです。

単純なベースラインを人数で測る

このステップでは、早期の中央値から後の2回のワークショップを予測し、平均絶対誤差を解釈します。

WebIDE から Terminal → New Terminal を開きます。エディタとターミナルはファイルを共有します。cd はこのターミナルの作業ディレクトリを変えます。新しいターミナルでは、別途 cd が必要です。

cd /home/labex/project/workshop-attendance

準備済みの ./python ランチャーは、このコースの Python 環境を使います。./ は「このディレクトリにある実行ファイル」を意味します。コースのファイルにはシステムの Python ではなく、これを使ってください。cat はテキストファイルを編集せずに表示します。

cat warmup-early.csv

この小さな練習には、早期の実際の参加人数 12、18、24 が含まれています。並べ替えた中央の値である中央値は18人です。ベースラインは、イベントの特徴を使わず、後のどのイベントにも18人と予測します。

cat warmup-later.csv

後期の実際の人数は L-7 が20人、L-2 が27人です。絶対誤差は abs(20 - 18) = 2 と abs(27 - 18) = 9 です。平均絶対誤差(MAE)はその平均、(2 + 9) / 2 = 5.5 人です。「平均5.5人の誤差」には明確な意味がありますが、単位のない「精度」では測定対象が曖昧になります。この練習は、次に使うシーズン全体のデータとは別です。

再利用可能なベースライン関数を作ります。シェルのリダイレクト > は baseline.py を置き換えます。引用符付きヒアドキュメント <<'PY' は、PY だけの行までの内容を、シェル展開せずファイルへ送ります。最後の PY も含めてブロック全体を貼り付けてください。WebIDE で同じファイルを編集し、File → Save で保存しても構いません。

実行用プログラムは、2つの pandas 表を summarize に渡します。itertuples() は名前付きフィールドを持つ行を順に処理し、辞書は各後期ワークショップの ID とその誤差を対応付けます。float は JSON 出力用に pandas の数値を通常の Python 数値に変換します。

cat > baseline.py <<'PY'
def summarize(early, later):
    baseline = float(early.actual_attendance.median())
    errors = {
        row.session_id: float(abs(row.actual_attendance - baseline))
        for row in later.itertuples()
    }
    return {
        "median_attendance": baseline,
        "absolute_errors": errors,
        "mae": sum(errors.values()) / len(errors),
    }
PY

準備済みのファイル書き込み用補助プログラムを実行します。引数 baseline がこの段階を選び、関数の結果を output/baseline.json に保存します。JSON は CSV の行ではなく、名前付きの値やオブジェクトを保存します。

./python run.py baseline

表示には中央値 18.0、誤差 2.0 と 9.0、MAE 5.5 が含まれるはずです。保存した成果物を準備済みのリーダーで読みます。このリーダーは欠けた結果を再生成しません。

./python show_results.py baseline

これで、計画の課題と同じ単位の誤差を持つ比較基準ができました。後のモデルは同じ評価イベントで比較する必要があります。別の標本でこの練習の値を上回っても、公平な比較にはなりません。

訓練時点と予測時点を分ける

このステップでは、ワークショップ ID で結果を対応付け、後の日付を評価用に確保します。

同じ WebIDE ターミナルの /home/labex/project/workshop-attendance で続けます。シーズンの境界と3つの主要な表を読みます。

cat season.json
cat history.csv
cat labels.csv
cat future.csv

データ辞書は次のとおりです。

フィールド 意味と利用可能になる時点 用途
session_id ワークショップの安定した識別子。ファイル順は任意 行の対応付け。モデル特徴にはしない
event_date 開催予定日。ISO YYYY-MM-DD 形式 時間による分割を決める
booked_7d 開催のちょうど7日前に保存した予約スナップショット 使用できる数値特徴
duration_minutes 7日前の締め切りまでに公表された所要時間 使用できる数値特徴
final_bookings 開催時の最終予約総数 予測の締め切りでは利用不可
scanned_entries 開催時に集めた入場スキャン 予測の締め切りでは利用不可
actual_attendance 開催当日の終了までに分かる結果 訓練の目的変数または保留評価ラベル

CSV の数値セルが空欄なら、予約ゼロではなく情報の欠損です。どの使用可能な特徴にも、少なくとも1つの観測された訓練値があります。各表内で ID は一意です。labels.csv には各過去 ID の結果がちょうど1つあり、意図的に別の順序で並んでいます。future.csv には結果や開催後の列はありません。不正なキー、訓練特徴列の全欠損、モデルの逐次更新は、このコースの入力範囲外です。

モデルは1回だけ訓練し、as_of_date、つまり 2026年4月1日 00:00 UTC に固定します。その日より前のイベントだけが訓練ラベルを提供できます。このシーズンの最後の訓練イベントは3月8日なので、そのラベルはすでに利用可能です。保留集合は holdout_start の4月12日から始まります。最初の7日前予測の締め切りは4月5日で、訓練固定後です。提供された過去イベントは、この間の空白期間にはありません。

ここには異なる2つの時計があります。4月1日に学習済みモデルを固定し、後の各イベントは自身の予測日に自身の booked_7d を提供します。4月12日のイベントの4月5日のスナップショットは4月5日に使うのであり、4月1日に既知だったとは主張しません。このファイル演習は、保存済みスナップショットを再現します。後期の実際のラベルは、事後的な性能測定のためだけに明らかにします。future.csv の5月のワークショップは、引き続きラベルなしの予測です。

未完成の位置依存の分割を置き換えます。1対1の merge は session_id でラベルを結び、1行目同士が一致するとは仮定しません。pd.to_datetime は日付を、pd.Timestamp は設定された境界を解釈し、ブールマスクが該当行を選びます。日付、その後 ID で並べ替えると読みやすくなりますが、ID の綴りで期間を決めることはありません。.copy() は選択した表を独立したコピーにします。

cat > split.py <<'PY'
import pandas as pd


def split_events(history, labels, season):
    events = history.merge(labels, on="session_id", validate="one_to_one")
    dates = pd.to_datetime(events["event_date"])
    train = events.loc[dates < pd.Timestamp(season["as_of_date"])].copy()
    holdout = events.loc[dates >= pd.Timestamp(season["holdout_start"])].copy()
    return (
        train.sort_values(["event_date", "session_id"]),
        holdout.sort_values(["event_date", "session_id"]),
    )
PY
./python run.py split

訓練の順序は W-91, W-04, W-77, W-12, W-63, W-02、保留 ID は W-88, W-09 のはずです。不規則な ID は、アルファベット順やファイル末尾の2行では分割を決められない理由を示しています。

./python show_results.py split

W-88 を確認してください。同じ行位置のラベルではなく、対応するラベルの実際の人数46を保つ必要があります。保存された training.csv と holdout.csv には、確認のため開催後の列も残っています。次のステップでは使用可能な2特徴だけを選びます。数値として保存されていても、予測に使える列とは限りません。

ターミナルを誤って閉じた場合は、Terminal → New Terminal を開き、上の cd を繰り返します。「No such file or directory」は通常、ディレクトリの間違いやファイル名の誤記です。pwd で現在のパス、ls でファイル一覧を確認し、この作業場所に戻って正しいコマンドを再実行してください。通常のパスの間違いでラボを再起動する必要はありません。

欠損値の平均を訓練データだけから学ぶ

このステップでは、早期のワークショップで1つの補完器を学習し、後期のスナップショットからは学習せずに再利用します。

WebIDE の /home/labex/project/workshop-attendance で続けます。baseline.py、split.py、prepare.py と自分の output/ ファイルを編集できます。提供された CSV/JSON 入力、python、run.py、coursekit.py、show_results.py、すべての starter-*.py を保ってください。初期コピーからモジュールを復元でき、教わった完全版を再度貼り付けても構いません。日付、行順、数値が変わっても主要関数を再利用できる必要があります。

補完は、欠損した特徴を学習した値で置き換えます。SimpleImputer(strategy="mean") は各列の算術平均を学習します。ここで booked_7d の訓練観測値は10、20、40、25、35で、平均は26です。既知の6つの所要時間の平均は80分です。全期間を使うと、結果ラベルを使わなくても後期ワークショップが訓練の選択に影響します。分割してから学習し、先に学習しないでください。

coursekit が提供する FEATURES は、正確に ['booked_7d', 'duration_minutes'] です。二重の角括弧で、この順序で2列を選びます。fit_transform は平均を学び訓練行列を補完し、transform は同じ平均を保留・未来の行列に使います。statistics_ は特徴順に学習した平均を示します。戻り値の配列は各入力表の行順を保ち、補助プログラムが ID を維持できるようにします。

cat > prepare.py <<'PY'
from sklearn.impute import SimpleImputer
from coursekit import FEATURES


def prepare_features(train, holdout, future):
    imputer = SimpleImputer(strategy="mean")
    training_values = imputer.fit_transform(train[FEATURES])
    holdout_values = imputer.transform(holdout[FEATURES])
    future_values = imputer.transform(future[FEATURES])
    return training_values, holdout_values, future_values, imputer.statistics_
PY
./python run.py prepare

学習した平均は booked_7d: 26.0 と duration_minutes: 80.0 のはずです。

./python show_results.py prepare

holdout-features.csv では、W-88 は予約26と観測済みの150分を使い、W-09 は予約90を保って80分を使います。future-features.csv の F-101 も同じ訓練予約平均を使います。最終予約、スキャン、日付、ID、結果は、これらの数値行列には入りません。入力ファイルの元の空欄も変わりません。

早期から後期へ進む本当の評価境界ができました。ただし、将来が過去と同じ挙動になる証明ではありません。次の独立ラボでは、小モデルを学習し、同じラベル付き保留集合で連続予測誤差を訓練中央値ベースラインと比較します。ID の対応と数値の意味が同じなら、同等の計算や異なる出力行順も受け入れます。数値比較の絶対・相対許容誤差は 1e-8 です。

まとめ

再利用可能な中央値ベースラインを作り、MAE を人数単位で測定し、ID で結果を結合して、早期の訓練日と後期の評価日を分けました。7日前に利用できる情報だけを選び、欠損値補完用の平均を訓練行だけで学習しました。保存した表は元の識別関係を保ち、入力データも次の分析段階に向けて変更せずに残っています。