大模型词表注入

大模型词表注入(Vocabulary Injection)

大模型词表注入(Vocabulary Injection)是指在预训练语言模型(如GPT、LLAMA等)的基础上,动态扩展其词表(Vocabulary)的技术,以适应特定任务或领域的需求。

一、词表注入的「原理」

  1. 词表结构与嵌入层调整
    • 大模型的词表通常由子词(subword)或词片(token)组成(如BPE、WordPiece算法生成),每个词对应一个嵌入向量(Embedding Vector)。
    • 注入新词时,需要扩展模型的嵌入矩阵(Embedding Matrix),新增词对应的向量,并调整模型输入层(Embedding Layer)和输出层(如LM Head)的维度。
  2. 新词向量的初始化
    • 直接随机初始化新词的嵌入向量可能导致训练不稳定。常见策略是:
      • 复用相似词向量:例如,将新词"LLM"初始化为"language"和"model"的平均向量。
      • 对齐预训练语义空间:通过外部词向量(如Word2Vec)映射到模型的嵌入空间。
  3. 参数适配与微调
    • 注入新词后,通常需要在小规模领域数据上对模型进行微调(Fine-tuning),使新词的嵌入向量与原有参数协同工作。
    • 某些方法(如[《Extending Pre-trained Models with Domain-Specific Vocabulary》](https://arxiv.org/abs/2104.08646))会冻结部分参数,仅训练新词相关部分以减少计算量。

二、词表注入的「原因」

  1. 解决未登录词(OOV)问题
    • 预训练模型的词表固定,无法覆盖领域专有名词(如医学术语“EGFR”)、新造词(如网络流行语“栓Q”)或多语言词汇。
  2. 提升领域任务性能
    • 在特定领域(法律、医疗、金融)中,直接使用原始词表可能导致文本被过度切分为子词,丢失语义信息。注入领域词表可保留关键术语的完整性。
  3. 多语言扩展需求
    • 为支持新语言,需注入该语言的词汇(如中文字符、俄文字母),同时调整模型处理多语言的能力。
  4. 避免全模型重训练
    • 从头预训练大模型成本极高,词表注入允许在原有模型基础上低成本扩展,节省计算资源和时间。

三、技术挑战与解决方案

  1. 嵌入空间对齐
    • 问题:新词向量可能破坏原有语义空间的一致性。
    • 方案:使用对比学习(Contrastive Learning)或跨词注意力(Cross-token Attention)对齐新旧词向量。
  2. 模型结构限制
    • 问题:Transformer的参数量与词表大小相关,盲目扩展词表会显著增加模型体积。
    • 方案:动态词表(Dynamic Vocabulary)、参数共享(如ALBERT的跨层参数共享)。
  3. 训练数据偏差
    • 问题:注入新词后,若微调数据不足,模型可能过拟合或遗忘原有知识。
    • 方案:渐进式训练(Progressive Training)或知识蒸馏(Knowledge Distillation)。

四、典型应用场景

  1. 领域适配
    • 例如,向BERT注入法律术语后,在合同解析任务中表现更佳。
  2. 多语言模型扩展
    • 如为英文训练的GPT-2注入中文词表,支持中英混合生成。
  3. 实时更新
    • 快速响应新事件(如疫情术语“奥密克戎”)或网络热词。

五、代码及微调实验

有两种方法:1.词表注入;2.词表训练–>添加词表

  • 导入原始大模型及tokenier
tokenizer = AutoTokenizer.from_pretrained(
    model_path,
    trust_remote_code=True,
    use_fast=False if model_arch == 'llama' else True
)

model = AutoModel.from_pretrained(
    model_path,
    trust_remote_code=True,
    torch_dtype=torch_dtype
)
  • 词表注入
all_words = []
with open(file, 'r', encoding='utf-8') as f:
    lines = f.readlines()
words = [line.strip() for line in lines]
all_words.extend(words)
tokenizer.add_tokens(all_words)
tokenizer.save_pretrained(save_path)
  • 词表训练

使用sentencepiece==4.1.0 训练词表

sp.SentencePieceTrainer.train(
    # 只支持 txt 和 tsv 格式
    input=corpus,
    # 保存的模型前缀名
    model_prefix='bpe_expand',
    # 词表大小
    vocab_size=vocab_size,
    # 指定模型的字符覆盖率, 中文日文等推荐为 0.9995, 其余可以尝试 1.0
    character_coverage=character_coverage,
    # 分词算法
    model_type='bpe',
    # 是否将数字划分为单个 token, 在 llama 中是这么做的
    split_digits=True if model_arch == 'llama' else False,
    # 指定在遇到未知或很少的字符时将其分解为 UTF-8 字节, 开启后等效于 bbpe
    byte_fallback=True,
    # 指定输入句子的最大长度,以字节为单位
    max_sentence_length=max_sentence_length

参数说明:

参数重要性推荐场景
input必填所有场景
model_prefix必填所有场景
model_type根据需求选择 unigrambpe
vocab_size通常设为 3200050000 或更高
character_coverage多语言数据设为 0.9995,单语言数据默认 1.0
byte_fallback处理未知字符时设为 True
max_sentence_length处理长文本时需调大(如 16384
split_digits需区分数字时设为 True
  • 添加词表

    词表训练之后需要添加词表,并保存:

    #1.加载bpe model
    sp_bpe = sp.SentencePieceProcessor()
    sp_bpe.load(bpe_model)
    #2.处理词汇
    raw_vocab = [sp_bpe.id_to_piece(id) for id in range(sp_bpe.get_piece_size())]
    clean_vocab = list(set(filter(is_chinese, raw_vocab)))
    #添加词汇并保存zz
    tokenizer.add_tokens(clean_vocab)
    tokenizer.save_pretrained(save_path)
    
  • 维度更新

经过词表注入或者词表训练,两种方法其中之一之后,更新模型的维度参数:

model.resize_token_embeddings(new_length)#new_length 为新词表的词汇量
model.save_pretrained(save_path)
微调对比实验(待补充)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值