可解释的房颤检测
智能手表的心律警报之所以吓人,是因为它不说理由。这条管线会把证据摆出来,然后测量这个解释有多少次在撒谎。

有一位患者在一年里做了 916 次智能手表心电图,跑了十二次不必要的急诊。那些警报并没有骗她,它们只是从来不说为什么。
问题是什么
智能手表擅长抓出房颤,不擅长排除房颤。灵敏度高、特异度低,于是很多人被标记出来的其实是良性心律,比如咖啡因或者焦虑带来的那种偏快但规整的心跳。
真正造成伤害的并不是那个错误的标签,而是标签周围的沉默。手表说「可能房颤」或者「无法判断」,不给任何理由,用户手里就没有可以思考的东西。2024 年一项针对房颤患者的研究发现,20% 的可穿戴设备使用者在收到心律通知后报告了强烈焦虑,而这一组人后续接受的诊断检查是对照组的两倍,消融手术率是 4.5 倍。焦虑抬高心率,心率抬高触发更多警报,循环就闭合了。
所以这个项目的目标不是更高的准确率,而是一个能说出自己看到了什么的输出。
这条管线
单导联心电图进入一个小型 1D CNN,分成 Normal、AFib、Other 三类。Grad-CAM 读取最后一个卷积层,生成一张显著性图,指出模型沿着波形究竟在看哪里。
但那张图仍然只是一张图,所以下一步是把它变成人能据此行动的文字。用 NeuroKit2 检测 R 波峰,在每一拍周围的三个生理窗口里对显著性取平均,分别是 P 波、QRS 波群和 T 波,再加上心率和心跳间隔的变异度。每条记录五个数。
这五个数被归成「高」「不规整」这样的朴素说法,交给 Claude 写面向患者的解释,并且约束死:只描述证据里有的东西,不添加任何内容,不告诉用户他有或者没有某种病,永远建议去看医生。语言模型看不到原始信号,所以写解释这件事从「诊断」退化成了「翻译」。

模型到底在看什么
在测试集上取平均,房颤记录的 QRS 激活最高,0.216 对 Normal 的 0.106;心跳间隔变异度也远高于其他类,164 毫秒对 82 毫秒。这与房颤「绝对不规整」的临床定义吻合,是个让人安心的结果,说明网络找到的是真实信号,而不是数据集里的某种伪相关。
P 波激活在三类之间差不多。在单导联、信噪比不高的条件下,模型依靠的是节律而不是 P 波形态。
分类器本身很一般。准确率 64%,macro F1 0.53,Normal 强、AFib 弱,这就是 10 比 1 的类别不平衡会带来的结果。这一点值得直说,因为真正有意思的结果在它下游。
发现
四十条解释被逐条人工标注,对照的是生成它们的那份证据。一条解释只有在既不与证据矛盾、也不添加证据里没有的内容时,才算「忠实」。
整体忠实率 72.5%。但按类别拆开,这个数字就散了。房颤解释的忠实率是 94%,Other 是 100%,而 Normal 只有 29%。

原因几乎有点好笑。在一条正常记录上,模型往往哪里都不特别关注,于是三个激活值全都很低。证据实际上什么都没说,而语言模型被要求去解释,就用听起来很合理、但毫无依据的临床描述把这段沉默填上了。它会自信地写「P 波、QRS 波群和 T 波都符合正常节律的预期」,而输入里根本没提过这些。
给语言模型一个空地,它会自己造一层地板出来。
修法
在 prompt 里加一条规则:当三个激活值都低于 0.3 时,只描述心率和节律是否规整,不要提任何波形形态。管线其他部分全部不动,把受影响的解释重新生成、按同一套标准重新标注。

那道差距从来不是模型问题,是 prompt 问题。而它之所以被看见,只是因为有人把每一条解释逐行对着证据核过。ROUGE 这类文本指标会给那个编造版本打出很不错的分数。
95% 还不够放到患者面前。二十条里仍然有一条包含没有依据的说法,而且一条解释可以完全忠实于模型的证据,同时底层的分类根本就是错的。诚实的总结是:把文字锚定在结构化证据上能补掉大部分差距,而剩下的那一小部分,才是真正的难处所在。