# Source: content/notes/ml/unsupervised-learning.md
# Independent CPU example; use the curriculum environment.
# See /notes/ml/#example-environment or /notes/deep-learning/#example-environment.

import numpy as np
from sklearn.ensemble import IsolationForest
from sklearn.metrics import average_precision_score, roc_auc_score
from sklearn.neighbors import KernelDensity, LocalOutlierFactor
from sklearn.svm import OneClassSVM
from sklearn.covariance import EllipticEnvelope

rng = np.random.default_rng(77)
train = rng.normal(size=(240, 2))
normal = rng.normal(size=(100, 2))
anomaly = rng.uniform(5, 7, size=(25, 2))
test = np.vstack([normal, anomaly])
y = np.r_[np.zeros(len(normal)), np.ones(len(anomaly))]
models = {
    "Isolation Forest": IsolationForest(n_estimators=80, contamination=0.05, random_state=77),
    "LOF novelty": LocalOutlierFactor(n_neighbors=20, novelty=True, contamination=0.05),
    "one-class SVM": OneClassSVM(nu=0.05, gamma="scale"),
    "elliptic envelope": EllipticEnvelope(contamination=0.05, random_state=77),
}
for name, model in models.items():
    model.fit(train)
    score = -model.decision_function(test)
    alerts = model.predict(test) == -1
    assert np.isfinite(score).all() and alerts.shape == y.shape
    print(name, "AUC", roc_auc_score(y, score),
          "AP", average_precision_score(y, score), "alerts", alerts.sum())
kde = KernelDensity(kernel="gaussian", bandwidth=0.5).fit(train)
density_score = kde.score_samples(test)
assert np.isfinite(density_score).all()
print("KDE anomaly AUC:", roc_auc_score(y, -density_score))
