pyod 3.5.2__tar.gz → 3.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. {pyod-3.5.2/pyod.egg-info → pyod-3.6.0}/PKG-INFO +12 -7
  2. {pyod-3.5.2 → pyod-3.6.0}/README.rst +5 -5
  3. {pyod-3.5.2 → pyod-3.6.0}/pyod/cli.py +8 -2
  4. pyod-3.6.0/pyod/models/audio_ae.py +235 -0
  5. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/embedding.py +49 -0
  6. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/SKILL.md +123 -123
  7. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/graph.md +2 -2
  8. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/tabular.md +3 -4
  9. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/text_image.md +2 -3
  10. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/time_series.md +1 -1
  11. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/workflow.md +237 -237
  12. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/_detector_factory.py +2 -0
  13. pyod-3.6.0/pyod/utils/_llm.py +267 -0
  14. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/_quality_metrics.py +505 -500
  15. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/ad_engine.py +354 -8
  16. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/encoders/__init__.py +6 -0
  17. pyod-3.6.0/pyod/utils/encoders/audio.py +175 -0
  18. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/knowledge/algorithms.json +30 -3
  19. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/knowledge/routing_rules.json +12 -0
  20. {pyod-3.5.2 → pyod-3.6.0}/pyod/version.py +23 -23
  21. {pyod-3.5.2 → pyod-3.6.0/pyod.egg-info}/PKG-INFO +12 -7
  22. {pyod-3.5.2 → pyod-3.6.0}/pyod.egg-info/SOURCES.txt +3 -0
  23. {pyod-3.5.2 → pyod-3.6.0}/pyod.egg-info/requires.txt +6 -0
  24. {pyod-3.5.2 → pyod-3.6.0}/pyproject.toml +4 -1
  25. {pyod-3.5.2 → pyod-3.6.0}/LICENSE +0 -0
  26. {pyod-3.5.2 → pyod-3.6.0}/MANIFEST.in +0 -0
  27. {pyod-3.5.2 → pyod-3.6.0}/pyod/__init__.py +0 -0
  28. {pyod-3.5.2 → pyod-3.6.0}/pyod/mcp_server.py +0 -0
  29. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/__init__.py +0 -0
  30. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/_pyg_utils.py +0 -0
  31. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/_ts_utils.py +0 -0
  32. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/abod.py +0 -0
  33. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ae1svm.py +0 -0
  34. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/alad.py +0 -0
  35. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/anogan.py +0 -0
  36. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/auto_encoder.py +0 -0
  37. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/base.py +0 -0
  38. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/base_dl.py +0 -0
  39. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/cblof.py +0 -0
  40. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/cd.py +0 -0
  41. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/cof.py +0 -0
  42. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/combination.py +0 -0
  43. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/copod.py +0 -0
  44. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/deep_svdd.py +0 -0
  45. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/devnet.py +0 -0
  46. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/dif.py +0 -0
  47. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ecod.py +0 -0
  48. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/feature_bagging.py +0 -0
  49. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/gaal_base.py +0 -0
  50. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/gmm.py +0 -0
  51. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/hbos.py +0 -0
  52. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/hdbscan.py +0 -0
  53. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/iforest.py +0 -0
  54. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/inne.py +0 -0
  55. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/kde.py +0 -0
  56. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/knn.py +0 -0
  57. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/kpca.py +0 -0
  58. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/lmdd.py +0 -0
  59. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/loci.py +0 -0
  60. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/loda.py +0 -0
  61. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/lof.py +0 -0
  62. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/lscp.py +0 -0
  63. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/lunar.py +0 -0
  64. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/mad.py +0 -0
  65. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/mcd.py +0 -0
  66. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/mo_gaal.py +0 -0
  67. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ocsvm.py +0 -0
  68. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pca.py +0 -0
  69. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_anomalous.py +0 -0
  70. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_anomalydae.py +0 -0
  71. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_cola.py +0 -0
  72. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_conad.py +0 -0
  73. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_dominant.py +0 -0
  74. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_guide.py +0 -0
  75. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_radar.py +0 -0
  76. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/pyg_scan.py +0 -0
  77. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/qmcd.py +0 -0
  78. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/rgraph.py +0 -0
  79. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/rod.py +0 -0
  80. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/sampling.py +0 -0
  81. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/sklearn_base.py +0 -0
  82. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/so_gaal.py +0 -0
  83. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/so_gaal_new.py +0 -0
  84. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/sod.py +0 -0
  85. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/sos.py +0 -0
  86. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/suod.py +0 -0
  87. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/thresholds.py +0 -0
  88. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_anomaly_transformer.py +0 -0
  89. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_kshape.py +0 -0
  90. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_lstm.py +0 -0
  91. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_matrix_profile.py +0 -0
  92. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_od.py +0 -0
  93. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_sand.py +0 -0
  94. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/ts_spectral_residual.py +0 -0
  95. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/vae.py +0 -0
  96. {pyod-3.5.2 → pyod-3.6.0}/pyod/models/xgbod.py +0 -0
  97. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/__init__.py +0 -0
  98. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/__init__.py +0 -0
  99. {pyod-3.5.2 → pyod-3.6.0}/pyod/skills/od_expert/references/pitfalls.md +0 -0
  100. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/__init__.py +0 -0
  101. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/_kb_router.py +0 -0
  102. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/_nl_feedback.py +0 -0
  103. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/auto_model_selector.py +0 -0
  104. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/data.py +0 -0
  105. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/encoders/huggingface.py +0 -0
  106. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/encoders/openai_encoder.py +0 -0
  107. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/encoders/sentence_transformer.py +0 -0
  108. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/example.py +0 -0
  109. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/investigation.py +0 -0
  110. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/knowledge/__init__.py +0 -0
  111. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/knowledge/benchmarks.json +0 -0
  112. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/knowledge/papers.json +0 -0
  113. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/AE1SVM.json +0 -0
  114. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/ALAD.json +0 -0
  115. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/AnoGAN.json +0 -0
  116. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/AutoEncoder.json +0 -0
  117. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/Deep SVDD.json +0 -0
  118. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/DevNet.json +0 -0
  119. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/LUNAR.json +0 -0
  120. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/MO-GAAL.json +0 -0
  121. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/SO-GAAL.json +0 -0
  122. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/VAE.json +0 -0
  123. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/model_analysis_jsons/__init__.py +0 -0
  124. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/persistence.py +0 -0
  125. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/stat_models.py +0 -0
  126. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/torch_utility.py +0 -0
  127. {pyod-3.5.2 → pyod-3.6.0}/pyod/utils/utility.py +0 -0
  128. {pyod-3.5.2 → pyod-3.6.0}/pyod.egg-info/dependency_links.txt +0 -0
  129. {pyod-3.5.2 → pyod-3.6.0}/pyod.egg-info/entry_points.txt +0 -0
  130. {pyod-3.5.2 → pyod-3.6.0}/pyod.egg-info/top_level.txt +0 -0
  131. {pyod-3.5.2 → pyod-3.6.0}/requirements.txt +0 -0
  132. {pyod-3.5.2 → pyod-3.6.0}/setup.cfg +0 -0
  133. {pyod-3.5.2 → pyod-3.6.0}/setup.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyod
3
- Version: 3.5.2
4
- Summary: A Python library for anomaly detection across tabular, time series, graph, text, and image data. 60+ detectors, benchmark-backed ADEngine orchestration, and an agentic workflow for AI agents.
3
+ Version: 3.6.0
4
+ Summary: A Python library for anomaly detection across tabular, time series, graph, text, image, and audio data. 61 detectors, benchmark-backed ADEngine orchestration, and an agentic workflow for AI agents.
5
5
  Author-email: Yue Zhao <yzhao062@gmail.com>
6
6
  License-Expression: BSD-2-Clause
7
7
  Project-URL: Homepage, https://github.com/yzhao062/pyod
@@ -53,6 +53,9 @@ Requires-Dist: torch>=2.0; extra == "graph"
53
53
  Requires-Dist: torch_geometric>=2.0; extra == "graph"
54
54
  Provides-Extra: mcp
55
55
  Requires-Dist: mcp>=1.0; extra == "mcp"
56
+ Provides-Extra: audio
57
+ Requires-Dist: librosa>=0.10; extra == "audio"
58
+ Requires-Dist: soundfile; extra == "audio"
56
59
  Provides-Extra: all
57
60
  Requires-Dist: torch>=2.0; extra == "all"
58
61
  Requires-Dist: suod; extra == "all"
@@ -65,6 +68,8 @@ Requires-Dist: transformers>=4.25.1; extra == "all"
65
68
  Requires-Dist: torch_geometric>=2.0; extra == "all"
66
69
  Requires-Dist: Pillow; extra == "all"
67
70
  Requires-Dist: mcp>=1.0; extra == "all"
71
+ Requires-Dist: librosa>=0.10; extra == "all"
72
+ Requires-Dist: soundfile; extra == "all"
68
73
  Dynamic: license-file
69
74
 
70
75
  Python Outlier Detection (PyOD) 3
@@ -131,7 +136,7 @@ PyOD 3 is the most comprehensive Python library for anomaly detection. Four pill
131
136
  =========================== ========================================================================================
132
137
  Pillar What it means
133
138
  =========================== ========================================================================================
134
- Multi-Modal 60+ detectors across **tabular, time series, graph, text, and image** data, one API
139
+ Multi-Modal 61 detectors across **tabular, time series, graph, text, image, and audio** data, one API
135
140
  Full Lifecycle From raw data to explained anomalies and next-step guidance in a single call
136
141
  Agentic ``od-expert`` turns natural-language requests into ADEngine workflows; MCP exposes structured tools for other agents
137
142
  Most Used 38+ million downloads; benchmark-backed routing (ADBench, TSB-AD, BOND, NLP-ADBench)
@@ -191,7 +196,7 @@ Layer Name When to use
191
196
  3 Agentic Investigation You want an AI agent to drive OD through natural conversation `Layer 3 walkthrough <https://pyod.readthedocs.io/en/latest/examples/agentic.html>`__
192
197
  ========= ===================== ====================================================================== =======================================
193
198
 
194
- Layers 2 and 3 are powered by ``ADEngine``, PyOD's intelligent orchestration core. The full multi-turn Layer 3 investigation flow is available through the ``od-expert`` skill for Claude Code and Codex. The MCP server (``python -m pyod.mcp_server``) exposes ten stateless tools for MCP-compatible LLMs, spanning knowledge queries (``list_detectors``, ``explain_detector``, ``compare_detectors``, ``get_benchmarks``), planning (``profile_data``, ``plan_detection``, ``build_detector``), and detection (``run_detection``, ``analyze_results``, ``explain_findings``); stateful ``investigate`` / ``iterate`` MCP tools are deferred.
199
+ Layers 2 and 3 are powered by ``ADEngine``, PyOD's lifecycle orchestration core. The full multi-turn Layer 3 investigation flow is available through the ``od-expert`` skill for Claude Code and Codex. The MCP server (``python -m pyod.mcp_server``) exposes ten stateless tools for MCP-compatible LLMs, spanning knowledge queries (``list_detectors``, ``explain_detector``, ``compare_detectors``, ``get_benchmarks``), planning (``profile_data``, ``plan_detection``, ``build_detector``), and detection (``run_detection``, ``analyze_results``, ``explain_findings``); stateful ``investigate`` / ``iterate`` MCP tools are deferred.
195
200
 
196
201
  .. image:: https://raw.githubusercontent.com/yzhao062/pyod/development/docs/figs/agentic-demo.png
197
202
  :alt: PyOD 3 agentic investigation demo on cardiotocography dataset
@@ -211,7 +216,7 @@ About PyOD
211
216
 
212
217
  PyOD, established in 2017, is the longest-running and most widely used Python library for anomaly detection. With `38+ million downloads <https://pepy.tech/project/pyod>`__, it serves both academic research (featured in `Analytics Vidhya <https://www.analyticsvidhya.com/blog/2019/02/outlier-detection-python-pyod/>`__, `KDnuggets <https://www.kdnuggets.com/2019/02/outlier-detection-methods-cheat-sheet.html>`__, and `Towards Data Science <https://towardsdatascience.com/anomaly-detection-for-dummies-15f148e559c1>`__) and commercial products.
213
218
 
214
- V3 extends the library with ``ADEngine`` (intelligent orchestration) and the ``od-expert`` skill (agentic workflow), while keeping the classic ``fit``/``predict`` API fully backward-compatible. V3 is built on SUOD [#Zhao2021SUOD]_ for fast parallel training and numba JIT for per-model speedups.
219
+ V3 extends the library with ``ADEngine`` (lifecycle orchestration) and the ``od-expert`` skill (agentic workflow), while keeping the classic ``fit``/``predict`` API fully backward-compatible. V3 is built on SUOD [#Zhao2021SUOD]_ for fast parallel training and numba JIT for per-model speedups.
215
220
 
216
221
  **Impact & Recognition**:
217
222
 
@@ -322,7 +327,7 @@ Additional Topics
322
327
  Implemented Algorithms
323
328
  ^^^^^^^^^^^^^^^^^^^^^^
324
329
 
325
- PyOD is organized into two functional groups: **(i) Detection Algorithms**, with dedicated subsections for tabular, time series, and graph data (EmbeddingOD inside the tabular table adds multi-modal support for text and image via foundation model encoders); and **(ii) Utility Functions** for data generation, evaluation, and intelligent orchestration.
330
+ PyOD is organized into two functional groups: **(i) Detection Algorithms**, with dedicated subsections for tabular, time series, and graph data (EmbeddingOD inside the tabular table adds multi-modal support for text, image, and audio via foundation model or handcrafted encoders); and **(ii) Utility Functions** for data generation, evaluation, and lifecycle orchestration.
326
331
 
327
332
  **(i-a) Tabular & Multi-Modal Detection Algorithms** :
328
333
 
@@ -577,7 +582,7 @@ PyOD is organized into two functional groups: **(i) Detection Algorithms**, with
577
582
  - [#Goodge2022Lunar]_
578
583
  * - Embedding-based
579
584
  - EmbeddingOD
580
- - Multi-modal anomaly detection via foundation model embeddings, text and image (`example <https://github.com/yzhao062/pyod/blob/development/examples/embedding_od_example.py>`__)
585
+ - Multi-modal anomaly detection via foundation model embeddings, text, image, and audio (`example <https://github.com/yzhao062/pyod/blob/development/examples/embedding_od_example.py>`__)
581
586
  - 2025
582
587
  - [#Li2024NLPADBench]_
583
588
 
@@ -62,7 +62,7 @@ PyOD 3 is the most comprehensive Python library for anomaly detection. Four pill
62
62
  =========================== ========================================================================================
63
63
  Pillar What it means
64
64
  =========================== ========================================================================================
65
- Multi-Modal 60+ detectors across **tabular, time series, graph, text, and image** data, one API
65
+ Multi-Modal 61 detectors across **tabular, time series, graph, text, image, and audio** data, one API
66
66
  Full Lifecycle From raw data to explained anomalies and next-step guidance in a single call
67
67
  Agentic ``od-expert`` turns natural-language requests into ADEngine workflows; MCP exposes structured tools for other agents
68
68
  Most Used 38+ million downloads; benchmark-backed routing (ADBench, TSB-AD, BOND, NLP-ADBench)
@@ -122,7 +122,7 @@ Layer Name When to use
122
122
  3 Agentic Investigation You want an AI agent to drive OD through natural conversation `Layer 3 walkthrough <https://pyod.readthedocs.io/en/latest/examples/agentic.html>`__
123
123
  ========= ===================== ====================================================================== =======================================
124
124
 
125
- Layers 2 and 3 are powered by ``ADEngine``, PyOD's intelligent orchestration core. The full multi-turn Layer 3 investigation flow is available through the ``od-expert`` skill for Claude Code and Codex. The MCP server (``python -m pyod.mcp_server``) exposes ten stateless tools for MCP-compatible LLMs, spanning knowledge queries (``list_detectors``, ``explain_detector``, ``compare_detectors``, ``get_benchmarks``), planning (``profile_data``, ``plan_detection``, ``build_detector``), and detection (``run_detection``, ``analyze_results``, ``explain_findings``); stateful ``investigate`` / ``iterate`` MCP tools are deferred.
125
+ Layers 2 and 3 are powered by ``ADEngine``, PyOD's lifecycle orchestration core. The full multi-turn Layer 3 investigation flow is available through the ``od-expert`` skill for Claude Code and Codex. The MCP server (``python -m pyod.mcp_server``) exposes ten stateless tools for MCP-compatible LLMs, spanning knowledge queries (``list_detectors``, ``explain_detector``, ``compare_detectors``, ``get_benchmarks``), planning (``profile_data``, ``plan_detection``, ``build_detector``), and detection (``run_detection``, ``analyze_results``, ``explain_findings``); stateful ``investigate`` / ``iterate`` MCP tools are deferred.
126
126
 
127
127
  .. image:: https://raw.githubusercontent.com/yzhao062/pyod/development/docs/figs/agentic-demo.png
128
128
  :alt: PyOD 3 agentic investigation demo on cardiotocography dataset
@@ -142,7 +142,7 @@ About PyOD
142
142
 
143
143
  PyOD, established in 2017, is the longest-running and most widely used Python library for anomaly detection. With `38+ million downloads <https://pepy.tech/project/pyod>`__, it serves both academic research (featured in `Analytics Vidhya <https://www.analyticsvidhya.com/blog/2019/02/outlier-detection-python-pyod/>`__, `KDnuggets <https://www.kdnuggets.com/2019/02/outlier-detection-methods-cheat-sheet.html>`__, and `Towards Data Science <https://towardsdatascience.com/anomaly-detection-for-dummies-15f148e559c1>`__) and commercial products.
144
144
 
145
- V3 extends the library with ``ADEngine`` (intelligent orchestration) and the ``od-expert`` skill (agentic workflow), while keeping the classic ``fit``/``predict`` API fully backward-compatible. V3 is built on SUOD [#Zhao2021SUOD]_ for fast parallel training and numba JIT for per-model speedups.
145
+ V3 extends the library with ``ADEngine`` (lifecycle orchestration) and the ``od-expert`` skill (agentic workflow), while keeping the classic ``fit``/``predict`` API fully backward-compatible. V3 is built on SUOD [#Zhao2021SUOD]_ for fast parallel training and numba JIT for per-model speedups.
146
146
 
147
147
  **Impact & Recognition**:
148
148
 
@@ -253,7 +253,7 @@ Additional Topics
253
253
  Implemented Algorithms
254
254
  ^^^^^^^^^^^^^^^^^^^^^^
255
255
 
256
- PyOD is organized into two functional groups: **(i) Detection Algorithms**, with dedicated subsections for tabular, time series, and graph data (EmbeddingOD inside the tabular table adds multi-modal support for text and image via foundation model encoders); and **(ii) Utility Functions** for data generation, evaluation, and intelligent orchestration.
256
+ PyOD is organized into two functional groups: **(i) Detection Algorithms**, with dedicated subsections for tabular, time series, and graph data (EmbeddingOD inside the tabular table adds multi-modal support for text, image, and audio via foundation model or handcrafted encoders); and **(ii) Utility Functions** for data generation, evaluation, and lifecycle orchestration.
257
257
 
258
258
  **(i-a) Tabular & Multi-Modal Detection Algorithms** :
259
259
 
@@ -508,7 +508,7 @@ PyOD is organized into two functional groups: **(i) Detection Algorithms**, with
508
508
  - [#Goodge2022Lunar]_
509
509
  * - Embedding-based
510
510
  - EmbeddingOD
511
- - Multi-modal anomaly detection via foundation model embeddings, text and image (`example <https://github.com/yzhao062/pyod/blob/development/examples/embedding_od_example.py>`__)
511
+ - Multi-modal anomaly detection via foundation model embeddings, text, image, and audio (`example <https://github.com/yzhao062/pyod/blob/development/examples/embedding_od_example.py>`__)
512
512
  - 2025
513
513
  - [#Li2024NLPADBench]_
514
514
 
@@ -46,10 +46,16 @@ def _cmd_info(args: argparse.Namespace) -> int:
46
46
  from pyod.utils.ad_engine import ADEngine
47
47
  engine = ADEngine()
48
48
  counts: Counter = Counter()
49
- for algo in engine.kb.algorithms.values():
49
+ # Count only buildable detectors: a `planned` entry (e.g., LLMAD) has
50
+ # no backing module, so it must not inflate the reported total.
51
+ buildable = {
52
+ name: algo for name, algo in engine.kb.algorithms.items()
53
+ if algo.get("status") != "planned"
54
+ }
55
+ for algo in buildable.values():
50
56
  for dt in algo.get("data_types", []):
51
57
  counts[dt] += 1
52
- total = len(engine.kb.algorithms)
58
+ total = len(buildable)
53
59
  ad_ok = True
54
60
  except Exception:
55
61
  counts = Counter()
@@ -0,0 +1,235 @@
1
+ # -*- coding: utf-8 -*-
2
+ """AudioAE: a log-mel reconstruction autoencoder for audio anomaly detection.
3
+
4
+ Each clip is turned into overlapping log-mel context windows; a dense
5
+ autoencoder is fit on the windows of the (mostly normal) training clips,
6
+ and each clip is scored by its mean per-window reconstruction error. This
7
+ is the DCASE-style audio anomaly detection baseline, expressed through
8
+ PyOD's ``AutoEncoder`` so the training loop and preprocessing are shared
9
+ with the rest of the library.
10
+ """
11
+ # Author: Yue Zhao <yzhao062@gmail.com>
12
+ # License: BSD 2 clause
13
+
14
+ import numpy as np
15
+ from sklearn.utils.validation import check_is_fitted
16
+
17
+ from .base import BaseDetector
18
+ from ..utils.encoders.audio import _to_mono_waveform
19
+
20
+ _DEFAULT_SR = 22050
21
+
22
+
23
+ def _logmel_windows(y, sr, n_mels, context, hop_length):
24
+ """Return overlapping log-mel context windows for one waveform.
25
+
26
+ Output shape is ``(n_windows, n_mels * context)``. Clips shorter than
27
+ one context window are padded so at least one window is produced.
28
+ """
29
+ import librosa
30
+
31
+ spec = librosa.power_to_db(
32
+ librosa.feature.melspectrogram(
33
+ y=y, sr=sr, n_mels=n_mels, hop_length=hop_length))
34
+ n_frames = spec.shape[1]
35
+ if n_frames < context:
36
+ pad = np.zeros((n_mels, context - n_frames), dtype=spec.dtype)
37
+ spec = np.concatenate([spec, pad], axis=1)
38
+ n_frames = context
39
+ windows = [spec[:, t:t + context].T.reshape(-1)
40
+ for t in range(n_frames - context + 1)]
41
+ return np.stack(windows).astype(np.float32)
42
+
43
+
44
+ class AudioAE(BaseDetector):
45
+ """Log-mel reconstruction autoencoder for audio anomaly detection.
46
+
47
+ The detector extracts overlapping log-mel context windows from each
48
+ clip, fits a dense autoencoder (PyOD's :class:`AutoEncoder`) on the
49
+ windows of the training clips, and scores each clip by its mean
50
+ per-window reconstruction error. Training assumes the input is mostly
51
+ normal, the usual unsupervised setting.
52
+
53
+ Requires ``torch`` (for the autoencoder) and ``pyod[audio]``
54
+ (``librosa``, ``soundfile``).
55
+
56
+ Parameters
57
+ ----------
58
+ n_mels : int, optional (default=64)
59
+ Number of mel bands in the spectrogram.
60
+
61
+ context : int, optional (default=5)
62
+ Number of consecutive frames stacked into one autoencoder input
63
+ window. The window dimensionality is ``n_mels * context``.
64
+
65
+ hop_length : int, optional (default=512)
66
+ STFT hop length in samples.
67
+
68
+ sr : int, optional (default=22050)
69
+ Target sample rate. File inputs are loaded at this rate;
70
+ ``(waveform, sample_rate)`` tuples are resampled to it.
71
+
72
+ contamination : float, optional (default=0.1)
73
+ Expected proportion of outliers, used for the clip-level
74
+ threshold and labels.
75
+
76
+ epoch_num : int, optional (default=40)
77
+ Autoencoder training epochs.
78
+
79
+ batch_size : int, optional (default=1024)
80
+ Autoencoder mini-batch size (over frames, not clips).
81
+
82
+ lr : float, optional (default=1e-3)
83
+ Learning rate.
84
+
85
+ hidden_neuron_list : list of int or None, optional (default=None)
86
+ Encoder hidden sizes. ``None`` uses ``[128, 32, 8]``, which gives
87
+ the DCASE-style 320-128-32-8 contraction for the default
88
+ 320-dimensional window (``n_mels=64``, ``context=5``).
89
+
90
+ device : str or None, optional (default=None)
91
+ Torch device. ``None`` auto-selects.
92
+
93
+ random_state : int, optional (default=42)
94
+ Seed forwarded to the autoencoder.
95
+
96
+ verbose : int, optional (default=0)
97
+ Autoencoder verbosity.
98
+
99
+ Attributes
100
+ ----------
101
+ decision_scores_ : numpy array of shape (n_clips,)
102
+ Clip-level outlier scores of the training data.
103
+
104
+ threshold_ : float
105
+ Score threshold based on ``contamination``.
106
+
107
+ labels_ : numpy array of shape (n_clips,)
108
+ Binary labels of training clips (0: inlier, 1: outlier).
109
+
110
+ ae_ : AutoEncoder
111
+ The fitted frame-level autoencoder.
112
+
113
+ Examples
114
+ --------
115
+ >>> import numpy as np
116
+ >>> from pyod.models.audio_ae import AudioAE
117
+ >>> clips = [np.random.RandomState(s).randn(22050) for s in range(20)]
118
+ >>> clf = AudioAE(epoch_num=5)
119
+ >>> clf.fit(clips) # doctest: +SKIP
120
+ >>> scores = clf.decision_function(clips) # doctest: +SKIP
121
+ """
122
+
123
+ def __init__(self, n_mels=64, context=5, hop_length=512, sr=_DEFAULT_SR,
124
+ contamination=0.1, epoch_num=40, batch_size=1024, lr=1e-3,
125
+ hidden_neuron_list=None, device=None, random_state=42,
126
+ verbose=0):
127
+ super(AudioAE, self).__init__(contamination=contamination)
128
+ self.n_mels = n_mels
129
+ self.context = context
130
+ self.hop_length = hop_length
131
+ self.sr = sr
132
+ self.epoch_num = epoch_num
133
+ self.batch_size = batch_size
134
+ self.lr = lr
135
+ self.hidden_neuron_list = hidden_neuron_list
136
+ self.device = device
137
+ self.random_state = random_state
138
+ self.verbose = verbose
139
+
140
+ def _extract(self, X):
141
+ """Return (frames, clip_idx) over all clips in X."""
142
+ try:
143
+ import librosa # noqa: F401
144
+ import soundfile # noqa: F401
145
+ except ImportError:
146
+ raise ImportError(
147
+ "AudioAE requires 'librosa' and 'soundfile'. "
148
+ "Install with: pip install pyod[audio]")
149
+ if len(X) == 0:
150
+ raise ValueError("AudioAE received an empty input.")
151
+ frames_list, clip_idx = [], []
152
+ for i, item in enumerate(X):
153
+ y = _to_mono_waveform(item, self.sr)
154
+ windows = _logmel_windows(y, self.sr, self.n_mels,
155
+ self.context, self.hop_length)
156
+ frames_list.append(windows)
157
+ clip_idx.append(np.full(len(windows), i, dtype=np.int64))
158
+ return np.concatenate(frames_list, axis=0), np.concatenate(clip_idx)
159
+
160
+ @staticmethod
161
+ def _aggregate(frame_scores, clip_idx, n_clips):
162
+ """Mean per-frame score within each clip."""
163
+ out = np.zeros(n_clips, dtype=np.float64)
164
+ for i in range(n_clips):
165
+ mask = clip_idx == i
166
+ if mask.any():
167
+ out[i] = float(frame_scores[mask].mean())
168
+ return out
169
+
170
+ def fit(self, X, y=None):
171
+ """Fit the frame autoencoder and score the training clips.
172
+
173
+ Parameters
174
+ ----------
175
+ X : list
176
+ Audio clips as file paths, waveform arrays, or
177
+ ``(waveform, sample_rate)`` tuples.
178
+
179
+ y : Ignored
180
+ Not used, present for API consistency.
181
+
182
+ Returns
183
+ -------
184
+ self : object
185
+ """
186
+ try:
187
+ import torch # noqa: F401
188
+ except ImportError:
189
+ raise ImportError(
190
+ "AudioAE requires torch (for the autoencoder) and "
191
+ "pyod[audio] (librosa, soundfile). Install with: "
192
+ "pip install pyod[torch,audio]")
193
+ from .auto_encoder import AutoEncoder
194
+
195
+ frames, clip_idx = self._extract(X)
196
+ dim = frames.shape[1]
197
+ hidden = self.hidden_neuron_list or [128, 32, 8]
198
+ # Drop hidden layers that are not smaller than the input so the
199
+ # autoencoder stays a contraction for unusually small windows.
200
+ hidden = [h for h in hidden if h < dim] or [max(dim // 2, 2)]
201
+
202
+ # Cap the batch size to the frame count. PyOD's AutoEncoder drops
203
+ # the last incomplete batch, so a batch larger than the dataset
204
+ # would drop every frame and leave the training loop with nothing.
205
+ batch_size = max(1, min(self.batch_size, frames.shape[0]))
206
+
207
+ self.ae_ = AutoEncoder(
208
+ contamination=self.contamination, epoch_num=self.epoch_num,
209
+ batch_size=batch_size, lr=self.lr,
210
+ hidden_neuron_list=hidden, device=self.device,
211
+ random_state=self.random_state, verbose=self.verbose)
212
+ self.ae_.fit(frames)
213
+
214
+ frame_scores = self.ae_.decision_function(frames)
215
+ self._set_n_classes(y)
216
+ self.decision_scores_ = self._aggregate(frame_scores, clip_idx, len(X))
217
+ self._process_decision_scores()
218
+ return self
219
+
220
+ def decision_function(self, X):
221
+ """Predict clip-level anomaly scores for X.
222
+
223
+ Parameters
224
+ ----------
225
+ X : list
226
+ Audio clips in the same formats accepted by ``fit``.
227
+
228
+ Returns
229
+ -------
230
+ anomaly_scores : numpy array of shape (n_clips,)
231
+ """
232
+ check_is_fitted(self, ['decision_scores_', 'threshold_', 'labels_'])
233
+ frames, clip_idx = self._extract(X)
234
+ frame_scores = self.ae_.decision_function(frames)
235
+ return self._aggregate(frame_scores, clip_idx, len(X))
@@ -431,6 +431,55 @@ class EmbeddingOD(BaseDetector):
431
431
  config = {**presets[quality], **kwargs}
432
432
  return cls(**config)
433
433
 
434
+ @classmethod
435
+ def for_audio(cls, quality='balanced', **kwargs):
436
+ """Create an EmbeddingOD configured for audio anomaly detection.
437
+
438
+ Uses a handcrafted 74-dim acoustic feature encoder (20 MFCC,
439
+ 12 chroma, and 5 spectral descriptors, each as mean and standard
440
+ deviation over frames) followed by a classical PyOD detector. This
441
+ embed-then-detect pattern with classical detectors is competitive
442
+ on standard audio anomaly detection benchmarks and needs no GPU.
443
+ Requires ``pyod[audio]`` (librosa, soundfile).
444
+
445
+ Input clips may be file paths, waveform arrays, or
446
+ ``(waveform, sample_rate)`` tuples.
447
+
448
+ Parameters
449
+ ----------
450
+ quality : str, optional (default='balanced')
451
+ - 'fast': handcrafted features + IForest.
452
+ - 'balanced': handcrafted features + KNN.
453
+ - 'best': handcrafted features + LUNAR (requires torch).
454
+
455
+ **kwargs
456
+ Override any EmbeddingOD parameter.
457
+
458
+ Returns
459
+ -------
460
+ clf : EmbeddingOD
461
+ """
462
+ presets = {
463
+ 'fast': {
464
+ 'encoder': 'audio-mfcc',
465
+ 'detector': 'IForest',
466
+ },
467
+ 'balanced': {
468
+ 'encoder': 'audio-mfcc',
469
+ 'detector': 'KNN',
470
+ },
471
+ 'best': {
472
+ 'encoder': 'audio-mfcc',
473
+ 'detector': 'LUNAR',
474
+ },
475
+ }
476
+ if quality not in presets:
477
+ raise ValueError(
478
+ "quality must be 'fast', 'balanced', or 'best', "
479
+ "got '%s'" % quality)
480
+ config = {**presets[quality], **kwargs}
481
+ return cls(**config)
482
+
434
483
 
435
484
  class MultiModalOD(BaseDetector):
436
485
  """Multi-modal anomaly detection via score fusion.