笔者近期针对门诊患者的心理量化特征(焦虑/抑郁指数)展开了一系列研究,并推进了基于 AI 驱动的门诊病患焦虑抑郁识别工作。本文是该系列研究的基座篇——数据构建与预处理管线(Data Pipeline)设计。 笔者首先与医学同学们完成了原始的医疗场景语音数据采集与 TTS(语音转文字)工作。数据池包含了 133 份门诊场景下患者与医生的对话转录文本(涵盖初诊与复诊),以及每位患者在门诊后填写的 PHQ-9(抑郁)和 GAD-7(焦虑)心理量表。至此,我们获得了医患对话的原始文本对应的心理指标对照组

在深度学习(尤其是大模型)普及之前,特征工程是 NLP 任务的核心。即使在今天,在处理特定垂直领域数据或使用轻量化机器学习模型(如 SVM、XGBoost)时,特征工程依然至关重要,更何况在我们的研究场景下特征工程其实。我们的愿景是构建一套高精度、多维度的自然语言数据集。这套数据集不仅是对门诊对话的简单记录,更是要通过特征工程,将非结构化的医患互动转化为可计算、可感知的“数字心理表型“。

然而在 NLP 与医疗大模型的交叉领域,真实的门诊对话数据是极具价值的“富矿”。然而,现实中的门诊录音转写文本往往是极其非结构化、充满噪音且缺乏语境的。

在进入深度的特征挖掘(Feature Mining)之前,特征工程的第一步,也是最重要的一步,是数据清洗、多源对齐与结构化重塑。本文将详细记录我是如何将零散的“门诊对话文本”与“心理量表表格”,加工成符合大模型训练与纵向特征追踪的高质量结构化数据集的。

1. 有参考性的开源数据集与工业标准

门诊对话数据集和心理数据集早有相应的成熟范例,然而医疗门诊对话数据集却没有相关资料,这暗示我参考现有的开源数据集和工业标准制订相关的。在设计自己的数据集架构前,我参考业内权威的数据集标准,以保证未来管线的可扩展性与兼容性。

1.1 全球心理健康计算权威:DAIC-WOZ (The Distress Analysis Interview Corpus)

DAIC-WOZ 是用于抑郁症检测的标杆数据集,它具有分离式存储架构:采用了“元数据表 + 原始记录”分离的方式。train_split.csv 仅存储病人 ID 和 PHQ-8 总分(Label);而另一个独立文件夹存放具体的对话转录(Transcript)。这为我们处理 .csv 量表与 .txt 文本的对齐提供了标准范式。值得注意的是其 Transcript 文件严格保留了 start_timeend_time 字段,这种时间戳的标注为未来的多模态(音频特征)分析留下了切入口。

  • 格式:“元数据表 + 原始记录”分离**的存储方式。
  • 样例
    • CSV 表 (train_split.csv):只存 ID 和 标签(PHQ-8分数)。
        Participant_ID, PHQ8_Binary, PHQ8_Score, Gender
        303, 0, 0, 0
        304, 0, 6, 0
    
    • Transcript 文件 (303_TRANSCRIPT.csv):存具体对话,带有详细的时间戳。
        start_time, stop_time, speaker, value
        10.5, 12.1, Ellie, How are you doing today?
        12.5, 14.2, Participant, I am doing good.
    
  • 借鉴意义: .xlsx 和 .txt 分离存储完全符合这一标准。在论文中可以写:“Followed the data organization structure of the DAIC-WOZ corpus.”

1.2 中文医疗标准:IMCS-21 (Intelligent Medical Consultation System)

IMCS-21 是目前国内医疗对话理解领域的基准数据集(Benchmark),被广泛应用于国内顶尖科研机构及大模型医疗微调的评测中。该数据集已在 GitHub 完全开源,具有行业参考价值。

  • 特点:高度结构化的实体标注(NER)。它不仅有对话,还标注了这句话是在谈论“症状”、“药物”还是“检查”。 IMCS-21 带来的最大启发在于其高度结构化的字段定义。在我们的数据管线构建初期,即使当前阶段尚未引入自动化的实体提取工具,也应当参考其规范,在 JSON 架构中预留出 diagnosis(诊断结果)、symptoms(症状列表)、medication(用药建议)等关键字段,即使现在是空的,也有可能等未来管线自动化提取时填入,确保数据集的向前兼容性。

1.3 大模型微调标准:OpenAI Chat Format / ShareGPT格式

这是目前训练 Llama 3, Qwen, ChatGLM 等大模型最通用的格式。将所有对话转化为 messages 列表,包含 role 和 content,如果把数据整理成这个格式,未来不需要任何转换就能直接拿来微调大模型。
{ "conversations": [ {"from": "human", "value": "医生,我最近总是失眠。"}, {"from": "gpt", "value": "这种情况持续多久了?"}, {"from": "human", "value": "大概两周了。"} ], "system": "你是一个专业的心理医生。" } 这是目前工业界微调模型最通用的接口。把数据做成这样,兼容性最强。然而这可能与保留我们的保留原有的医患对话数据集的初衷背离。

2. 数据清洗

数据脱敏

在医疗数据处理中,隐私保护是不可逾越的底线,我引入了基于深度学习的命名实体识别(NER)方案:roberta-base-finetuned-cluener2020-chinese是HuggingFace上的较为出名的简体中文命名体识别模型,模型基于 RoBERTa 中文预训练模型,并在 CLUENER2020 数据集上进行微调。CLUENER2020 是一个细粒度的中文命名实体识别数据集。

接着我使用roberta-base-finetuned-cluener2020-chinese模型进行脱敏,通过 transformers 库加载模型,我们在数据脱敏阶段,精准提取并遮蔽了所有真实人名(替换为 [NAME])与医疗机构名(替换为 [ORG]),满足数据最小化与隐私保护的伦理标准。

说话人标注

在早期 TTS 工作中,由于缺乏统一的 SOP,原始数据的角色标注出现了严重的异构问题:有一位同学的文本目前基本是“纯对话句子逐行”,文本没有身份标签;至于另一位同学,虽然进行了身份的标注工作,但是却也有两套标注风格并存,部分使用了中文标记(如 医生/患者/家属);还有部分混用了半角英文标记(如 【D】/【P】)。 我的目标是将所有说话人统一清洗为干净的 [医生]:[患者]:[患者家属]: 的非常干净形式,对此我的解决方案是:

  • 启发式规则处理:针对已有显式标记的文本(50 份),编写 Python 正则脚本进行规则匹配与强制替换。
  • 大模型辅助划分:针对完全没有说话人标签的纯对话句子(34 份),利用大模型的语境理解能力进行自动化 Speaker 推断与回填。

3. 数据分析

3.1 数据面貌

经过几重处理后,我们现有的数据基本符合进行大规模批处理的前提。我们拿到手的数据属于典型的多源异构数据:

  1. 量表数据 (.csv): 包含每位患者的编号、年龄、性别以及 GAD-7(焦虑)和 PHQ-9(抑郁)的具体量表得分。

  2. 对话文本 (.txt): 门诊录音转录文本,文件命名极其不规则,且包含了多轮、多次的门诊对话。

3.2 目标结构设计

为了便于后续提取时序特征和角色特征,笔者采用“以患者为中心(Patient-Centered)”的树状 JSON 架构。 这种设计不仅能绑定静态特征(量表评分),还能将动态特征(多次就诊的对话)按时间线串联:

  • Patient (根节点) -> 包含基础画像(年龄、性别)与心理量表评分。

    • Visits (子节点) -> 记录纵向的多次就诊记录。

      • Dialogue (叶节点) -> 包含清洗后的逐句(Turn-level)对话,并打上规范化的角色标签。

4. 核心处理管线

基于上述目标设计了批量转换管线:

Step 1: 多源数据对齐与元数据提取

原始文本文件名极度随意(如 101[NAME] 男 58岁.txt102,103[NAME] 女 4岁.txt)。

  • 匹配逻辑:通过正则表达式提取文件名前缀数字作为 Patient_ID,将其与量表 CSV 文件中的序号进行关联匹配,生成 GAD-7.totalPHQ-9.total 节点。

  • 属性提取:通过后缀规则优先提取性别、年龄等元数据(Metadata)写入 JSON 根节点。此外,扫描文本首部,若存在“关键词”段落,则提取为症状标签特征。

Step 2: 纵向会话切片

原始文本将患者当天的初诊、复诊混杂在同一个 TXT 中。为了保留时间层次感,系统会识别单行孤立的 [(...)]OUT出去 等环境音/动作标记符,将其作为特殊分隔符(Delimiter),自动将长文本切分为独立的 Visit 单元。

Step 3: 角色推断与话轮提取

将单次 Visit 下的文本按行解析为 Turns 列表。在这里加入了一个关键的医疗业务逻辑:儿童与成人患者的角色推断差异

Python

# 角色映射的核心业务逻辑伪代码
if is_pediatric(age):
    # 若为儿童,对话中的“患者”通常指代代为诉说的家属
    if raw_role in ["患者", "患者家属", "P"]:
        return "caregiver"
else:
    # 若为成人,区分患者本人与陪同家属
    if raw_role in ["患者", "P"]:
        return "patient"
    elif raw_role == "患者家属":
        return "caregiver"

5. 最终的结构化输出成果

经过以上 ETL(Extract, Transform, Load)流程,原本混乱不堪的文件目录,最终被炼化为了如下高信息密度的 JSON 结构:

{
  "patients": [
    {
      "patient_id": "P-000102",
      "name": "[NAME]",
      "gender": "女",
      "age": 4,
      "scales": [
        {
          "GAD-7": {"total": 14},
          "PHQ-9": {"total": 17}
        }
      ],
      "visits": [
        {
          "visit_id": "V-000102-1",
          "dialogue": {
            "source_file": "102,103[NAME] 女 4岁.txt",
            "turns": [
              {"role": "doctor", "text": "你好久等[NAME]。"},
              {"role": "caregiver", "text": "你好,他看那个腺样体"}
            ]
          }
        },
        {
          "visit_id": "V-000102-2",
          "dialogue": { ... }
        }
      ]
    }
  ]
}

伦理声明: 本数据集使用roberta-base-finetuned-cluener2020-chinese模型对于人名和组织进行脱敏,完成身份脱敏,删除所有可直接识别个人的信息(PII),姓名、身份证号、精确联系方式等,处理可能推断出身份的独特病史或社会关系;满足最小化原则, 仅收集研究所必需的数据。满足知情同意,数据采集获得了患者或其监护人的明确同意,并告知数据用途。符合国际和国内(如《个人信息保护法》、HIPAA 或 GDPR)的医疗数据研究伦理标准。

4. 总结

在复杂对话场景的 AI 研究中,“数据结构即特征”。 我们成功解决了异构数据对齐、多轮复诊切分、角色身份规范化以及隐私脱敏四大问题。这一干净、结构化的基座,为下一步开展基于深度学习的情感计算(VADER)、人格特征提取(Personality)、语言探究与词数统计(LIWC-CH)以及最终的焦虑抑郁风险预测模型,铺平了坚实的道路。