srujanc09/BioSentinel

GitHub: srujanc09/BioSentinel

BioSentinel 是一个用于生物医学时间序列传感器数据(如冷链温度)的开源机器学习异常检测工具,提供从统计方法到 IsolationForest 的七种检测器。

Stars: 0 | Forks: 0

# BioSentinel 用于生物医学时间序列数据(冷链传感器、实验室仪器)的开源 ML 异常检测工具。 ## 问题背景 冷链设备和实验室仪器会不断传输传感器读数。储存疫苗或胰岛素的冰箱可能会在数小时内缓慢发生故障。被篡改的传感器可以通过伪造的正常读数来掩盖受污染的批次。等到人工检查发现这些故障时,产品通常已经损坏。 简单的阈值系统只能捕捉到急剧的峰值,但会漏掉持续的缓慢故障。虽然存在高级的商业系统,但它们通常是闭源且无法审计的。BioSentinel 提供了一个完全开源且可复现的基准,任何研究人员或学生都可以对其进行检查、运行和扩展。 ## 数据集 BioSentinel 在 [Numenta Anomaly Benchmark](https://github.com/numenta/NAB) 的 `machine_temperature_system_failure` 数据集上进行了评估: - 22,695 行数据,每 5 分钟读取一次 - 日期范围:2013 年 12 月 2 日至 2014 年 2 月 19 日 - 包含四个覆盖设备故障事件的标注异常窗口 - 2,268 个标注异常点(占所有读数的 10.0%) 本仓库不包含该数据集(`data/` 文件夹已被 gitignore 忽略)。要使用它,请执行以下操作: ``` mkdir data curl -L -o data/machine_temp.csv \ "https://raw.githubusercontent.com/numenta/NAB/master/data/realKnownCause/machine_temperature_system_failure.csv" ``` 或者手动下载该 URL,并将文件保存为 `data/machine_temp.csv`。 ## 方法论 按照复杂度顺序构建了七个检测器。每一步的构建动机都源于前一个检测器的特定缺陷。 | 步骤 | 检测器 | 构建原因 | |------|----------|-----------------| | 1 | 3-Sigma (Global) | 统计学基准——任何偏离全局均值超过 3 个标准差的数据点都会被标记。仅需两行算术运算即可完成审计。 | | 2 | Rolling 3-Sigma | 使用局部滚动均值代替全局均值。预期能更好地适应渐变漂移。 | | 3 | EWMA | 指数加权基准,span=5000(约 17 天)。其适应速度足够慢,能够在 48 小时的故障期间保持稳定。 | | 4 | Hampel Filter | 使用滚动中位数和 MAD 代替均值和标准差的稳健统计过滤器。已知能够很好地处理突然出现的峰值。 | | 5 | LOF | Local Outlier Factor (局部异常因子) 将局部密度与相邻点进行比较。旨在任意特征空间中寻找孤立的异常值。 | | 6 | IsolationForest | 使用随机切分来隔离数据点的基于树的方法。具有全局分布特性,不受窗口适应问题的干扰。 | | 7 | IsolationForest + Rolling | 增加了一个工程特征:`sustained_dev = value - rolling_mean(360)`。在 48 小时的故障期间,即使原始温度看起来像是一次正常的下降,该特征也会保持强烈的负值。**表现最佳的模型。** | ## 结果 所有指标均是针对四个 NAB 真实异常窗口计算得出的。没有进行任何刻意挑选。包含并解释了失败的检测器。 | 检测器 | Precision | Recall | F1 | |----------|-----------|--------|----| | 3-Sigma (Global) | 0.991 | 0.202 | 0.336 | | Rolling 3-Sigma (w=1000) | 0.283 | 0.088 | 0.134 | | EWMA (span=5000) | 0.586 | 0.513 | 0.547 | | Hampel Filter (w=144) | 0.107 | 0.033 | 0.050 | | LOF (k=20) | 0.109 | 0.131 | 0.119 | | IsolationForest (raw) | 0.471 | 0.566 | 0.514 | | **IsolationForest + Rolling (w=360)** | **0.568** | **0.682** | **0.619** | **关于 recall 上限的说明:** 38.8% 的标注异常点落在正常温度范围内,因为 NAB 异常窗口在温度下降之前就开始了。任何仅依赖原始值的检测器,其 recall 都无法超过大约 61.2%。IsolationForest + Rolling 模型通过使用 `sustained_dev` 作为第二特征,使模型获得了原始值无法提供的时间上下文,从而达到了 recall=0.682。 **Precision-Recall AUC 分数**(跨所有阈值的排序能力): | 检测器 | AUC-PR | |----------|--------| | 3-Sigma | 0.604 | | EWMA | 0.418 | | LOF | 0.112 | | IsolationForest (raw) | 0.559 | | IsolationForest + Rolling | **0.610** | ## 超参数调优 两个关键超参数均经过了系统性扫描调优,而非盲目猜测。 **Contamination 扫描**(0.02 到 0.30,long_window 固定为 360):F1 在 contamination=0.12 时达到峰值。真实的异常率为 10.0%,但 IsolationForest 的内部阈值校准略显保守,因此将 contamination 设置得略高于真实比率可以获得更好的 Precision-Recall 平衡。 **Window 扫描**(24 到 576 行,contamination 固定为 0.12):F1 在 360 行 = 30 小时时达到峰值。2 月份的故障持续了大约 48 小时。30 小时的基准窗口不会完全适应故障状态,从而使 `sustained_dev` 在整个过程中保持明显的负值。较短的窗口会将故障状态视为正常;而较长的窗口则会丧失故障 onset(发作)时的分辨率。 ## 安装说明 ``` pip install -r requirements.txt ``` 需要 Python 3.10 或更高版本。 ## 运行 CLI 主入口点是 `biosentinel.py detect`。它会加载 CSV 文件,运行选定的检测器,并按异常分数排序打印出被标记的时间戳。 **基本用法——打印异常分数最高的前 20 个数据点:** ``` python biosentinel.py detect data/machine_temp.csv ``` **选择不同的检测器:** ``` python biosentinel.py detect data/machine_temp.csv --detector ewma python biosentinel.py detect data/machine_temp.csv --detector 3sigma python biosentinel.py detect data/machine_temp.csv --detector iforest ``` **打印所有被标记的时间戳(不仅是前 20 个):** ``` python biosentinel.py detect data/machine_temp.csv --all ``` **将结果导出为 CSV:** ``` python biosentinel.py detect data/machine_temp.csv --all --export flagged.csv ``` **保存检测图表:** ``` python biosentinel.py detect data/machine_temp.csv --plot out.png ``` **根据真实窗口进行评估(计算 Precision、Recall、F1):** ``` python biosentinel.py detect data/machine_temp.csv \ --labels "2013-12-10 06:25:00" "2013-12-12 05:35:00" \ "2013-12-15 17:50:00" "2013-12-17 17:00:00" \ "2014-01-27 14:20:00" "2014-01-29 13:30:00" \ "2014-02-07 14:55:00" "2014-02-09 14:05:00" ``` **所有选项:** ``` python biosentinel.py detect --help --detector 3sigma | rolling-3sigma | ewma | hampel | lof | iforest | rolling-iforest --contamination float (default: 0.12) --window int rolling window rows for rolling-3sigma / hampel (default: 1000) --span int EWMA span in rows (default: 5000) --long-window int sustained-deviation window for rolling-iforest (default: 360) --n-neighbors int LOF neighbors (default: 20) --top int print top N flagged timestamps (default: 20) --all print every flagged timestamp --labels START1 END1 START2 END2 ... (for scoring) --plot OUTPUT.png --export OUTPUT.csv ``` ## 运行 Streamlit App 交互式 App 允许您在所有 7 个检测器之间进行切换,并通过 5 个选项卡探索信号:检测图表、异常重叠、特征视图、异常分数和检测器比较。 ``` streamlit run app.py ``` ## 运行分析脚本 ``` # 比较全部 7 个 detector 并打印完整表格 python compare.py # Hyperparameter sweep — 生成 data/tune_sweep.png python tune.py # Precision-Recall curves — 生成 data/pr_curve.png python pr_curve.py # 探索 raw signal python explore.py # 重新生成所有网站图像 # 注意:先运行 tune.py 和 pr_curve.py — generate_web_images.py 会将 # data/tune_sweep.png 和 data/pr_curve.png 复制到 docs/images/ python generate_web_images.py ``` `docs/images/` 中的图表是预先生成并提交的,因此新克隆的代码库无需重新运行这些脚本即可使用该网站。 ## 项目结构 ``` biosentinel/ ├── biosentinel.py # All 7 detectors, evaluation helpers, CLI ├── app.py # Streamlit interactive demo ├── compare.py # Run all detectors side by side ├── tune.py # Hyperparameter sweep ├── pr_curve.py # Precision-Recall curves ├── explore.py # Signal visualization ├── evaluate.py # Baseline evaluation ├── generate_web_images.py # Reproducible figure generation for website ├── requirements.txt ├── data/ # Not included — download NAB dataset here │ └── machine_temp.csv └── website/ # Static portfolio site ├── index.html └── images/ ``` ## 局限性 本项目对其定位和适用范围保持客观透明。 **单一数据集。** 所有结果均来自单一的 NAB 时间序列。检测器的调优、最佳 window 大小以及观察到的 recall 上限都是针对此数据集和此类故障类型的。在其他传感器或故障模式下的表现尚属未知。 **手工设计的特征。** `sustained_dev` 特征是专门为持续的温度下降而设计的。其他故障模式(振荡故障、传感器漂移、间歇性故障)可能需要不同的工程特征。 **基于点的标签。** NAB 的标签是基于单次读数的(二进制:是或不是异常)。现实中,制药行业的质量控制通常需要基于批次或窗口的决策:不仅仅是“这个点是否异常”,而是“这批生产是否受损”。基于点的 F1 是一个有用的代理指标,但二者并不等同。 **无交叉验证。** 整个数据集被同时用于训练和评估。IsolationForest 是一种无监督方法(它在训练期间不使用标签),因此严格的训练/测试分离并不那么关键,但在进行超参数调优时,确实使用了标签来选择 contamination 和 window 大小。 **未在真实制药数据上进行验证。** 本项目是一个研究原型和教育工具。它尚未在实际的制药冷链传感器数据、监管级别的标签标准或生产监控基础设施上进行过测试。 ## License MIT License。详见 `LICENSE`。 ## 致谢 数据集:[Numenta Anomaly Benchmark](https://github.com/numenta/NAB)(BSD 3-Clause License)。
标签:Apex, DFIR, Kubernetes, 冷链监控, 异常检测, 数据科学, 文档结构分析, 时间序列分析, 机器学习, 生物医学, 资源验证, 逆向工具