NoWon1's picture
Upload folder using huggingface_hub (part 16)
54bb6a3 verified
Raw History Blame
2.38 kB
"""Baseline fixed-horizon risk classifier."""
from __future__ import annotations
from dataclasses import dataclass
import numpy as np
import pandas as pd
try:
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
except ImportError: # pragma: no cover
SimpleImputer = LogisticRegression = Pipeline = StandardScaler = None
@dataclass
class RiskClassifier:
feature_columns: list[str]
def __post_init__(self) -> None:
self.pipeline = None
if Pipeline is not None:
self.pipeline = Pipeline(
steps=[
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
("model", LogisticRegression(max_iter=1000, class_weight="balanced")),
]
)
def fit(self, frame: pd.DataFrame, target_col: str = "event") -> "RiskClassifier":
if self.pipeline is not None:
self.pipeline.fit(frame[self.feature_columns], frame[target_col])
return self
x = frame[self.feature_columns].astype(float)
y = frame[target_col].astype(int)
self.medians_ = x.median()
x = x.fillna(self.medians_)
self.means_ = x.mean()
self.stds_ = x.std(ddof=0).replace(0, 1.0)
z = (x - self.means_) / self.stds_
pos = z[y == 1].mean()
neg = z[y == 0].mean()
self.direction_ = (pos - neg).fillna(0.0)
self.intercept_ = -float((pos + neg).fillna(0.0).dot(self.direction_) / 2.0)
return self
def predict_risk(self, frame: pd.DataFrame) -> pd.Series:
if self.pipeline is not None:
probabilities = self.pipeline.predict_proba(frame[self.feature_columns])[:, 1]
return pd.Series(probabilities, index=frame.index, name="risk")
if not hasattr(self, "direction_"):
raise RuntimeError("RiskClassifier must be fitted before predict_risk")
x = frame[self.feature_columns].astype(float).fillna(self.medians_)
z = (x - self.means_) / self.stds_
logits = z.dot(self.direction_) + self.intercept_
probabilities = 1.0 / (1.0 + np.exp(-logits))
return pd.Series(probabilities, index=frame.index, name="risk")