使用BERT和GPT-2计算句子困惑度PPL

定义

BERT

一个使用bert计算ppl的github项目

how-do-i-use-bertformaskedlm-or-bertmodel-to-calculate-perplexity-of-a-sentence

Chinese-BERT-wwm

对于给定的sentence,按顺序依次mask掉一个token,并计算所预测单词的nll loss,将所有的token的loss求和再取平均,最后取以自然数为底的次方即为该句话的PPL。

测试写法:

import numpy as np
import torch
import torch.nn as nn
from transformers import BertTokenizer, BertForMaskedLM
# Load pre-trained model (weights)
with torch.no_grad():
    model = BertForMaskedLM.from_pretrained('hfl/chinese-bert-wwm-ext')
    model.eval()
    # Load pre-trained model tokenizer (vocabulary)
    tokenizer = BertTokenizer.from_pretrained('hfl/chinese-bert-wwm-ext')
    sentence = "我不会忘记和你一起奋斗的时光。"
    tokenize_input = tokenizer.tokenize(sentence)
    tensor_input = torch.tensor([tokenizer.convert_tokens_to_ids(tokenize_input)])
    sen_len = len(tokenize_input)
    sentence_loss = 0.

    for i, word in enumerate(tokenize_input):
        # add mask to i-th character of the sentence
        tokenize_input[i] = '[MASK]'
        mask_input = torch.tensor([tokenizer.convert_tokens_to_ids(tokenize_input)])

        output = model(mask_input)

        prediction_scores = output[0]
        softmax = nn.Softmax(dim=0)
        ps = softmax(prediction_scores[0, i]).log()
        word_loss = ps[tensor_input[0, i]]
        sentence_loss += word_loss.item()

        tokenize_input[i] = word
    ppl = np.exp(-sentence_loss/sen_len)
    print(ppl)

tensor思维的写法:

def score(model, tokenizer, sentence,  mask_token_id=103):
  tensor_input = tokenizer.encode(sentence, return_tensors='pt')
  repeat_input = tensor_input.repeat(tensor_input.size(-1)-2, 1)
  mask = torch.ones(tensor_input.size(-1) - 1).diag(1)[:-2]
  masked_input = repeat_input.masked_fill(mask == 1, 103)
  labels = repeat_input.masked_fill( masked_input != 103, -100)
  loss,_ = model(masked_input, masked_lm_labels=labels)
  result = np.exp(loss.item())
  return result

s = score(model, tokenizer, '我不会忘记和你一起奋斗的时光。')
print(s)

GPT-2

GPT2-Chinese

官方的gpt-2不支持中文,且是BPE分词方式。对于中文,有NLPer训练出了中文的gpt-2模型,且分词采用的是bert tokenizer的分词方式。

对于给定的sentence,若其长度为n,首先将其向左偏移一位作为label,将其去除末位作为input,将gpt-2的输出与label求cross entroy loss,再求以自然数为底的次方即为该句话的PPL。

import torch
from transformers import BertTokenizer, GPT2LMHeadModel
from torch.nn import CrossEntropyLoss


def cal_ppl_bygpt2():
    sens = ["今天是个好日子。", "天今子日。个是好", "这个婴儿有900000克呢。", "我不会忘记和你一起奋斗的时光。",
            "我不会记忘和你一起奋斗的时光。", "会我记忘和你斗起一奋的时光。"]
    tokenizer = BertTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
    model = GPT2LMHeadModel.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
    inputs = tokenizer(sens, padding='max_length', max_length=50, truncation=True, return_tensors="pt")
    bs, sl = inputs['input_ids'].size()
    outputs = model(**inputs, labels=inputs['input_ids'])
    logits = outputs[1]
    # Shift so that tokens < n predict n
    shift_logits = logits[:, :-1, :].contiguous()
    shift_labels = inputs['input_ids'][:, 1:].contiguous()
    shift_attentions = inputs['attention_mask'][:, 1:].contiguous()
    # Flatten the tokens
    loss_fct = CrossEntropyLoss(ignore_index=0, reduction="none")
    loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)).detach().reshape(bs, -1)
    meanloss = loss.sum(1) / shift_attentions.sum(1)
    ppl = torch.exp(meanloss).numpy().tolist()
    return ppl


if __name__ == '__main__':
    cal_ppl_bygpt2()
<think>嗯,用户问的是领域微调基座模型选择,我需要先理解这个问题。领域微调应该是指在特定领域上对预训练好的基座模型进行微调,比如医疗、法律或者金融这些领域。基座模型可能指的是像BERTGPT这类大型预训练模型。用户可能想知道如何选择合适的基座模型来进行微调,以提升在特定领域的表现。 首先,我需要回忆一下领域微调的基本概念。微调(Fine-tuning)是指在一个预训练好的模型基础上,用特定领域的数据继续训练,使模型适应这个领域的任务。基座模型的选择很重要,因为不同的模型架构预训练数据会影响微调的效果。 接下来要考虑用户可能的背景。用户可能是开发者或者研究人员,想要在自己的项目中应用模型,但不确定该选哪个基座模型。他们可能关心模型的大小、计算资源、数据量、领域适配性等因素。比如,如果数据量小,可能需要较小的模型;如果领域专业性强,可能需要选择在该领域有预训练的模型。 然后需要整理影响选择的因素。比如任务类型(文本分类、生成等)、领域相关性、模型规模、计算资源、数据量、微调策略等。每个因素都需要详细说明,比如任务类型不同,可能选择的模型结构也不同,像生成任务可能用GPT,而分类任务可能用BERT。 还需要介绍常见的基座模型,比如BERT、RoBERTa、GPT系列、T5等,以及它们的适用场景。比如BERT适合NLU任务,GPT适合生成任务,T5是文本到文本的框架。另外,像领域特定的预训练模型,如BioBERT用于生物医学,LegalBERT用于法律,这些可能更适合对应领域的微调。 然后要考虑模型规模计算资源之间的平衡。大模型效果可能更好,但需要更多计算资源,部署成本高。这时候可能需要权衡,选择适合自己资源的模型。 数据量也是一个关键点。如果领域数据充足,可能微调更大的模型更好;如果数据少,可能需要小模型或者采用数据增强、迁移学习等方法。 微调策略方面,除了全参数微调,还有参数高效微调方法,比如Adapter、LoRA等,这些可能帮助在资源有限的情况下进行微调,同时保持模型性能。 最后需要给出步骤建议,比如明确需求、评估资源、筛选模型、试验验证、持续优化等。可能还要提醒用户注意预训练数据的领域覆盖情况,以及模型的可解释性部署需求。 需要确保回答结构清晰,分点说明,帮助用户一步步理清思路。同时要检查是否有遗漏的重要因素,比如多语言支持、模型的开源许可等可能也是用户需要考虑的。 还要注意使用正确的中文术语,比如“微调”、“预训练模型”、“领域适配”等,避免专业术语错误。同时保持语言口语化,让用户容易理解。</think>领域微调(Domain Fine-tuning)是提升基座模型在特定领域表现的核心方法。以下是选择基座模型的系统化思考框架关键步骤: --- ### 一、核心选择维 1. **任务匹配性** - **文本理解任务**(如分类、实体识别):优先选择编码器架构(如BERT、RoBERTa) - **生成任务**(如文本生成、对话):解码器架构(如GPT系列、LLaMA)或编解码架构(如T5)更优 $$ \text{模型适用性} = f(\text{架构特性}, \text{任务需求}) $$ 2. **领域相关性** - 检查预训练语料组成(如GPT-3包含书籍、网页等通用语料) - 优先选择有领域预训练的变体(例如: - 生物医学:BioBERT ($\text{PubMed+PMC}$语料) - 法律:Legal-BERT ($\text{法院文书+法律条文}$) - 金融:FinBERT ($\text{财经新闻+财报}$)) 3. **规模权衡** | 模型参数 | 适用场景 | 硬件需求 | |---|---|---| | <3B | 快速迭代/有限算力 | 单GPU可训练 | | 7B-13B | 平衡性能与成本 | 多GPU并行 | | >20B | 数据充足/追求SOTA | TPU集群 | --- ### 二、关键评估指标 1. **领域困惑PPL)** 在领域验证集上测试未微调模型的困惑,反映原始知识覆盖: $$ PPL = \exp\left(-\frac{1}{N}\sum_{i=1}^N \log p(w_i|w_{<i})\right) $$ 2. **迁移学习效率** 通过小样本实验(如5%领域数据)观察: - 损失下降速 - 验证集准确率提升斜率 3. **领域词表覆盖** 统计领域专业术语在模型tokenizer中的未登录词(OOV)比例: $$ \text{OOV\%} = \frac{\text{领域术语未匹配数}}{\text{总术语数}} \times 100 $$ --- ### 三、典型优化路径 ```mermaid graph LR A[原始基座模型] --> B{领域适配分析} B -->|高OOV| C[增量预训练] B -->|低PPL| D[直接微调] C --> E[动态词表扩展] D --> F[参数高效微调] E --> G[领域适配模型] F --> G ``` 1. **增量预训练** - 适用场景:领域术语密 > 15% - 训练策略: - 80%掩码语言建模(MLM) - 20%领域特定目标(如医学实体预测) 2. **参数高效微调** - LoRA(Low-Rank Adaptation): $$ W' = W + \Delta W = W + BA^T $$ 其中 $B \in \mathbb{R}^{d \times r}$, $A \in \mathbb{R}^{r \times k}$,秩 $r \ll d$ - 内存消耗降低60-70%,适合7B以上模型 --- ### 四、实践建议 1. **资源受限时**:选择领域相近的小模型(如Legal-BERT-base) 2. **数据充足时**:采用LLaMA-2 13B + LoRA微调 3. **专业领域**:组合使用检索增强(RAG)+ 微调模型 **典型案例**: 某金融公司微调流程: 1. 测试GPT-3/ChatGLM-6B/BLOOM的PPL 2. 选择PPL最低的ChatGLM-6B 3. 采用QLoRA(4bit量化)在3090显卡微调 4. 最终领域任务准确率提升27.6% --- ### 五、风险控制 1. **领域漂移检测**:监控微调后模型在通用任务的表现 2. **灾难性遗忘**:采用弹性权重固化(EWC)正则化 $$ \mathcal{L} = \mathcal{L}_{\text{task}} + \lambda \sum_i F_i (\theta_i - \theta_{0,i})^2 $$ ($F_i$为Fisher信息矩阵) 选择基座模型需要综合评估领域特性、计算资源业务需求,建议通过控制变量法进行AB测试验证。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值