RELSA 嚴重度評估和人道終點預測
概述
動物研究中的嚴重度評估在法律上是強制性的,在科學上也是至關重要的:它驅動著人道終點的決策,而欠佳的福利監控會降低研究的可重複性。通常的做法是孤立地評估每個讀數——這裡是體重減輕,那裡是臨床評分——這使得很難判斷一隻個體動物的實際情況有多糟糕。
此技能實作了兩種已發表的程序來解決這個問題:
- RELSA(Talbot 等人,2022)將幾個結果指標組合成每隻動物在每個時間點的一個分數,並相對於一個已知負擔的參考組進行表達。RELSA = 0 是基線;RELSA = 1 表示該動物已達到參考組的最大偏差。
- foRcast(Lutscher 等人,2026)對單隻動物的 RELSA 軌跡擬合一個 ARIMA 模型,並使用 95% 的預測區間預測下一個分數,這樣可以在動物達到人道終點之前識別出它們。RELSA 尺度上的核密度估計提供了候選的注意和危險區間以供解釋。
重點是優化:更早地關注高風險動物,並避免安樂死本可康復的動物。這兩種程序都是嚴重度評估的輔助工具,而非決策規則——詳見範圍。
何時使用此技能
- 將體重減輕、溫度、臨床評分、生物標記物或遠端監測數據組合成一個單一的每隻動物嚴重度分數
- 詢問群組中哪些動物有達到人道終點的風險,或預測未來某個時間點的嚴重度分數
- 在一個共同的相對尺度上比較治療組、干預措施或動物模型之間的嚴重度
- 根據數據定義嚴重度尺度上的閾值或區間
- 撰寫動物福利報告、3R/優化分析或根據 EU Directive 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。 - **每隻動物每個時間點一行。**首先將每小時的遠端監測數據平均為每個間隔的一個值(已發表的模型平均心率、心率變異性和溫度,並彙總活動)。
- 缺失的測量值留空。它們會被從分數中剔除,絕不會被插補——將缺失值視為「無偏差」會使嚴重度得分偏低。
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 臨床評分
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 Directive 2010/63/EU 的分類(非恢復、輕度、中度、重度)是透過不同的過程前瞻性分配的。該論文明確指出其閾值「不應與監管意義上的嚴重度分級混淆」,並且不能直接轉換為後者。
- **分數在不同參考組或模型之間不具有可比性。**RELSA 本質上是相對的,並且不同實驗室之間的臨床評分並未標準化。報告分數時請務必同時報告其參考組。
- 已發表的證據是一個概念驗證:涵蓋 7 個模型的 13 隻動物,其中 5 個數據行僅基於一或兩隻動物。整體 RMSE 為 0.069,PICP 為 96%,來自於 13 個終點預測。
- 低估分數是危險的錯誤,因為它會減少關注並可能延遲安樂死的決定,而高估則只會促使給予額外的照護。
報告檢查清單
只有當以下所有內容都被說明時,嚴重度分析才是可重複的:
- 結果指標、它們的單位以及方向性(哪些被轉向,以及原因)。
- 基線時間點或視窗,以及哪些變量被歸一化。
- 應用於有序變量的任何分數映射,包括其尺度。
- 參考組:哪些動物、哪個群組、數量,以及為什麼假定它們承擔最大的負擔。
- 研究中實際應用的、獨立於 RELSA 分數之外的人道終點標準。
- 對於預測:插值步長、為每隻動物選擇的 ARIMA 階數,以及 RMSE、PICP和 MPIW。
- 對於閾值:帶寬、分數數量以及帶寬敏感性掃描。
- 軟體版本,以及閾值特定於模型而非監管分級的聲明。
常見陷阱
- 方向性錯誤——未列在
--turned中的上升變量,會靜默地貢獻恰好為零,並且除非它從未下降,否則無法發出警告。請親自檢查參考模型表格:對於一個下降的變量,max reached應該低於 100,而對於一個轉向的變量,則應高於 100;max delta對於該測量指標來說應該是一個合理的數值。 - 對百分比進行兩次歸一化——
bwc [%]和映射後的分數已經處於百分比尺度上;將它們傳遞給--normalize...
[其餘內容因原始提示截斷而未包含]