pni-detect-v2 / train_classifiers.py
Prajwaldange's picture
Docker-based Gradio app with Phikon-v2 (bookworm, no apt-get)
05fd28b verified
"""One-time script to train and pickle the nerve/PNI classifiers.
Run locally before deploying to HuggingFace Spaces:
python train_classifiers.py
"""
import numpy as np
import joblib
from pathlib import Path
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
def main():
features_path = Path(__file__).parent / "features.npz"
out_dir = Path(__file__).parent / "classifiers"
out_dir.mkdir(exist_ok=True)
print("Loading features...")
data = np.load(features_path, allow_pickle=True)
features = data["features"]
labels_nerve = data["labels_nerve"]
labels_pni = data["labels_pni"]
# --- Nerve detector ---
print(f"Training nerve detector on {len(features)} patches...")
nerve_clf = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(
C=1.0, max_iter=2000, class_weight="balanced",
solver="lbfgs", random_state=42,
)),
])
nerve_clf.fit(features, labels_nerve)
nerve_path = out_dir / "nerve_clf.pkl"
joblib.dump(nerve_clf, nerve_path)
print(f" Saved: {nerve_path} ({nerve_path.stat().st_size / 1024:.1f} KB)")
# --- PNI classifier (nerve patches only) ---
pni_mask = labels_pni != -1
print(f"Training PNI classifier on {pni_mask.sum()} nerve patches...")
pni_clf = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(
C=1.0, max_iter=2000, class_weight="balanced",
solver="lbfgs", random_state=42,
)),
])
pni_clf.fit(features[pni_mask], labels_pni[pni_mask])
pni_path = out_dir / "pni_clf.pkl"
joblib.dump(pni_clf, pni_path)
print(f" Saved: {pni_path} ({pni_path.stat().st_size / 1024:.1f} KB)")
print("\nDone! Classifiers ready for deployment.")
if __name__ == "__main__":
main()