File size: 3,530 Bytes
6cf9dac | 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | """Run one frozen neural outer split so long training is restart-safe."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
import numpy as np
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from revision.scripts.reanalysis_neural import run_neural_stack
from revision.scripts.reanalysis_pipeline import (
_extract_features,
_write_sha256_manifest,
validate_config,
)
from revision.scripts.run_revision_reanalysis import configure_utf8_console
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Train GAT, GCN, FPNN, and the fixed stack for one frozen outer split."
)
parser.add_argument(
"--config",
default=str(PROJECT_ROOT / "revision" / "config" / "reanalysis.json"),
)
parser.add_argument(
"--artifacts-root",
default=str(PROJECT_ROOT / "revision" / "artifacts" / "reviewer_requested_reanalysis_v4"),
)
parser.add_argument("--strategy", required=True)
parser.add_argument("--seed", required=True, type=int)
return parser.parse_args()
def main() -> int:
configure_utf8_console()
args = parse_args()
config = validate_config(
json.loads(Path(args.config).resolve().read_text(encoding="utf-8")),
PROJECT_ROOT,
)
if args.strategy not in config["split_strategies"]:
raise ValueError(f"Unknown strategy: {args.strategy}")
if args.seed not in config["outer_seeds"]:
raise ValueError(f"Seed was not predeclared: {args.seed}")
artifacts_root = Path(args.artifacts_root).resolve()
expected_root = Path(config["output_root"]).resolve()
if artifacts_root != expected_root:
raise ValueError(
f"Artifacts root must match the frozen config: {expected_root}"
)
if not (artifacts_root / "SHA256SUMS.txt").is_file():
raise FileNotFoundError("Completed classical artifacts and SHA256SUMS.txt are required first.")
annotated = pd.read_csv(artifacts_root / "record_identity_manifest.csv")
descriptor_matrix, fingerprint_matrix = _extract_features(
annotated,
config["descriptor_features"],
config["fingerprint"],
)
split_dir = artifacts_root / args.strategy / f"seed_{args.seed}"
split_data = np.load(split_dir / "split_indices.npz", allow_pickle=True)
development = np.asarray(split_data["development_indices"], dtype=int)
test = np.asarray(split_data["test_indices"], dtype=int)
inner_train = split_data["inner_train_indices"]
inner_validation = split_data["inner_validation_indices"]
inner_folds = [
(np.asarray(train, dtype=int), np.asarray(validation, dtype=int))
for train, validation in zip(inner_train, inner_validation)
]
output = run_neural_stack(
config,
annotated=annotated,
descriptor_matrix=descriptor_matrix,
fingerprint_matrix=fingerprint_matrix,
train_indices=development,
test_indices=test,
inner_folds=inner_folds,
output_dir=split_dir / "neural_stack",
seed=args.seed,
smoke_only=False,
)
_write_sha256_manifest(artifacts_root)
print(f"Completed frozen neural split: {output}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
|