個人基線:為什麼你的「正常」不是人群均值
人群均值是一個沒有你參與的平均數。個人基線是你自己最近這段時間寫下的尺子——它一開始很鈍,用得久才準。
兩個人,同一個數字
兩個人,一個平時的讀數高出一大截,一個平時的讀數低一大截。某天下午,兩個人的讀數停在了同一個數上。
一把人群尺子會這麼說:第二位沒事,第一位狀態糟糕。可那天真正發生的是——第一位掉了一大截,第二位漲了一大截。
當我們還沒有你的基線時,用的就是這麼一把尺子:一個來自人群統計的中心,配上同樣來自人群的寬度。它只是最初幾天的兜底,不是我們認為正確的做法。用得越久越明顯:它衡量的不是你,是你和一群陌生人之間的距離。
人和人的差距,比一個人每天的波動大得多
HRV 受年齡、性別、基礎心率、用藥、訓練水平、自主神經張力影響。人和人之間能差出好幾倍;而同一個人,日與日之間只在一個很窄的範圍裡晃。
所以人群尺子是兩頭都錯:對基線高的人,他正常的低端會被判成糟糕;對基線低的人,他真正糟糕的一天還落在人群的正常區間裡,尺子一聲不響。
還有個更安靜的問題:它獎勵天生 HRV 高的人。同樣的生活方式,起點不同,分數就不同。而我們想衡量的不是你站在人群的哪個位置,是你離你自己有多遠。
這把尺子是怎麼造出來的
先讓樣本等權。 Apple Watch 有些天寫得密,有些天寫得稀。要是直接把樣本丟進統計,寫得多的時段就會拿到更大權重——基線不是被你的身體推動,而是被取樣率推動。所以進入基線計算之前,HRV 先按本地時間歸入一個個等長的時間桶,每桶只留中位數。圖表、詳情、當次算分仍然用原始樣本,只有造尺子這一步用桶。
再選窗口。 上限大約一個月。最近這段時間裡 HRV 桶、靜息心率樣本和覆蓋的自然日都夠多,就用完整窗口;達不到,就用真實的數據跨度。為什麼不把窗口定得更短——太短,一個糟心的夜晚就能把基線拽走。為什麼不再拉長——太長,換季、訓練週期、作息改變會混進來。
中心取中位數。 先丟掉物理上不合理的值,樣本夠多時兩端各裁掉一小截,然後取中位數。中位數對偶發的極端值不敏感:一次沒戴穩測出的離譜高值,不該抬高你一整週的中心。
把中心釘在當下這個小時。 HRV 有晝夜節律,多數人睡眠時最高、下午最低(形狀因人而異)。一個靜止的中心不夠用。我們從最近這段時間的幾個粗時段的中位數算節律因子——每個時段都要有足夠樣本,且要有足夠多的時段算得上可靠;缺的時段按環形插值補上,展開到每個小時之後做一次輕度平滑,最後鉗在一個合理的範圍內。某一時刻的動態中心 = 全天中心 × 那個小時的因子。
為什麼是幾個粗時段,而不是一小時一格:手錶上的 HRV 稀疏又不均勻,多數小時只有一兩條樣本,按小時取中位數基本是在給噪聲畫曲線。粗時段加上插值與平滑,比精細但空著的桶更接近真實節律。
區間不用標準差。 這是關鍵的一步。HRV 的變化是乘性的:從高位掉同樣的比例,和從低位掉同樣的比例,是同一件事,可絕對差一個是另一個的好幾倍。所以對每個樣本,我們算的是它相對那一刻動態中心的對數殘差。
在對數尺度上,基線不同的人可以放進同一張圖裡比較;換回毫秒時,區間天然為正。然後在這堆殘差上取三個分位——偏下的一側、偏上的一側,以及更靠外的一檔:
狀態正常的下沿 = 中心 × exp(偏下那一檔的殘差)
元氣滿滿的入口 = 中心 × exp(偏上那一檔的殘差)
狀態糟糕的入口 = 中心 × exp(更靠外那一檔的殘差)
選這一組而不是常見的四分位是有意的:讓「狀態正常」覆蓋你日常波動的中間一段,並且整體向高的一側偏移——偏低時更早被注意到,只有進入你個人最好的一小段才算元氣滿滿。健康產品不該靠發誇獎來維持存在感。
上面還壓了三道安全閥:
半寬有下限。天生波動很小的人,分位會窄到離譜,單次讀數的噪聲就夠讓他在一天裡反覆跨檔。
上半寬最多是下半寬的一個固定倍數。HRV 右側那條長尾會一直把「狀態正常」的上沿往上頂,頂到最後變成「只要你不是特別低就算正常」。
狀態糟糕的入口還要再往外推:取分位與「中心減去若干個有效下半寬」裡更靠外的那個。同樣是防抖——寧可讓這條線更靠外,也不讓它卡在噪聲裡。
殘差模型自己也有准入門檻:歸一化樣本要夠多、覆蓋的自然日要夠多、可靠的時段要夠多。達不到就整體回退到穩健半寬——用中位數的絕對偏差和四分位差裡更穩的那個,寬度再封一道頂。也就是說,你看到的區間要麼來自你自己的分位分佈,要麼來自一把很鈍但很穩的尺子,不會來自一個湊出來的分位數。
檔位的單位是「半寬」,不是標準差。 算分看的是當前值離中心偏了幾個半寬(低於中心用下半寬,高於用上半寬),不是幾個標準差。這樣每個檔位在所有人身上語義一致:偏離在一個半寬以內是狀態正常,往低的一側越過就是元氣滿滿,再往外是有些疲憊,跌破狀態糟糕的入口就是最後一檔。人和人的差別只體現在「半寬有多寬」,不體現在「多少分算正常」。
還有兩根護欄。心率是輔助項,只在 HRV 已經偏離中心時才加重權重(偏得越遠,權重越高),而且它比的是你自己的靜息心率。另一根是絕對極低 HRV 的保護,它完全不看個人基線——生理上的極低就是極低,不需要「相對你的基線」來開脫。
數據還不夠的時候
頭幾天,個性化分數會和人群兜底分數按天數線性混合;這時基線標記為冷啟動,只作參考,不承擔檔位邊界。再往後是一段「學習中」。用到足夠多天、且殘差模型質量過關,才算成熟。
可靠性是另一套門檻:已有的數據越少,要求的樣本越多。它決定這條基線有沒有資格參與算分;成熟度決定它在選擇策略裡的優先級,以及介面上該怎麼表達信心。
評估某一天時,只使用嚴格早於那天的基線。當天現算出來的基線不參與當天的判斷——否則 HealthKit 一條條把數據同步進來,今天的結論會來回跳。
基線自己也會漂,所以留了第二根錨
滾動窗口有個副作用:一個人如果連續幾個月處在低 HRV,這個低水平會慢慢變成「他的正常」,長期變化就看不見了。
所以我們保留最近一段時間裡的基線快照,把當前快照和大約一個月前的一份配對。要湊夠足夠的配對、且大部分方向一致,才輸出「持續偏低」或「持續偏高」。給用戶的說法是三態:比上個月好一些、差一些、差不多。湊不齊就留白——不把「不知道」寫成「沒變」。
另外還有一條慢錨,每天最多向快基線挪很小一步,遇到持續漂移時步長再縮小。它只在持續偏低時對分數做很輕微的上調,而且不回刷歷史記錄。這個不對稱是故意的:長期偏低值得被更認真地對待,長期偏高不需要獎勵。
還沒解決的部分
取樣密度在基線一側被這套分桶隔離了,但日匯總仍然按壓力點等權,高頻設備上白天的權重會偏大。這是已知偏置,改法(按時間桶等權)在需求池裡,這一輪沒動。
混淆因素也清不完。咖啡因、飲酒、時差、生理週期、生病都會讓 HRV 動,我們顯式處理的只有運動和最主要的一小批來源。
最後說清楚:基線不是診斷。它是一把相對尺子,描述的是你和你自己的關係,不做任何醫學判斷。
一句話收尾——人群均值是一個沒有你參與的平均數;個人基線是你自己最近這段時間寫下的尺子。它一開始很鈍,用得久才準,這件事沒法加速。
繼續閱讀
在 Stress HRV 裡體驗這些想法
App Store 下載這些筆記分享個人健康工具的產品思考,不構成醫療建議。