data-analysis
Patterns for data loading, exploration, and statistical analysis
Enforces baseline comparisons, cross-validation, interpretation, and leakage prevention for ML pipelines
$ npx -y skills add Yeachan-Heo/My-Jogyo --skill ml-rigor --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/ml-rigorContext preview
The summary Claude sees to decide when to auto-load this skill.
Enforces baseline comparisons, cross-validation, interpretation, and leakage prevention for ML pipelines
name: ml-rigor description: Enforces baseline comparisons, cross-validation, interpretation, and leakage prevention for ML pipelines
Load this skill when building machine learning models. Every ML pipeline must demonstrate:
**Quality Gate**: ML findings without baseline comparison or cross-validation are marked as "Exploratory" in reports.
---
**Every model must be compared to baselines.** A model that can't beat a dummy classifier isn't learning anything useful.
1. **DummyClassifier/DummyRegressor** - The absolute minimum bar 2. **Simple linear model** - LogisticRegression or LinearRegression 3. **Domain heuristic** (if available) - Rule-based approach
from sklearn.dummy import DummyClassifier, DummyRegressor
from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.model_selection import cross_val_score
import numpy as np
print("[DECISION] Establishing baselines before training complex models")
# Classification baselines
dummy_clf = DummyClassifier(strategy='most_frequent')
dummy_scores = cross_val_score(dummy_clf, X_train, y_train, cv=5, scoring='accuracy')
print(f"[METRIC:baseline_accuracy] {dummy_scores.mean():.3f} (majority class)")
print(f"[METRIC:baseline_accuracy_std] {dummy_scores.std():.3f}")
# Simple linear baseline
lr = LogisticRegression(max_iter=1000, random_state=42)
lr_scores = cross_val_score(lr, X_train, y_train, cv=5, scoring='accuracy')
print(f"[METRIC:linear_baseline_accuracy] {lr_scores.mean():.3f}")
print(f"[METRIC:linear_baseline_accuracy_std] {lr_scores.std():.3f}")
# For regression tasks
dummy_reg = DummyRegressor(strategy='mean')
dummy_rmse = cross_val_score(dummy_reg, X_train, y_train, cv=5,
scoring='neg_root_mean_squared_error')
print(f"[METRIC:baseline_rmse] {-dummy_rmse.mean():.3f} (mean predictor)")from scipy import stats
# Calculate improvement with confidence interval
model_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
improvement = model_scores.mean() - dummy_scores.mean()
# Bootstrap CI for improvement
n_bootstrap = 1000
improvements = []
for _ in range(n_bootstrap):
idx = np.random.choice(len(model_scores), len(model_scores), replace=True)
boot_improvement = model_scores[idx].mean() - dummy_scores[idx].mean()
improvements.append(boot_improvement)
ci_low, ci_high = np.percentile(improvements, [2.5, 97.5])
print(f"[METRIC:improvement_over_baseline] {improvement:.3f}")
print(f"[STAT:ci] 95% CI [{ci_low:.3f}, {ci_high:.3f}]")
print(f"[STAT:effect_size] Relative improvement: {improvement/dummy_scores.mean()*100:.1f}%")
if ci_low > 0:
print("[FINDING] Model significantly outperforms baseline")
else:
print("[LIMITATION] Improvement over baseline not statistically significant")---
**Never report a single train/test split.** Cross-validation shows how much your score varies.
from sklearn.model_selection import (
StratifiedKFold, cross_val_score, cross_validate,
RepeatedStratifiedKFold
)
import numpy as np
from scipy import stats
print("[DECISION] Using 5-fold stratified CV to estimate model performance")
# Stratified K-Fold for classification
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Multiple metrics
scoring = ['accuracy', 'f1_weighted', 'roc_auc']
cv_results = cross_validate(model, X, y, cv=cv, scoring=scoring,
return_train_score=True)
# Report mean +/- std (REQUIRED)
for metric in scoring:
test_scores = cv_results[f'test_{metric}']
train_scores = cv_results[f'train_{metric}']
print(f"[METRIC:cv_{metric}_mean] {test_scores.mean():.3f}")
print(f"[METRIC:cv_{metric}_std] {test_scores.std():.3f}")
# Check for overfitting
gap = train_scores.mean() - test_scores.mean()
if gap > 0.1:
print(f"[LIMITATION] Train-test gap of {gap:.3f} suggests overfitting")# CI for cross-validation mean (t-distribution for small n)
def cv_confidence_interval(scores, confidence=0.95):
n = len(scores)
mean = scores.mean()
se = stats.sem(scores)
h = se * stats.t.ppf((1 + confidence) / 2, n - 1)
return mean - h, mean + h
ci_low, ci_high = cv_confidence_interval(cv_results['test_accuracy'])
print(f"[STAT:ci] 95% CI for accuracy: [{ci_low:.3f}, {ci_high:.3f}]")
# For small datasets, use repeated CV
print("[DECISION] Using repeated CV for more stable estimates")
rcv = RepeatedStratifiedKFold(n_splits=5, n_repeats=10, random_state=42)
scores = cross_val_score(model, X, y, cv=rcv, scoring='accuracy')
print(f"[METRIC:repeated_cv_mean] {scores.mean():.3f}")
print(f"[METRIC:repeated_cv_std] {scores.std():.3f}")---
**Avoid overfitting to the validation set.** Report the distribution of scores, not just the best.
from sklearn.model_selection import RandomizedSearchCV, cross_val_score from scipy.stat
"Every great professor needs a great teaching assistant." Gyoshu (교수, Professor) orchestrates. Jogyo (조교, Teaching Assistant) executes.
Patterns for data loading, exploration, and statistical analysis