RELSA 严重程度评估与人道终点预测
概述
动物研究中的严重程度评估在法律上是强制性的,在科学上也是关键支撑:它驱动着人道终点的决策,糟糕的福利监测会降低研究的可重复性。常规做法是孤立地评估每个读数——这里是体重损失,那里是临床评分——这使得难以判断一只动物个体的真实痛苦程度。
该技能实现了两种已发表的方法来解决这个问题:
- RELSA (Talbot et al., 2022) 将多个结果指标合并为每只动物在每个时间点的一个得分,表达为相对于一个已知负担的参考集。RELSA = 0 表示基线;RELSA = 1 表示该动物已达到参考集的最大偏差。
- foRcast (Lutscher et al., 2026) 对每只动物的 RELSA 轨迹拟合 ARIMA 模型,并通过 95% 预测区间预测下一个得分,从而可以在动物到达人道终点之前识别出正在向该终点发展的个体。在 RELSA 标尺上的核密度估计提供了候选的关注区和危险区以供解释。
关键是优化:更早地关注有风险的动物,并避免对可能恢复的动物实施安乐死。这两种方法都是严重程度评估的辅助工具,而非决策规则——请参见边界。
何时使用该技能
- 将体重损失、体温、临床评分、生物标志物或遥测数据合并为每只动物的单一严重程度得分
- 询问一个队列中哪些动物有达到人道终点的风险,或预测未来时间点的严重程度得分
- 在共同的相对标尺上比较治疗组、干预措施或动物模型之间的严重程度
- 从数据中定义严重程度标尺上的阈值或区域
- 编写动物福利报告、3Rs/优化分析或 EU 2010/63/EU 指令下申请的严重程度评估部分
对于非严重程度得分的通用时间序列预测,请使用 timesfm-forecasting 或 statsmodels。对于研究设计和样本量,请使用 experimental-design 和 statistical-power。
安装
uv pip install "numpy>=1.26" "pandas>=2.0" "scipy>=1.11" "statsmodels>=0.14" matplotlib
relsa_score.py 和 kde_thresholds.py 仅需要 numpy/pandas/scipy;statsmodels 用于预测,matplotlib 仅用于绘图。
数据格式
每只动物每个时间点一行,格式为 CSV:
| id | treatment | condition | day | temp | weight | score | il6 |
|---|---|---|---|---|---|---|---|
| M01 | treated | endpoint | -1 | 37.15 | 25.17 | 0 | 35.1 |
| M01 | treated | endpoint | 0 | 37.26 | 25.25 | 0 | 39.5 |
| M01 | treated | endpoint | 1 | 35.83 | 23.12 | 4 | 162.0 |
- 需要
id和一个时间列(day、time、hour等);treatment和condition是可选的标签,用于分组和选择参考集。 - 时间可以是天、小时或分钟——只需对每只动物保持单调递增。RELSA 惯例将基线时间点编码为
-1。 - 每只动物每个时间点一行。 首先将每小时遥测数据平均为一个区间的值(已发表模型平均心率、HRV 和体温,并汇总活动量)。
- 缺失测量值留空。它们会从得分中删除,从不进行插补——缺失值被视为“无偏差”,会严重低估得分。
assets/example_cohort.csv 是一个小的合成队列(6 只小鼠,9 天,体温、体重、0-8 分临床评分和一个类似 IL-6 的生物标志物),被以下每个命令使用,因此每个命令都可以直接运行。
决定结果的四个关键选择
明确做出这些选择并将其写入方法。其他任何步骤都没有这些重要。
1. 方向性——哪些变量在恶化时上升? 下降是默认方向(体重、活动量、食物摄入、挖掘、跑轮)。上升的变量必须声明为 --turned:临床评分、炎症生物标志物、发热、心动过速。如果弄错,该变量将完全无贡献,悄无声息地,因为“错误”方向的偏差会被归零。体温取决于模型——在脓毒症和内毒素血症中它下降,在发热模型中它上升。数据本身无法解决这个问题:在已发表的脓毒症模型中,活动量在基线以上和以下的摆动都合法存在,因此只有从未按声明方向移动的变量才能被检测到,build_reference() 会警告这种情况。
2. 参考集——相对于什么? 没有参考集,RELSA 得分毫无意义。使用您模型中假定承受最大负担的组(已发表研究使用最高剂量或达到终点的治疗组)。参考集太温和会将所有得分推到 1 以上;太严苛会将所有得分压缩到接近 0。使用 --save-reference 保存参考集,并使用 --load-reference 重新加载,以便后续队列保持在同一标尺上。
3. 具有零基线的得分。 健康动物中的临床评分为 0 不能进行比率归一化——0/0 未定义。使用 --score-scale score=8 将得分的标尺映射(健康 → 100%,最差可能 → 200%),这也将其标记为转向。这种映射是一种建模选择,决定了得分的一个点相对于体重的一个百分点的价值;需要说明它。另一种选择是将评分排除在 RELSA 之外,并将其用作独立的终点标准。
4. 哪些变量在整个过程中被测量。 由于得分是对可用变量进行平均,因此一个在轨迹中途出现或消失的变量会独自改变得分。在已发表的脓毒症数据中,添加仅在安乐死当天记录的体重,将该动物的终点得分从 0.93 降至 0.83,这没有生物学原因。relsa_scores() 在组成变化时会发出警告;应得分在整个过程中都存在的变量。
工作流程
第 1 步——计算 RELSA 得分
python scripts/relsa_score.py assets/example_cohort.csv \
--variables weight,temp,score,il6 \
--normalize weight,temp,il6 \
--turned il6 \
--score-scale score=8 \
--baseline-time -1 \
--reference-group condition=endpoint \
--save-reference reference.json \
--out relsa_scores.csv
参考模型会回显,以便标尺可审计:
reference model: assets/example_cohort.csv [condition=endpoint]
animals=2 rows=18 baseline_time=-1.0
variable turned max reached max delta
weight no 82.40 17.60
temp no 92.79 7.21
score yes 187.50 87.50
il6 yes 797.72 697.72
relsa_scores.csv 包含每个变量的权重以及得分,这使得得分可解释——这里 M01 恶化到其终点,M03 在第 3 天达到峰值然后恢复:
id time weight temp score il6 n_vars relsa
M01 1 0.46 0.49 0.57 0.52 4 0.51
M01 3 0.84 0.76 1.00 0.89 4 0.88
M01 5 1.00 1.00 1.00 1.00 4 1.00
M03 3 0.56 0.44 0.57 0.54 4 0.53
M03 5 0.35 0.26 0.43 0.32 4 0.35
M03 7 0.12 0.06 0.14 0.11 4 0.11
权重为 1.00 表示该变量达到了参考最大值;n_vars 是该时间点进入得分的变量数量。
从 Python 中执行相同操作,当您需要对象时:
import sys; sys.path.insert(0, "scripts")
from _common import read_relsa_table, score_to_percent
from relsa_score import prepare, build_reference, relsa_scores
frame = read_relsa_table("assets/example_cohort.csv")
frame["score"] = score_to_percent(frame["score"], max_score=8) # 0-8 clinical score
VARS, TURNED = ["weight", "temp", "score", "il6"], ["score", "il6"]
prepared = prepare(frame, normalize=["weight", "temp", "il6"], baseline_time=-1)
reference = build_reference(prepared[prepared.condition == "endpoint"],
variables=VARS, turned=TURNED, baseline_time=-1,
label="endpoint-reaching animals")
scores = relsa_scores(prepared, reference)
第 2 步——预测终点
使用截至终点前时间点的所有数据训练模型,预测终点处的得分,并对预测进行评分:
python scripts/forecast_relsa.py relsa_scores.csv \
--animals M01,M02 --endpoints M01=5 --endpoints M02=6 \
--group-col condition --plot-dir figs --endpoint-line 1.0
id time predicted lower upper model actual
M01 5.0 0.932585 0.670443 1.194728 ARIMA(1,1,0) 1.00
M02 6.0 0.955696 0.748309 1.163084 ARIMA(1,1,0) 0.94
group id model n rmse picp mpiw
endpoint M01 ARIMA(1,1,0) 1 0.0674 100.0 0.524
endpoint M02 ARIMA(1,1,0) 1 0.0157 100.0 0.415
endpoint -- endpoint -- 2 0.0489 100.0 0.470
OVERALL 2 0.0489 100.0 0.470
同时报告所有三个指标。RMSE 是点预测精度,PICP 是实际值落在区间内的百分比,MPIW 是以 RELSA 单位表示的平均区间宽度——一个模型可以通过使区间过宽(以至于失去意义)来达到 PICP = 100%,这恰好是论文中胰腺癌行所展示的情况(PICP 100%,MPIW 7.35,即 RELSA 范围的 735%)。
对于实时监测,在每个时间点向前一步预测:
python scripts/forecast_relsa.py relsa_scores.csv --mode rolling --animals M03
在信任预测之前需要了解两件事:
- 插值默认开启(
--interpolate-step 0.1),因为每天一个测量值对于 ARIMA 来说过于稀疏。它能以牺牲诚实的不确定性为代价,获得可用的模型选择和更窄的区间。当测量频率允许时,设置--interpolate-step 0。 - ARIMA 无法预测断崖式下降。 它假设平稳性和线性,因此终点前最后几小时的突然崩溃无法从平滑的先前轨迹中预测出来——这正是论文自身的失败案例。应采取区间上限行动,并且永远不要让低预测值覆盖看起来不适的动物。
第 3 步——用严重程度区域将得分置于上下文中
python scripts/kde_thresholds.py relsa_scores.csv \
--group treatment=treated --n-thresholds 2 --plot zones.png --json zones.json
KDE on 33 RELSA scores (bandwidth = 0.1502)
candidate thresholds (density minima): 0.703
density modes: 0.264, 0.866
normal [0.000, 0.703) n=25 (75.8%)
danger >= 0.703 n=8 (24.2%)
阈值是得分密度的最小值——得分簇之间的稀疏谷底。应包括终点动物、幸存者和假手术组:这些区域旨在分离这些状态,因此必须全部呈现。
在相信阈值之前检查带宽。 在已发表的脓毒症数据上,此实现找到最小值在 0.355 和 0.655(已发表:0.337 和 0.643)——但带宽增大 10% 会同时消除这两个最小值。运行 references/thresholds-and-zones.md 中的扫描,并报告扫描结果,而不是一对孤立的数字。空阈值列表是合法答案:得分形成一个簇,并且没有数据驱动的切割点。
边界:在报告中说明这些内容
- RELSA 是严重程度评估的辅助工具,而非决定性参数。 具有低 RELSA 得分但显示其他痛苦迹象的动物仍必须得到相应处理。两种方法都不是经过验证的死亡预测指标。
- KDE 区域不是法规严重程度分级。 EU 2010/63/EU 指令的分类(非恢复、轻度、中度、重度)是通过不同程序前瞻性分配的。论文明确指出其阈值“不应与法规严重程度分级混淆”,并且不能直接转换。
- 得分在不同参考集或模型之间不可比较。 RELSA 本质上是相对的,临床评分在不同实验室之间也未统一。始终随得分报告参考集。
- 已发表的证据是概念验证:涉及 7 个模型中的 13 只动物,其中 5 行仅依赖于一到两只动物。0.069 的整体 RMSE 和 96% 的 PICP 来自 13 个终点预测。
- 低估得分是危险的错误,因为它会抑制关注并可能延迟安乐死决定,而高估只会导致额外的护理。
报告清单
严重程度分析只有在所有以下内容都得到说明时才是可重复的:
- 结果指标、其单位及其方向性(哪些被转向,以及为什么)。
- 基线时间点或窗口,以及哪些变量被归一化。
- 应用于有序变量的任何得分映射及其标尺。
- 参考集:哪些动物、哪个组、数量,以及为什么假定它们承受最大负担。
- 研究中实际应用的人道终点标准,与 RELSA 得分分开。
- 对于预测:插值步骤、每只动物选择的 ARIMA 阶数以及 RMSE、PICP 和 MPIW。
- 对于阈值:带宽、得分数量以及带宽敏感性扫描。
- 软件版本,以及阈值是模型特异性的而非法规分级的说明。
常见陷阱
- 错误的方向性——未在
--turned中列出的上升变量会完全零贡献,悄无声息地,并且除非该变量从未下降,否则无法发出警告。自己检查参考模型表:max reached对于下降变量应低于 100,对于转向变量应高于 100,并且max delta应对于该指标是合理的大小。 - 两次归一化一个百分比——
bwc [%]和映射得分已经处于百分比标尺上;将它们传递给--normalize会按健康基线的百分比对它们进行缩放,如果健康值不能保证为 100,则会导致无意义的数字。仅对原始测量值(体重、体温、活动计数、生物标志物浓度)使用--normalize。 - 随时间变化的变量组成——如果一个变量仅在几个时间点可用,它会独立改变得分。确保得分在整个研究期间基于相同的一组变量。
- 忽略带宽敏感性——KDE 阈值可能对带宽选择高度敏感。始终进行敏感性扫描,如果阈值不稳定,则报告这一点。
- 将 RELSA 混淆为监管终点——RELSA 得分是动物福利评估的辅助工具,而不是活体使用的替代品。监管决定必须根据所有可用信息做出。
引用
如果您在已发表的研究中使用这种方法,请引用:
- Talbot, S. R., et al. (2022). "RELSA — A multidimensional procedure for the relative severity assessment of animal models." Animal Models and Experimental Medicine, 5(3), 245–254. DOI: 10.1002/ame2.12251
- Lutscher, M., et al. (2026). "foRcast — Forecasting humane endpoints in laboratory animal studies using time series analysis." Laboratory Animals (预印本/已提交).
未来方向
正在开发的内容:
- 多物种支持:扩展参考框架以处理除小鼠和大鼠以外的物种。
- 多元 ARIMA:直接对多个读数建模,而不是先汇总到 RELSA。
- 贝叶斯方法:在预测区间中提供更好的不确定性量化。
- 实时仪表板:集成到 vivarium 监测系统中。
欢迎贡献!请提出问题或拉取请求。
许可
该技能在 MIT 许可下发布。详见 LICENSE 文件。