Download verify_completion.py from Crystalbullet/lunar_project: direct link, hf CLI and curl.
- Browser
- Download file 6.94 kB
-
https://huggingface.co/Crystalbullet/lunar_project/resolve/main/verify_completion.py
- Command line
-
hf download hf://Crystalbullet/lunar_project/verify_completion.py
-
curl -L -o verify_completion.py https://huggingface.co/Crystalbullet/lunar_project/resolve/main/verify_completion.py
6.94 kB
| """Independent post-run acceptance checks and full checkpoint prediction replay.""" | |
| import argparse | |
| import json | |
| from dataclasses import asdict | |
| from pathlib import Path | |
| import numpy as np | |
| import pandas as pd | |
| import torch | |
| from experiment_utils import DEFAULT_EXPERIMENT, ROOT, atomic_csv, fingerprint, metrics, sha, validate_submission | |
| from training_engine import Settings, build_model, load_checkpoint, metadata_signature, prediction_frame, setup, source_hash | |
| from verify_inputs import verify | |
| def verify_completion(out): | |
| out = Path(out) | |
| verify(out) | |
| checks = [] | |
| def passed(name, detail): | |
| checks.append(dict(check=name, passed=True, detail=detail)) | |
| audit = pd.read_csv(out/'data_audit.csv') | |
| eligible = pd.read_csv(out/'eligible.csv') | |
| excluded = pd.read_csv(out/'excluded_samples.csv') | |
| assert set(eligible.image_id).isdisjoint(excluded.image_id) | |
| assert set(eligible.image_id) | set(excluded.image_id) == set(audit.image_id) | |
| passed('source_row_accounting', f'{len(eligible)} eligible + {len(excluded)} quarantined = {len(audit)}') | |
| manifest = pd.read_csv(out/'split_manifest.csv') | |
| for fold, frame in manifest.groupby('fold'): | |
| assert frame.groupby('group').role.nunique().max() == 1 | |
| assert not frame.image_id.duplicated().any() | |
| if fold < 5: assert set(frame.partition) == {'development'} | |
| outer = manifest.query('fold<5 and role=="outer"') | |
| assert not outer.image_id.duplicated().any() | |
| assert set(outer.image_id) == set(eligible.query('partition=="development"').image_id) | |
| passed('nested_group_splits', 'Five disjoint outer folds cover development exactly once; holdout excluded') | |
| oof = pd.read_csv(out/'selected_oof.csv') | |
| assert set(oof.image_id) == set(outer.image_id) and not oof.image_id.duplicated().any() | |
| passed('selected_oof_coverage', f'{len(oof)} unique development predictions') | |
| state = load_checkpoint(out/'models/final_refit/inference.pt') | |
| choice = json.loads((out/'selection.json').read_text()) | |
| summary = pd.read_csv(out/'run_summary.csv').iloc[0] | |
| settings = Settings(**state['settings']) | |
| assert state['complete'] and settings.fixed_schedule and state['fold'] == -1 | |
| assert state['epoch'] == choice['refit_epochs'] == summary.final_epochs | |
| assert summary.eligible_rows == len(eligible) | |
| assert state['threshold'] == choice['threshold'] | |
| assert settings.use_metadata | |
| expected_signature=fingerprint(dict(settings=asdict(settings),fold=-1, | |
| data=metadata_signature(out),source=source_hash(),ids={'fit':eligible.image_id.tolist()})) | |
| assert state['signature']==expected_signature | |
| passed('final_refit_configuration', f'{state["epoch"]} fixed epochs, joint image/angle model, frozen OOF threshold') | |
| pair_metrics=[] | |
| for run in (out/'models').iterdir(): | |
| if not (run/'latest.pt').exists(): continue | |
| latest = load_checkpoint(run/'latest.pt') | |
| history = pd.read_csv(run/'training_history.csv') | |
| assert latest['complete'], run.name | |
| assert history.epoch.tolist() == list(range(1, latest['epoch']+1)), run.name | |
| if (run/'outer_predictions.csv').exists(): | |
| predictions=pd.read_csv(run/'outer_predictions.csv') | |
| threshold=float(pd.read_csv(run/'metrics.csv').query('role=="outer"').threshold.iloc[0]) | |
| paired=predictions.groupby('pixel_hash').image_id.transform('size')>1 | |
| for name,mask in [('repeated_image_observations',paired),('single_image_observations',~paired)]: | |
| subset=predictions[mask] | |
| if len(subset): | |
| pair_metrics.append(dict(run_id=run.name,subset=name, | |
| **metrics(subset.label,subset.probability,threshold))) | |
| atomic_csv(out/'pair_group_metrics.csv',pd.DataFrame(pair_metrics)) | |
| passed('epoch_commit_histories', 'Every saved experiment completed; contiguous epochs without duplicates') | |
| meta = pd.read_csv(ROOT/'Test_DATA/test_metadata.csv') | |
| saved = pd.read_csv(out/'submission.csv') | |
| root = pd.read_csv(ROOT/'submission.csv') | |
| validate_submission(saved, meta.image_id) | |
| pd.testing.assert_frame_equal(saved, root) | |
| setup(settings.seed) | |
| model = build_model(settings, False).cuda() | |
| model.load_state_dict(state['model']) | |
| replay = prediction_frame(model, meta, settings, state['threshold'], ROOT/'Test_DATA/eval_images') | |
| probabilities = pd.read_csv(out/'evaluation_probabilities.csv') | |
| # Fast cuDNN/FP16 kernels can choose different algorithms across processes. | |
| # Require exact label identity; tolerate one FP16 epsilon for probabilities. | |
| tolerance=float(torch.finfo(torch.float16).eps) if settings.amp else 1e-5 | |
| differences=pd.DataFrame(dict(image_id=meta.image_id,saved_probability=probabilities.probability, | |
| replay_probability=replay.probability,absolute_difference=np.abs(replay.probability-probabilities.probability), | |
| saved_label=saved.label,replay_label=replay.prediction)) | |
| atomic_csv(out/'inference_replay_differences.csv',differences) | |
| max_difference=float(differences.absolute_difference.max()) | |
| label_mismatches=int((saved.label!=replay.prediction).sum()) | |
| atomic_csv(out/'inference_replay_summary.csv',pd.DataFrame([dict(rows=len(meta), | |
| label_mismatches=label_mismatches,max_absolute_probability_difference=max_difference, | |
| absolute_probability_tolerance=tolerance,precision='AMP_FP16' if settings.amp else 'FP32')])) | |
| np.testing.assert_array_equal(replay.prediction, saved.label) | |
| np.testing.assert_allclose(replay.probability, probabilities.probability, rtol=0, atol=tolerance) | |
| passed('full_gpu_inference_replay', f'All {len(meta)} labels reproduced; max probability drift {max_difference:.8f}, tolerance {tolerance:.8f}; not a bitwise probability claim') | |
| passed('submission_schema_and_root_copy', f'image_id,label; exact IDs/order; sha256={sha((out/"submission.csv").read_bytes())}') | |
| holdout = pd.read_csv(out/'holdout_predictions.csv') | |
| expected_holdout = set(eligible.query('partition=="holdout"').image_id) | |
| assert set(holdout.image_id) == expected_holdout | |
| rule = ((holdout.sun_azimuth_angle.to_numpy() % 360) < 270).astype(float) | |
| comparators = pd.DataFrame([ | |
| dict(variant='selected_neural', **metrics(holdout.label, holdout.probability, choice['threshold'])), | |
| dict(variant='fixed_angle_rule', **metrics(holdout.label, rule)), | |
| ]) | |
| atomic_csv(out/'holdout_comparison.csv', comparators) | |
| passed('sealed_holdout_coverage', f'{len(holdout)} rows; fixed-angle comparator is diagnostic only, no reselection') | |
| atomic_csv(out/'completion_checks.csv', pd.DataFrame(checks)) | |
| print(pd.DataFrame(checks).to_string(index=False), flush=True) | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('--experiment', type=Path, default=DEFAULT_EXPERIMENT) | |
| verify_completion(parser.parse_args().experiment) | |