import numpy as np from sklearn.ensemble import IsolationForest row_names = np.array( [ "baseline-01", "baseline-02", "baseline-03", "baseline-04", "baseline-05", "baseline-06", "spike-01", ] ) readings = np.array( [ [10.0, 200.0], [10.4, 198.0], [9.8, 202.0], [10.2, 201.0], [10.1, 199.0], [10.5, 203.0], [42.0, 410.0], ] ) detector = IsolationForest(contamination=0.15, random_state=42) detector.fit(readings) labels = detector.predict(readings) scores = detector.decision_function(readings) print("Training rows") for row_name, label, score in zip(row_names, labels, scores): state = "outlier" if label == -1 else "inlier" print(f"{row_name:11s} {state:7s} label={label:2d} score={score: .3f}") outliers = row_names[labels == -1] print(f"Detected training outliers: {', '.join(outliers)}") new_rows = np.array( [ [10.3, 200.5], [35.0, 390.0], ] ) new_names = np.array(["incoming-normal", "incoming-spike"]) new_labels = detector.predict(new_rows) new_scores = detector.decision_function(new_rows) print("\nNew rows") for row_name, label, score in zip(new_names, new_labels, new_scores): state = "outlier" if label == -1 else "inlier" print(f"{row_name:15s} {state:7s} label={label:2d} score={score: .3f}") assert "spike-01" in outliers assert "incoming-spike" in new_names[new_labels == -1] print("\nSmoke check passed: expected spike rows are outliers")