Download scripts/infer_unknown.py from Laibaff7/cda-emr-classifier: direct link, hf CLI and curl.
- Browser
- Download file 3.35 kB
-
https://huggingface.co/Laibaff7/cda-emr-classifier/resolve/main/scripts/infer_unknown.py
- Command line
-
hf download hf://Laibaff7/cda-emr-classifier/scripts/infer_unknown.py
-
curl -L -o infer_unknown.py https://huggingface.co/Laibaff7/cda-emr-classifier/resolve/main/scripts/infer_unknown.py
3.35 kB
| """ | |
| Inference: rank all unknown spectra by EMR probability using the 5-model ensemble. | |
| Input : Data Parquet/unknown_data_after_noise_filter_cropped.parquet (sclk + spectrum_cropped) | |
| Models: EMR Classifier/models/emr_model_seed_*.pth | |
| Output: EMR Classifier/predictions/emr_candidates_unknown.csv (all rows, sorted desc) | |
| EMR Classifier/predictions/emr_top100.csv (top 100 for manual review) | |
| """ | |
| import os | |
| import numpy as np | |
| import pandas as pd | |
| import torch | |
| from torch.utils.data import DataLoader, TensorDataset | |
| from train_emr_classifier import Spectra1DCNN, TARGET_LEN, minmax | |
| ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # EMR Classifier/ | |
| DATA_PATH = os.path.join(ROOT, 'Data Parquet', 'unknown_data_after_noise_filter_cropped.parquet') | |
| MODELS_DIR = os.path.join(HERE, 'models') | |
| OUT_DIR = os.path.join(HERE, 'predictions') | |
| os.makedirs(OUT_DIR, exist_ok=True) | |
| BATCH_SIZE = 256 | |
| def main(): | |
| device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
| print(f'Using device: {device}') | |
| print('Loading unknown data (sclk + spectrum_cropped)...') | |
| df = pd.read_parquet(DATA_PATH, columns=['sclk', 'spectrum_cropped']) | |
| X = np.stack(df['spectrum_cropped'].to_numpy()).astype(np.float32) | |
| X = minmax(X) | |
| print(f' {X.shape}') | |
| model_files = sorted(f for f in os.listdir(MODELS_DIR) if f.startswith('emr_model_seed_')) | |
| models = [] | |
| for mf in model_files: | |
| m = Spectra1DCNN(TARGET_LEN) | |
| m.load_state_dict(torch.load(os.path.join(MODELS_DIR, mf), map_location=device)) | |
| m.to(device).eval() | |
| models.append(m) | |
| print(f'Loaded {len(models)} ensemble models: {model_files}') | |
| loader = DataLoader(TensorDataset(torch.from_numpy(X).unsqueeze(1)), | |
| batch_size=BATCH_SIZE, shuffle=False, num_workers=0) | |
| preds = np.zeros(len(X), dtype=np.float32) | |
| with torch.no_grad(): | |
| for i, (bx,) in enumerate(loader): | |
| bx = bx.to(device) | |
| acc = torch.zeros(bx.size(0), device=device) | |
| for m in models: | |
| acc += torch.sigmoid(m(bx)).squeeze(-1) | |
| acc /= len(models) | |
| s = i * BATCH_SIZE | |
| preds[s:s + bx.size(0)] = acc.cpu().numpy() | |
| if (i + 1) % 40 == 0: | |
| print(f' {(i + 1) * BATCH_SIZE:,} / {len(X):,}') | |
| df['emr_probability'] = preds | |
| df_sorted = (df.drop(columns=['spectrum_cropped']) | |
| .sort_values('emr_probability', ascending=False) | |
| .reset_index(names='original_parquet_index')) | |
| out_all = os.path.join(OUT_DIR, 'emr_candidates_unknown.csv') | |
| df_sorted.to_csv(out_all, index=False) | |
| print(f'Wrote {out_all} ({len(df_sorted):,} rows)') | |
| out_top = os.path.join(OUT_DIR, 'emr_top100.csv') | |
| df_sorted.head(100).to_csv(out_top, index=False) | |
| print(f'Wrote {out_top}') | |
| print(f'\nProbability distribution: ' | |
| f'mean={preds.mean():.4f} p50={np.percentile(preds, 50):.4f} ' | |
| f'p99={np.percentile(preds, 99):.4f} p99.9={np.percentile(preds, 99.9):.4f} ' | |
| f'max={preds.max():.4f}') | |
| for thr in (0.5, 0.75, 0.9): | |
| print(f' rows with emr_probability >= {thr}: {(preds >= thr).sum():,}') | |
| if __name__ == '__main__': | |
| main() |