当领域词汇表新增 8000 个中文医学术语时,如何扩展 tokenizer 并保证嵌入层初始化?
解读
面试官想验证三件事:
- 你是否理解中文医学术语对原有 tokenizer 的“切分灾难”——即被拆成无意义单字或子词,导致语义漂移。
- 你是否掌握无痛扩展方案:不重新预训练,却能将新词整体纳入词汇表,并同步完成嵌入层形状变更与初始化。
- 你是否能在国内合规场景下,保证模型版本可追溯、服务可热更新、数据不出境。
回答时要体现“LLMOps 闭环”思维:从语料清洗、词频统计、tokenizer 重训、模型热插拔、到线上灰度回滚,每一步都要给出可落地脚本级细节。
知识点
- SentencePiece 中文医学语料二次训练:–input_sentence_size、–shuffle_input_sentence、–character_coverage=0.995,防止过度拆字。
- Tokenizer 合并策略:老 vocab 保留原始 id,新词追加到尾部,id 连续不跳号,避免下游 embedding 矩阵错位。
- Embedding 层形状扩展:
new_emb = torch.nn.Embedding(old_weight.size(0)+8000, hidden_size)
new_emb.weight.data[:old_weight.size(0)] = old_weight
新 8000 行用高斯初始化σ=1e-4,防止梯度爆炸。 - 国内合规细节:
- 训练语料必须脱敏,剔除患者隐私;
- 若使用境外开源词表,需做哈希校验保证未被投毒;
- 最终模型文件存于境内私有云 OSS,调用链路走VPC 内网。
- LLMOps 热更新:
- 使用TorchScript + Redis 配置中心,embedding 权重以safetensors格式分片存储;
- 上线采用影子流量双跑 24h,指标漂移>1% 自动回滚。
答案
步骤一:语料准备
从中国知网医学期刊、万方医学术语词典拉取近 3 年文献,经隐私脱敏脚本(正则剔除姓名、手机号、医院名)后得到 2.3 G 纯文本,用jieba 医学自定义词典预切分,统计 8000 个出现频次≥50 的术语作为新增词表。
步骤二:Tokenizer 重训
基于原模型目录下的tokenizer.model(SentencePiece),执行:
spm_train –input=new_corpus.txt –model_prefix=med –vocab_size=原vocab_size+8000 –character_coverage=0.995 –model_type=unigram –control_symbols=<pad>,<unk>,<cls>,<sep>,<mask>
得到med.model与med.vocab后,用官方脚本spiece_to_hf_tokenizer.py转成 HuggingFace 格式,保证token id 从 32000 开始连续追加。
步骤三:模型权重扩展
- 加载原 pytorch_model.bin,提取model.embed_tokens.weight与lm_head.weight;
- 新建 Embedding 层:
old_num, dim = embed_tokens.weight.shape
new_embed = nn.Embedding(old_num + 8000, dim, dtype=torch.float16)
new_embed.weight.data[:old_num] = embed_tokens.weight.data
new_embed.weight.data[old_num:] = torch.normal(0, 1e-4, size=(8000, dim), dtype=torch.float16) - 同步扩展lm_head( tied embedding 场景下共享权重,需同样追加 8000 行);
- 保存为model-00001-of-00002.safetensors,使用transformers.modeling_utils.load_sharded_checkpoint验证加载无报错。
步骤四:继续预训练 & 微调
采用LoRA + DeepSpeed Zero-2在8×A100 40G(境内阿里云 ecs.ebmgn7t 裸金属)继续预训练 2 个 epoch,lr=5e-5,warmup=3%,global_batch=256。训练脚本中加入token_loss_mask:对新 8000 个 token 的 loss 乘以 2.0,加速收敛。
步骤五:上线与监控
- 通过FlagAI-LLMOps平台打 Tag:v1.3.0-med-token-8k;
- 镜像推送到阿里云 ACR 华北 2 私有仓库,部署Triton Inference Server,开启decoupled mode;
- 线上灰度 5% 流量,核心指标:
- 医学术语整词召回率提升≥6%
- 首 token 延迟 P99 增加≤8 ms
- GPU 显存占用增加≤1.2 GB
连续 24h 未触发回滚阈值,则全量发布。
拓展思考
- 如果新增术语达到8 万规模,上述高斯初始化会导致语义空间稀释,可引入对比学习:把新词在医学语料中的上下文向量作为正样本,随机采样其他词做负样本,warmup 阶段用 InfoNCE loss 预对齐。
- 当业务要求多租户隔离(医院 A 与医院 B 术语冲突),可采用动态 vocab 路由:底层仍共享主模型,上层通过prefix token(如 <@A>、<@B>)把不同租户的新词映射到独立的 embedding shard,实现一份权重、多份视图,节省 30% 显存。
- 国内数据跨境监管趋严,若未来需引入海外医学文献,必须走数据出境安全评估。可在境内建立只读镜像,用差分隐私(ε=1.0)对词频加噪,再合并到 tokenizer 训练,既合规又不显著降低术语命中率。