.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples\anomaly_detection\PADI_dnn.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_anomaly_detection_PADI_dnn.py: Post-Anomaly Detection Inference for Deep SVDD (Tabular Data) ============================================================= This example shows how to perform selective inference for Deep Support Vector Data Description (Deep SVDD) on tabular data using the `pythonsi` library. The method computes statistically valid p-values to control the False Positive Rate (FPR) in a post-hoc manner. The implementation is based on the work by Thanh et al. (2026) [1]. [1] Thanh, C. L. C., Vinh, D. Q., & Duy, V. N. L. (2026). Post-Anomaly Detection Inference for Deep SVDD. arXiv preprint arXiv:2609.37935. .. GENERATED FROM PYTHON SOURCE LINES 8-31 .. code-block:: Python import sys import os from pathlib import Path # Add pythonsi to module search path # REPO = Path(__file__).resolve().parent # while REPO.name and not (REPO / "pythonsi").exists(): # REPO = REPO.parent # sys.path.insert(0, str(REPO)) import numpy as np import torch import matplotlib.pyplot as plt from pythonsi import Data, Pipeline from pythonsi.anomaly_detection import DeepSVDDAD from pythonsi.test_statistics import DeepSVDDTestStatistic # Add dnn directory to path to import network # sys.path.insert(0, str(Path(__file__).resolve().parent / "deepsvdd" / "dnn")) from models.deepsvdd.dnn.network import MLP .. GENERATED FROM PYTHON SOURCE LINES 32-34 Configuration ------------- .. GENERATED FROM PYTHON SOURCE LINES 34-42 .. code-block:: Python SEED = 42 N_FEATURES = 50 N_REFS = 20 ALPHA = 0.05 DEVICE = "cuda" if torch.cuda.is_available() else "cpu" .. GENERATED FROM PYTHON SOURCE LINES 43-46 Load Trained Model ------------------ script_dir = Path(__file__).resolve().parent .. GENERATED FROM PYTHON SOURCE LINES 46-62 .. code-block:: Python ckpt_path = "./models/deepsvdd/dnn/weights/mlp_encoder.pth" ckpt = torch.load(ckpt_path, map_location=DEVICE, weights_only=False) cfg = ckpt["config"] model = MLP( n_features=cfg["n_features"], hidden_dim=cfg["hidden_dim"], repdim=cfg["repdim"], ).to(DEVICE) model.load_state_dict(ckpt["model_state_dict"]) model.eval() center_c = ckpt["center_c"] R_squared = ckpt["R_squared"] * 0.7 print(f"R² = {R_squared:.10f}") .. rst-class:: sphx-glr-script-out .. code-block:: none R² = 0.2253899843 .. GENERATED FROM PYTHON SOURCE LINES 63-65 Generate Test & Reference Data ------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 65-83 .. code-block:: Python rng = np.random.default_rng(SEED) # Reference data: normal N(0,1) X_refs = rng.normal(size=(N_REFS, N_FEATURES)).astype(np.float64) # Test data: anomalous (shifted mean) X_test = rng.normal(size=(1, N_FEATURES)).astype(np.float64) # Check if test triggers anomaly with torch.no_grad(): feat = model(torch.from_numpy(X_test).float().to(DEVICE)) score = torch.sum((feat - torch.tensor(center_c, device=DEVICE)) ** 2).item() print(f"Score: {score:.10f}") print(f"R²: {R_squared:.10f}") print(f"Anomaly detected: {score > R_squared}") .. rst-class:: sphx-glr-script-out .. code-block:: none Score: 0.2512427866 R²: 0.2253899843 Anomaly detected: True .. GENERATED FROM PYTHON SOURCE LINES 84-86 Build Pipeline & Compute Selective p-value ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 86-118 .. code-block:: Python test_node = Data() refs_node = Data() detector = DeepSVDDAD( model=model, R_squared=R_squared, center=center_c, device="cpu", network_type="dnn", ) anomaly_node = detector.run(test_node) pipeline = Pipeline( inputs=(test_node, refs_node), output=anomaly_node, test_statistic=DeepSVDDTestStatistic(test_node, refs_node), ) print("Running selective inference …") anomalies, p_values = pipeline( inputs=[X_test, X_refs], covariances=[np.eye(N_FEATURES)], verbose=False, ) print(f"\nDetected anomalies: {anomalies}") print(f"Selective p-values: {p_values}") if len(p_values) > 0 and p_values[0] is not None: print(f"Reject H₀ at α={ALPHA}? {'YES' if p_values[0] < ALPHA else 'NO'}") .. rst-class:: sphx-glr-script-out .. code-block:: none Running selective inference … Detected anomalies: [0] Selective p-values: [0.46534214671927887] Reject H₀ at α=0.05? NO .. GENERATED FROM PYTHON SOURCE LINES 119-121 Plot the p-values ----------------- .. GENERATED FROM PYTHON SOURCE LINES 121-132 .. code-block:: Python plt.figure(figsize=(8, 5)) plt.bar([str(anomaly) for anomaly in anomalies], p_values, color='skyblue') plt.axhline(y=ALPHA, color='red', linestyle='--', label=f'Alpha ({ALPHA})') plt.xlabel("Anomalies Index") plt.ylabel("Selective P-value") plt.title("Selective P-values for Detected Anomalies") plt.legend() plt.tight_layout() plt.show() .. image-sg:: /auto_examples/anomaly_detection/images/sphx_glr_PADI_dnn_001.png :alt: Selective P-values for Detected Anomalies :srcset: /auto_examples/anomaly_detection/images/sphx_glr_PADI_dnn_001.png :class: sphx-glr-single-img .. _sphx_glr_download_auto_examples_anomaly_detection_PADI_dnn.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: PADI_dnn.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: PADI_dnn.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: PADI_dnn.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_