Spaces:
Sleeping
Sleeping
Download utils/dm_risk.py from thinkhong/AI_Challenge2026: direct link, hf CLI and curl.
- Browser
- Download file 3.83 kB
-
https://huggingface.co/spaces/thinkhong/AI_Challenge2026/resolve/main/utils/dm_risk.py
- Command line
-
hf download hf://spaces/thinkhong/AI_Challenge2026/utils/dm_risk.py
-
curl -L -o dm_risk.py https://huggingface.co/spaces/thinkhong/AI_Challenge2026/resolve/main/utils/dm_risk.py
3.83 kB
| """DM ๊ฐ์ธ๋ณ ์ํ์์ธ - local SHAP. | |
| LLM_Report/utils/dm_risk.py์ ๊ณ์ฐ ๋ก์ง์ ๊ฐ๋ค(5-fold ์ฒดํฌํฌ์ธํธ ๊ฐ๊ฐ์ | |
| ๋ํด KernelExplainer๋ก local SHAP์ ๊ตฌํ๊ณ ํ๊ท - ์ฌํ์ต ์์). ๋ค๋ฅธ ์ ์ | |
| ๋ฐฐ๊ฒฝํ๋ณธ์ ์๋ณธ ๋ฐ์ดํฐ์์ ์ค์๊ฐ์ผ๋ก kmeans ์์ฝํ์ง ์๊ณ | |
| WEB/scripts/precompute_artifacts.py๊ฐ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋ dm_shap_background.csv | |
| (kmeans ํฉ์ฑ ๋ํ์ 100๊ฐ, ์ค์ ๊ฐ์ธ ๋ ์ฝ๋ ์๋)๋ฅผ ๊ทธ๋๋ก ์ด๋ค๋ ๊ฒ - | |
| ์๋ณธ ๋ฐ์ดํฐ๋ฅผ Space์ ์ ์ฌ๋ฆฌ๊ธฐ ์ํจ์ด์, ๋งค ์์ฒญ๋ง๋ค kmeans๋ฅผ ๋ค์ ์ | |
| ๋๋ ค๋ ๋๋ฏ๋ก ๋ ๋น ๋ฅด๋ค(๋ฌด๋ฃ CPU์์ ํนํ ์ค์). | |
| ์ฒดํฌํฌ์ธํธ๋ PRS_DM์ ๋ฃ์ด ํ์ตํ ๋ชจ๋ธ(ML/checkpoints/dm_prs)์ด๋ค. prs_value | |
| (z ์ ์)๋ฅผ ์ฃผ๋ฉด PRS๋ฅผ mask=1๋ก ๋ฃ๊ณ PRS_DM๋ ํ๋์ SHAP feature๋ก ์ค๋ช ํ๋ค. | |
| None์ด๋ฉด PRS๋ฅผ [MASK]๋ก ๋๊ณ EHR feature๋ง ์ค๋ช ํ๋ค(ํ์ต ๋ --prs-dropout์ผ๋ก | |
| [MASK]๋ ํ์ต๋ผ ์์ด EHR๋ง์ผ๋ก ์์ธก ๊ฐ๋ฅ). | |
| """ | |
| from pathlib import Path | |
| import numpy as np | |
| import pandas as pd | |
| import shap | |
| import torch | |
| from models.mlp import MultimodalModel | |
| from utils.shap_utils import build_predict_fn | |
| def compute_dm_local_shap( | |
| patient_row: dict, | |
| features: list, | |
| background_df: pd.DataFrame, | |
| checkpoint_dir: str = "artifacts/checkpoints", | |
| n_folds: int = 5, | |
| prs_dim: int = 1, | |
| device: str = "cpu", | |
| top_k: int = 8, | |
| prs_value: float = None, | |
| prs_feature: str = "PRS_DM", | |
| exclude_features: tuple = (), | |
| ) -> tuple: | |
| """๋ฐํ: (importance_df(top_k, feature/patient_value/local_shap/direction), | |
| ensemble_predicted_prob). 5๊ฐ fold ์ฒดํฌํฌ์ธํธ ๊ฐ๊ฐ์ผ๋ก ์ด ํ ์ฌ๋์ local | |
| SHAP์ ๊ตฌํ๊ณ feature๋ณ ํ๊ท ์ ์ต์ข ๊ฐ์ผ๋ก ์ด๋ค(์์ธก ํ๋ฅ ๋ 5๊ฐ ๋ชจ๋ธ ํ๊ท ). | |
| exclude_features: ์์ธก์๋ ๊ทธ๋๋ก ์ฐ๋ ์ค๋ช ํ์์๋ง ๋บ feature - ์ฌ์ฉ์๊ฐ | |
| ์ ๋ ฅํ์ง ์์ ์ธ๊ตฌ ์ค๊ฐ๊ฐ์ผ๋ก ์ฑ์ด ํญ๋ชฉ์ ์ค๊ฐ๊ฐ์ด SHAP ๋ฐฐ๊ฒฝ ํ๊ท ๊ณผ ๋ฌ๋ผ | |
| (์: ALT ์ค๊ฐ๊ฐ 19 vs ํ๊ท 22.7) ์ ๋ ฅํ์ง๋ ์์ ๊ฐ์ ๊ธฐ์ฌ๋๊ฐ ์๊ธฐ๋ฏ๋ก ๋บ๋ค.""" | |
| prs_in_input = prs_value is not None | |
| ehr_features = list(features) | |
| patient_row = dict(patient_row) | |
| if prs_in_input: | |
| features = ehr_features + [prs_feature] | |
| patient_row[prs_feature] = float(prs_value) | |
| patient_vec = np.array([[patient_row[f] for f in features]], dtype=np.float32) | |
| background = background_df[features].to_numpy(dtype=np.float32) | |
| shap_values_per_fold, probs = [], [] | |
| for fold_id in range(n_folds): | |
| checkpoint_path = Path(checkpoint_dir) / f"dm_fold{fold_id}.pt" | |
| model = MultimodalModel(ehr_dim=len(ehr_features), prs_dim=prs_dim).to(device) | |
| model.load_state_dict(torch.load(checkpoint_path, map_location=device)) | |
| model.eval() | |
| predict_fn = build_predict_fn( | |
| model, prs_dim=max(prs_dim, 1), device=device, apply_sigmoid=True, prs_in_input=prs_in_input | |
| ) | |
| explainer = shap.KernelExplainer(predict_fn, background) | |
| sv = np.asarray(explainer.shap_values(patient_vec)).reshape(1, len(features)) | |
| shap_values_per_fold.append(sv[0]) | |
| probs.append(float(predict_fn(patient_vec)[0])) | |
| mean_shap = np.mean(shap_values_per_fold, axis=0) | |
| ensemble_prob = float(np.mean(probs)) | |
| df = pd.DataFrame( | |
| {"feature": features, "patient_value": [patient_row[f] for f in features], "local_shap": mean_shap} | |
| ) | |
| df = df[~df["feature"].isin(exclude_features)] | |
| df = df.assign(_abs=df["local_shap"].abs()).sort_values("_abs", ascending=False).drop(columns="_abs") | |
| df = df.head(top_k).reset_index(drop=True) | |
| df["direction"] = df["local_shap"].apply(lambda x: "๋น๋จ๋ณ ์ํ ์ฆ๊ฐ" if x > 0 else "๋น๋จ๋ณ ์ํ ๊ฐ์") | |
| return df, ensemble_prob | |