# Python ML/AI Code Examples

Reference examples for each rule area. Read the relevant section when generating code for that area.

---

## Reproducibility

```python
# ✅ Good — set all seeds at entrypoint
import random, numpy as np, torch

def set_seed(seed: int) -> None:
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.use_deterministic_algorithms(True)
```

---

## Config Management

```python
# ✅ Good — load config from file
from dataclasses import dataclass
import yaml

@dataclass
class TrainConfig:
    lr: float
    max_epochs: int
    batch_size: int
    seed: int

def load_config(path: str) -> TrainConfig:
    with open(path) as f:
        return TrainConfig(**yaml.safe_load(f))

# ❌ Bad — hyperparameters hardcoded in training script
lr = 0.001
epochs = 50
```

---

## Leakage Prevention

```python
# ✅ Good — pipeline inside CV; transforms fit on train fold only
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score

pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("clf", LogisticRegression()),
])
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(pipe, X_train, y_train, cv=cv, scoring="roc_auc")

# ❌ Bad — scaler fit on full data before split (leakage)
scaler = StandardScaler().fit(X)
X_scaled = scaler.transform(X)
X_train, X_test = train_test_split(X_scaled, ...)
```

---

## Framework Idioms

### scikit-learn

```python
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.pipeline import Pipeline

preprocessor = ColumnTransformer([
    ("num", StandardScaler(), num_cols),
    ("cat", OneHotEncoder(handle_unknown="ignore"), cat_cols),
])
pipe = Pipeline([("prep", preprocessor), ("model", clf)])
```

### PyTorch

```python
import torch
from torch.utils.data import DataLoader

def seed_worker(worker_id: int) -> None:
    import random, numpy as np
    worker_seed = torch.initial_seed() % (2**32)
    random.seed(worker_seed)
    np.random.seed(worker_seed)

g = torch.Generator()
g.manual_seed(42)
loader = DataLoader(dataset, batch_size=32, worker_init_fn=seed_worker, generator=g)

# Training loop
model.train()
for batch in train_loader:
    ...

# Validation loop
model.eval()
with torch.no_grad():
    for batch in val_loader:
        ...
```

### TensorFlow / Keras

```python
import tensorflow as tf

tf.random.set_seed(42)

callbacks = [
    tf.keras.callbacks.ModelCheckpoint(
        filepath="models/best.keras",
        monitor="val_loss",
        save_best_only=True,
    ),
    tf.keras.callbacks.EarlyStopping(
        monitor="val_loss",
        patience=5,
        restore_best_weights=True,
    ),
]
model.fit(X_train, y_train, validation_data=(X_val, y_val), callbacks=callbacks)
```

### HuggingFace (LLM fine-tuning)

```python
from transformers import Trainer, TrainingArguments

args = TrainingArguments(
    output_dir="models/ft-run",
    num_train_epochs=3,
    learning_rate=2e-5,
    warmup_ratio=0.1,
    seed=42,
    report_to="mlflow",
)
trainer = Trainer(model=model, args=args, train_dataset=train_ds, eval_dataset=val_ds)
trainer.train()
```

---

## Experiment Tracking

```python
import mlflow

mlflow.set_experiment("my-project")
with mlflow.start_run(run_name="ML-42_lgbm-tfidf_20241115-1"):
    mlflow.log_params({"lr": cfg.lr, "seed": cfg.seed, "data_version": "v1.2"})
    mlflow.log_metric("val_roc_auc", val_score)
    mlflow.sklearn.log_model(pipe, artifact_path="model")
```

---

## Testing

```python
import pytest
import numpy as np
from src.eval.metrics import binary_roc_auc
from src.data.splits import make_temporal_split

def test_roc_auc_perfect_classifier():
    y_true = np.array([0, 0, 1, 1])
    y_score = np.array([0.1, 0.2, 0.8, 0.9])
    assert binary_roc_auc(y_true, y_score) == pytest.approx(1.0)

def test_temporal_split_no_leakage():
    train_ids, test_ids = make_temporal_split(df, date_col="event_date", test_months=3)
    overlap = set(train_ids) & set(test_ids)
    assert len(overlap) == 0, f"Leakage: {len(overlap)} overlapping IDs"
```
