File size: 3,729 Bytes
c023008
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""Fit the formal 3686-case experiment on a SLURM compute node."""
import argparse
from datetime import datetime, timezone
import importlib.metadata
import os
from pathlib import Path
import platform
import time

import numpy as np
from common import (load_config, ensure_compute_node, load_fixed_dataset, metrics_for,
                    print_metrics, prediction_frame, write_json, write_metrics, sha256, WavyChannelRF)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--config", required=True)
    args = parser.parse_args()
    config = load_config(args.config)
    runtime = ensure_compute_node(config)
    directory = Path(config["output"]["results_dir"])
    directory.mkdir(parents=True, exist_ok=True)
    started = time.perf_counter()
    data, data_manifest = load_fixed_dataset(config)
    split_col = config["data"]["split_column"]
    train, test = (data.loc[data[split_col] == split] for split in ["train", "test"])
    features, targets = config["data"]["features"], config["data"]["targets"]
    versions = {p: importlib.metadata.version(p) for p in ["numpy", "pandas", "scikit-learn", "joblib", "PyYAML", "matplotlib"]}
    print("[train] Formal full fit: two independent Random Forests, 800 trees per target; no epochs.", flush=True)
    model = WavyChannelRF(config["model"]["rf_params"])
    model.fit(train[features], train[targets])
    predictions = model.predict(test[features])
    train_predictions = model.predict(train[features])
    metrics = metrics_for(test[targets], predictions, targets)
    train_metrics = metrics_for(train[targets], train_predictions, targets)
    print_metrics("test", metrics, len(test))
    print_metrics("train", train_metrics, len(train))
    manifest = {"experiment": config["experiment"], "utc_time": datetime.now(timezone.utc).isoformat(),
                "runtime": runtime, "python": platform.python_version(), "versions": versions,
                "data": data_manifest, "fit_seconds": model.fit_seconds_,
                "fitted_train_rows": model.n_train_,
                "trees_per_target": {t: len(model.models_[t].estimators_) for t in targets},
                "actual_rf_parameters": {t: model.models_[t].get_params() for t in targets},
                "checkpoint_semantics": "sole fully fitted formal model; no validation/test model selection",
                "serialization": "joblib bundle containing two fitted sklearn forests; .pth is requested filename",
                "sources": config["reference"], "training_script_sha256": sha256(__file__),
                "model_source_sha256": sha256(Path(__file__).resolve().parents[1] / "model/wavy_channel_rf.py")}
    checkpoint = Path(config["output"]["checkpoint"])
    model.save(checkpoint, manifest)
    print(f"[save] Reloadable joblib checkpoint: {checkpoint} ({checkpoint.stat().st_size} bytes)", flush=True)
    write_metrics(directory, metrics)
    write_json(directory / "train_metrics.json", train_metrics)
    prediction_frame(test, predictions, config).to_csv(directory / "test_predictions.csv", index=False)
    model.feature_importances().to_csv(directory / "feature_importances.csv", index=False)
    write_json(directory / "data_manifest.json", data_manifest)
    write_json(directory / "config_snapshot.json", config)
    manifest.update({"test_metrics": metrics, "checkpoint": str(checkpoint), "checkpoint_sha256": sha256(checkpoint),
                     "total_seconds": time.perf_counter() - started, "execution_state": "completed"})
    write_json(directory / "run_manifest.json", manifest)
    print(f"[train] Completed formal experiment in {manifest['total_seconds']:.3f} s", flush=True)


if __name__ == "__main__":
    main()