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, 冷链监控, 异常检测, 数据科学, 文档结构分析, 时间序列分析, 机器学习, 生物医学, 资源验证, 逆向工具