Bekannte Informationen vor der Veranstaltung bestimmen

PythonIntermediate
Jetzt üben

Einführung

Ein Gemeinschaftsstudio bereitet das Material sieben Tage vor jedem Workshop vor. Vorhersagen aus nachträglichen Einlass-Scans könnten beeindruckend aussehen, wären zu diesem Stichtag jedoch unbrauchbar. Du erstellst zunächst einen einfachen Vergleichsmaßstab und entscheidest dann, welche Zeilen und Spalten eine echte Vorhersage im Voraus verwenden darf.

Du benötigst Python-Funktionen, einfache Terminaleingaben, pandas-Auswahl und Joins sowie Grundkenntnisse zu Regression und Trainings-/Testaufteilung. Python und die wissenschaftlichen Bibliotheken sind vorbereitet. Alle Tabellen sind eigens erstellte synthetische Lehrdaten; die kleine Stichprobe zeigt einen Arbeitsablauf und garantiert keine Vorhersagen im Produktivbetrieb. Die 55 Minuten sind eine Schätzung des Autors einschließlich Lesen und gewöhnlicher Korrekturen.

Eine einfache Baseline in Personen messen

In diesem Schritt sagst du zwei spätere Workshops anhand eines früheren Medians voraus und interpretierst den mittleren absoluten Fehler.

Beginne in WebIDE und öffne Terminal → New Terminal. Editor und Terminal teilen dieselben Dateien. cd ändert das Arbeitsverzeichnis dieses Terminals; ein neues Terminal benötigt ein eigenes cd.

cd /home/labex/project/workshop-attendance

Der vorbereitete Starter ./python verwendet die Python-Umgebung dieses Kurses. ./ bedeutet „die ausführbare Datei in diesem Verzeichnis“. Verwende ihn für die Kursdateien statt eines System-Pythons. cat zeigt eine Textdatei an, ohne sie zu bearbeiten.

cat warmup-early.csv

Diese kleine Einstiegsübung enthält drei frühere tatsächliche Teilnehmerzahlen: 12, 18 und 24. Ihr Median, der mittlere Wert nach dem Sortieren, beträgt 18 Personen. Eine Baseline sagt für jede spätere Veranstaltung 18 voraus, ohne Veranstaltungsmerkmale zu verwenden.

cat warmup-later.csv

Später kamen 20 Personen zu L-7 und 27 zu L-2. Die absoluten Fehler sind abs(20 - 18) = 2 und abs(27 - 18) = 9. Der mittlere absolute Fehler (MAE) ist ihr Durchschnitt: (2 + 9) / 2 = 5.5 Personen. „Ein durchschnittlicher Fehler von 5,5 Personen“ ist verständlich; eine einheitenlose „Genauigkeit“ würde verdecken, was gemessen wird. Diese Einstiegsübung ist von der anschließend verwendeten vollständigen Saison getrennt.

Erstelle eine wiederverwendbare Baseline-Funktion. Die Shell-Umleitung > ersetzt baseline.py. Das zitierte Here-Dokument <<'PY' schreibt alles bis zu einer Zeile, die nur PY enthält, ohne Shell-Erweiterung in die Datei. Füge den gesamten Block einschließlich des abschließenden PY ein. Alternativ kannst du dieselbe Datei in WebIDE bearbeiten und mit File → Save speichern.

Das Ausführungsprogramm übergibt zwei pandas-Tabellen an summarize. itertuples() durchläuft Zeilen mit benannten Feldern; das Dictionary verknüpft jede spätere Workshop-ID mit ihrem eigenen Fehler. float wandelt pandas-Zahlen für die JSON-Ausgabe in gewöhnliche Python-Zahlen um.

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

Führe das vorbereitete Hilfsprogramm zum Schreiben der Dateien aus. Das Argument baseline wählt diese Phase; es speichert das Funktionsergebnis in output/baseline.json. JSON speichert benannte Werte und Objekte statt CSV-Zeilen.

./python run.py baseline

Die Ausgabe sollte den Median 18.0, die Fehler 2.0 und 9.0 sowie den MAE 5.5 enthalten. Lies das gespeicherte Ergebnis mit dem vorbereiteten Leser, der fehlende Ergebnisse niemals neu erzeugt.

./python show_results.py baseline

Nun hast du einen Vergleichsmaßstab, dessen Fehler dieselbe Einheit wie das Planungsproblem besitzt. Ein späteres Modell muss an denselben Auswertungsveranstaltungen verglichen werden; diesen Übungswert mit einer anderen Stichprobe zu unterbieten wäre kein fairer Vergleich.

Trainingszeit und Vorhersagezeit trennen

In diesem Schritt ordnest du Ergebnisse nach Workshop-ID zu und reservierst spätere Termine für die Auswertung.

Fahre im selben WebIDE-Terminal unter /home/labex/project/workshop-attendance fort. Lies die Saisongrenze und die drei Haupttabellen.

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

Das Datenwörterbuch lautet:

Feld Bedeutung und Verfügbarkeit Verwendung
session_id Stabile Workshop-Identität; beliebige Dateireihenfolge Zeilen zuordnen, niemals Modellmerkmal
event_date Geplanter Veranstaltungstag, ISO YYYY-MM-DD Zeitliche Aufteilung bestimmen
booked_7d Genau sieben Tage vorher gespeicherter Buchungsstand Erlaubtes numerisches Merkmal
duration_minutes Bereits am Sieben-Tage-Stichtag angekündigte Dauer Erlaubtes numerisches Merkmal
final_bookings Endgültige Buchungszahl bei der Veranstaltung Am Vorhersagestichtag nicht verfügbar
scanned_entries Während der Veranstaltung erfasste Einlass-Scans Am Vorhersagestichtag nicht verfügbar
actual_attendance Bis zum Ende des Veranstaltungstags bekanntes Ergebnis Trainingsziel oder zurückgehaltenes Auswertungslabel

Eine leere numerische CSV-Zelle bedeutet fehlende Information, nicht null Buchungen. Jedes erlaubte Merkmal hat mindestens einen beobachteten Trainingswert. IDs sind innerhalb jeder Tabelle eindeutig; labels.csv enthält genau ein Ergebnis pro historischer ID, absichtlich in anderer Reihenfolge. future.csv enthält weder Ergebnisse noch nachträgliche Spalten. Ungültige Schlüssel, vollständig leere Trainingsmerkmale und rollierende Modellaktualisierungen liegen außerhalb des Eingabebereichs dieses Kurses.

Das Modell wird einmal trainiert und am as_of_date, dem 1. April 2026 um 00:00 UTC, eingefroren. Nur vorherige Veranstaltungen dürfen Trainingslabels beitragen. In dieser Saison findet die letzte Trainingsveranstaltung am 8. März statt; ihre Labels sind also bereits verfügbar. Der Holdout beginnt am holdout_start, dem 12. April; sein frühester Sieben-Tage-Vorhersagestichtag ist der 5. April, nach dem Einfrieren. Im Zwischenraum gibt es keine bereitgestellten historischen Veranstaltungen.

Dies sind unterschiedliche Zeitpunkte: Der 1. April friert das angepasste Modell ein; jede spätere Veranstaltung liefert ihren eigenen booked_7d-Stand an ihrem jeweiligen Vorhersagetag. Der Stand vom 5. April für die Veranstaltung am 12. April wird am 5. April verwendet, ohne zu behaupten, er sei am 1. April bekannt gewesen. Diese Dateiübung spielt gespeicherte Stände nach. Die späteren tatsächlichen Labels werden nur zur rückblickenden Leistungsmessung offengelegt. Die Mai-Workshops in future.csv bleiben Vorhersagen ohne Labels.

Ersetze die unvollständige positionsbasierte Aufteilung. Ein eindeutiger Eins-zu-eins-merge verbindet Labels anhand von session_id; er setzt nicht voraus, dass Zeile 1 zu Zeile 1 gehört. pd.to_datetime liest Kalenderdaten ein, pd.Timestamp die konfigurierten Grenzen; boolesche Masken wählen die entsprechenden Zeilen. Sortieren nach Datum und anschließend ID macht die Ausgabe lesbar; die Schreibweise der ID bestimmt niemals den Zeitraum. .copy() erzeugt unabhängige ausgewählte Tabellen.

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

Die Trainingsreihenfolge sollte W-91, W-04, W-77, W-12, W-63, W-02 sein; die Holdout-IDs sind W-88, W-09. Diese unregelmäßigen IDs zeigen, weshalb weder alphabetische Reihenfolge noch die letzten beiden Dateizeilen die Aufteilung festlegen.

./python show_results.py split

Prüfe W-88: Es muss die tatsächliche Teilnehmerzahl 46 seines zugehörigen Labels behalten, nicht das Label an derselben Zeilenposition. Die gespeicherten Dateien training.csv und holdout.csv enthalten nachträgliche Spalten weiterhin zur Betrachtung. Im nächsten Schritt werden nur die zwei erlaubten Merkmale gewählt; die Speicherung als Zahl macht eine Spalte nicht zu einer zulässigen Vorhersageinformation.

Wenn du das Terminal versehentlich schließt, öffne Terminal → New Terminal und wiederhole das obige cd. „No such file or directory“ bedeutet meist ein falsches Verzeichnis oder einen falsch geschriebenen Dateinamen. Zeige mit pwd den aktuellen Pfad und mit ls die Dateien an, kehre in diesen Arbeitsbereich zurück und wiederhole den richtigen Befehl. Starte das Lab nicht wegen eines gewöhnlichen Pfadfehlers neu.

Mittelwerte für fehlende Werte nur aus Trainingsdaten lernen

In diesem Schritt passt du einen Imputer an frühere Workshops an und verwendest ihn für spätere Stände wieder, ohne von diesen zu lernen.

Fahre in WebIDE unter /home/labex/project/workshop-attendance fort. Du darfst baseline.py, split.py, prepare.py und deine output/-Dateien bearbeiten. Bewahre sämtliche gelieferten CSV/JSON-Eingaben, python, run.py, coursekit.py, show_results.py und jede starter-*.py auf. Die Startkopien erlauben die Wiederherstellung eines Moduls; du kannst auch seine vollständige gelehrte Version erneut einfügen. Die Hauptfunktionen müssen bei geänderten Daten, Zeilenreihenfolgen und Zahlen wiederverwendbar bleiben.

Imputation ersetzt ein fehlendes Merkmal durch einen gelernten Wert. SimpleImputer(strategy="mean") lernt das arithmetische Mittel jeder Spalte. Die Trainingsbeobachtungen von booked_7d sind hier 10, 20, 40, 25 und 35: der Mittelwert ist 26. Die sechs bekannten Dauern betragen durchschnittlich 80 Minuten. Alle Zeiträume gemeinsam zu verwenden ließe spätere Workshops diese Trainingsentscheidungen beeinflussen, auch ohne ihre Ergebnislabels. Passe erst nach der Aufteilung an.

Das von coursekit gelieferte FEATURES ist genau ['booked_7d', 'duration_minutes']. Doppelte eckige Klammern wählen diese Spalten in dieser Reihenfolge. fit_transform lernt Mittelwerte und ergänzt die Trainingsmatrix; transform verwendet dieselben Mittelwerte für Holdout- und Zukunftsmatrizen. statistics_ zeigt die gelernten Mittelwerte in Merkmalsreihenfolge. Die zurückgegebenen Arrays behalten die Zeilenreihenfolge jeder Eingabetabelle bei, damit das Hilfsprogramm deren IDs erhalten kann.

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

Die gelernten Mittelwerte sollten booked_7d: 26.0 und duration_minutes: 80.0 sein.

./python show_results.py prepare

In holdout-features.csv verwendet W-88 26 Buchungen und seine beobachteten 150 Minuten; W-09 behält 90 Buchungen und verwendet 80 Minuten. In future-features.csv verwendet F-101 denselben Trainingsmittelwert für Buchungen. Weder endgültige Buchungen, Scans, Datumsangaben, IDs noch Ergebnisse gelangen in diese numerischen Matrizen. Die ursprünglichen leeren Zellen bleiben in den Quelldateien unverändert.

Du hast eine echte Auswertungsgrenze von früher zu später vorbereitet. Dies beweist nicht, dass sich die Zukunft wie die Vergangenheit verhält. Das nächste unabhängige Lab passt ein kleines Modell an und vergleicht seine kontinuierlichen Fehler mit einer Trainingsmedian-Baseline auf demselben gelabelten Holdout. Gleichwertige Berechnungen und andere Ausgabereihenfolgen werden akzeptiert, wenn ID-Zuordnungen und numerische Bedeutung erhalten bleiben; numerische Vergleiche erlauben 1e-8 absolute und relative Toleranz.

Zusammenfassung

Du hast eine wiederverwendbare Median-Baseline erstellt, den MAE in Personen gemessen, Ergebnisse über IDs verbunden und frühere Trainingsdaten von späteren Auswertungsterminen getrennt. Du hast nur Informationen ausgewählt, die sieben Tage vorher vorliegen, und die Mittelwerte zur Ergänzung fehlender Werte ausschließlich an Trainingszeilen angepasst. Die gespeicherten Tabellen behalten die ursprünglichen Identitäten; die Quelldaten bleiben für die nächste Analysephase erhalten.