大模型的预训练:给大模型注入先验知识

自回归语大模型的预训练

一、什么是预训练

大模型预训练是指在大规模的无标注文本数据上,通过无监督学习的方式对模型进行初步训练,让模型学习语言的基本规律、模式和结构,从而为后续的特定任务微调打下基础。例如,像GPT(生成式预训练模型)系列模型,会在海量的文本数据上进行预训练,这些文本数据可以包括书籍、网页文章、新闻报道等多种来源的内容。

预训练的主要目的

  • 学习语言知识:语言是非常复杂的,包含词汇的语义、语法结构、语用规则等诸多要素。通过预训练,模型可以学习到单词之间的关系,比如同义词、反义词、上下位词等,还能掌握句子的语法结构,像主谓宾的搭配、定状补的使用等。例如,模型在预训练过程中会逐渐明白“狗”和“犬”是同义词,“大”和“小”是反义词,以及“我吃饭”这种主谓宾结构是符合语法的。
  • 捕捉语言的模式和规律:语言中存在很多模式,比如某些词汇组合经常一起出现,某些句式结构在特定语境下频繁使用。预训练模型能够捕捉到这些模式和规律,从而更好地理解和生成语言。比如,在新闻报道中,“据报道”“据消息人士透露”等短语经常出现在文章开头,模型通过预训练就能学习到这种模式,在生成新闻类文本时可能会更自然地使用类似的表达。
  • 为下游任务提供通用语言能力:不同的自然语言处理任务,如文本分类、情感分析、机器翻译、问答系统等,都需要模型具备一定的语言理解能力。预训练模型通过学习语言的通用知识,能够为这些下游任务提供一个良好的起点,使得模型在后续针对具体任务进行微调时能够更高效地适应任务需求,提高任务的性能。

常见的预训练方法

  • 语言模型预训练:这是最常见的一种预训练方法,模型的任务是根据已有的文本序列预测下一个词或下一个词的概率分布。例如,给定文本“我今天去”,模型需要预测下一个词可能是“公园”“学校”“上班”等,通过这种方式,模型能够学习到词汇之间的先后顺序关系和上下文语义关联。像GPT系列模型就是基于语言模型预训练的,它们通过大量的文本数据训练,能够生成连贯、符合语言习惯的文本。
  • 掩码语言模型预训练:这种方法是在输入文本中随机掩盖一些词,然后让模型预测被掩盖的词是什么。以BERT(Bidirectional Encoder Representations from Transformers)模型为例,它采用掩码语言模型预训练。假设输入文本是“我今天去图书馆看书”,模型可能会随机掩盖“图书馆”这个词,变成“我今天去[掩码]看书”,然后模型需要根据上下文“我今天去”和“看书”来预测“[掩码]”处应该是“图书馆”。这种方式能够让模型更好地学习上下文信息,因为它需要同时考虑掩盖词前后的语义来做出准确预测。
  • 自回归语言模型预训练:自回归语言模型是一种生成式模型,它在生成文本时是逐词生成的,每次生成一个词后,将这个词作为上下文的一部分,用于生成下一个词。例如,生成第一句话“春天来了”,模型会先生成“春”这个词,然后以“春”为上下文生成“天”,再以“春天”为上下文生成“来”,最后以“春天来”为上下文生成“了”。这种预训练方法能够很好地捕捉文本生成过程中的顺序性和依赖关系,像GPT系列模型就属于自回归语言模型。

预训练数据的特点

  • 规模大:预训练需要大量的文本数据来让模型充分学习语言的各种情况。通常数据量会达到数十亿甚至上百亿词级别。例如,一些大型语言模型会使用互联网上的海量文本数据,包括维基百科、新闻网站、小说网站等来源的内容,这样庞大的数据量能够涵盖各种不同的语言风格、主题和领域,使模型具备更广泛的语言知识。
  • 多样性:数据来源广泛,涵盖多种语言风格和主题领域。除了前面提到的维基百科、新闻等,还可能包括社交媒体文本、学术论文、专业领域文档等。社交媒体文本语言风格比较口语化、随意,可能包含一些网络流行语和缩写;而学术论文语言则比较正式、严谨,专业术语较多。模型通过接触这些不同风格和领域的数据,能够更好地适应各种语言环境和任务需求。
  • 无标注:预训练阶段的数据一般是不需要人工标注的,因为主要是让模型学习语言本身的规律,而不是去学习特定的任务标签。这样可以节省大量的人工标注成本,而且能够充分利用海量的无标注文本资源。

预训练模型的架构

  • Transformer架构:目前大多数大模型都采用Transformer架构或其变体。Transformer架构的核心是自注意力机制(Self-Attention),它能够让模型在处理文本时,充分考虑文本中各个词之间的相互关系,而不仅仅是相邻词的关系。例如,在句子“我喜欢吃水果,尤其是苹果”中,自注意力机制可以让模型在处理“苹果”这个词时,同时关注到“水果”这个词,因为它们之间存在语义关联。这种架构使得模型能够更好地捕捉长距离的依赖关系,对于理解复杂的语言结构非常有帮助。
  • 编码器 - 解码器架构:一些用于机器翻译、文本生成等任务的预训练模型会采用编码器 - 解码器架构。编码器负责将输入文本编码成一个语义表示,解码器则根据这个语义表示生成目标文本。例如,在机器翻译中,编码器将中文句子编码,解码器将其翻译成英文句子。这种架构能够很好地处理不同语言之间的转换和生成任务。

预训练模型的应用

  • 自然语言理解任务:像情感分析,模型可以判断一段文本是积极的、消极的还是中性的。例如,对于一条产品评论“这个手机的拍照效果太棒了”,经过预训练并微调后的模型能够理解这是积极的评价。在文本分类任务中,比如将新闻文章分类为体育、财经、娱乐等类别,预训练模型通过学习语言的语义特征,能够更准确地判断文章的主题。
  • 自然语言生成任务:包括文本生成、机器翻译、问答系统等。在文本生成方面,可以根据用户给定的提示生成故事、文章、诗歌等。例如,给模型提示“在一个阳光明媚的早晨”,模型可以生成一段描述早晨美好景象的文本。在机器翻译中,能够将一种语言的文本准确翻译成另一种语言,像把英文翻译成中文。在问答系统中,根据用户的问题生成准确的答案,比如用户问“北京的故宫是什么时候建立的”,模型可以回答出具体的时间。
  • 多模态任务:一些预训练模型还能够结合文本和其他模态信息,如图像、语音等。例如,在图文问答任务中,模型可以根据图像和问题生成答案。比如,给模型一张有动物的图片和问题“这是一只什么动物”,模型可以结合图像内容和语言知识回答出动物的名称。

二、预训练的两种情况

  • 1.从零开始的预训练: 训练开始时模型所有的参数都是随机初始化的,需要通过反向传播来更新参数。这种训练方式需要大量的计算资源,并且需要大量的训练数据。
  • 2.在开源已经预训练号的大模型的基础上进行对特定的行业、知识进行预训练(加强训练): 可以增强模型对特定领域上的知识和能力。这是我们更常见到的。

三、自回归语言大模型的预训练的input和label

在自回归语言建模(Autoregressive Language Modeling)中,模型的输入(input)和标签(label)是紧密相关的,它们共同用于训练模型以预测下一个词或字符。以下是详细的解释:

输入(Input)

输入是模型用来预测下一个词的上下文信息。在自回归语言建模中,输入通常是一个文本序列,其中每个词或字符都是之前已经生成或已知的部分。

具体形式:
  • 输入序列:假设有一个文本序列 x 1 , x 2 , … , x T x_1, x_2, \dots, x_T x1,x2,,xT,输入序列通常是这个序列的前缀部分。例如,对于预测第 t t t 个词 x t x_t xt,输入序列是 [ x 1 , x 2 , … , x t − 1 ] [x_1, x_2, \dots, x_{t-1}] [x1,x2,,xt1]
  • 嵌入表示:在模型中,输入序列会被转换为嵌入向量(embedding vectors)。每个词或字符 x i x_i xi 会被映射到一个固定维度的向量 e i \mathbf{e}_i ei。这些嵌入向量会作为模型的输入,经过多层Transformer架构处理。

标签(Label)

标签是模型需要预测的目标值。在自回归语言建模中,标签是输入序列的下一个词或字符。

具体形式:
  • 目标序列:对于输入序列 [ x 1 , x 2 , … , x t − 1 ] [x_1, x_2, \dots, x_{t-1}] [x1,x2,,xt1],目标(标签)是序列中的下一个词 x t x_t xt
  • 训练目标:模型的目标是学习如何根据输入序列 [ x 1 , x 2 , … , x t − 1 ] [x_1, x_2, \dots, x_{t-1}] [x1,x2,,xt1] 准确地预测出下一个词 x t x_t xt 的概率分布 P ( x t ∣ x 1 , x 2 , … , x t − 1 ) P(x_t | x_1, x_2, \dots, x_{t-1}) P(xtx1,x2,,xt1)

示例

假设我们有一个文本序列:

"自然语言处理是人工智能的一个重要分支"

我们将这个序列分割成长度为4的子序列进行训练。

输入和标签的对应关系:
  • 输入序列["自然", "语言", "处理"]
    • 标签"是"
  • 输入序列["语言", "处理", "是"]
    • 标签"人工智能"
  • 输入序列["处理", "是", "人工智能"]
    • 标签"的一个"
  • 输入序列["是", "人工智能", "的一个"]
    • 标签"重要分支"

训练过程中的输入和标签

在训练过程中,模型会接收输入序列,并通过前向传播计算每个位置的预测概率分布。然后,模型会将预测的概率分布与真实标签进行比较,计算损失函数(如交叉熵损失),并更新模型参数以最小化损失。

具体步骤
  1. 前向传播

    • 输入嵌入:将输入序列 [ x 1 , x 2 , … , x t − 1 ] [x_1, x_2, \dots, x_{t-1}] [x1,x2,,xt1] 转换为嵌入向量。
    • 自注意力机制:通过自注意力机制计算每个词的上下文表示。
    • 前馈网络:对上下文表示进行非线性变换。
    • 输出层:输出每个词的预测概率分布 P ( x t ∣ x 1 , x 2 , … , x t − 1 ) P(x_t | x_1, x_2, \dots, x_{t-1}) P(xtx1,x2,,xt1)
  2. 损失计算

    • 计算预测概率分布 P ( x t ∣ x 1 , x 2 , … , x t − 1 ) P(x_t | x_1, x_2, \dots, x_{t-1}) P(xtx1,x2,,xt1) 与真实标签 x t x_t xt 之间的交叉熵损失:
      L = − ∑ t = 1 T log ⁡ P ( x t ∣ x 1 , x 2 , … , x t − 1 ) \mathcal{L} = -\sum_{t=1}^{T} \log P(x_t | x_1, x_2, \dots, x_{t-1}) L=t=1TlogP(xtx1,x2,,xt1)

每一次计算和下一个字的LOSS,然后通过反向传播更新模型参数,当到达最后一个字预测完成后,由于我们也不知道下一个字是什么,所以会放弃下一个字的loss计算

  1. 反向传播
    • 通过反向传播更新模型参数,最小化损失函数。
  • 输入(Input):是模型用来预测下一个词的上下文序列,通常是已知的前缀部分。
  • 标签(Label):是模型需要预测的目标词或字符,即输入序列的下一个词。

通过这种方式,自回归语言模型能够逐步学习语言的结构和规律,并生成自然流畅的文本。

预训练的代码

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
from peft import TaskType, LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, LlamaConfig, LlamaForCausalLM,LlamaModel
import torch

model_path = '/data04/llama3/Meta-Llama-3.1-8B-Instruct'
tokenizer = AutoTokenizer.from_pretrained(model_path)

# # 1.从零开始训练大模型
# config = LlamaConfig() # 创建一个默认的Llama config
# config.num_hidden_layers = 12 # 配置网络结构
# config.hidden_size = 1024
# config.intermediate_size = 4096
# config.num_key_value_heads = 8
# # 用配置文件初始化一个大模型
# model = LlamaForCausalLM(config)

# 2.加载一个预训练的大模型

# # 4bit load
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    low_cpu_mem_usage=True,
    quantization_config=bnb_config
)

# 构造Lora模型
peft_config = LoraConfig(
        r=8,
        target_modules=["q_proj",
                        "v_proj",
                        "k_proj",
                        "o_proj",
                        "gate_proj",
                        "down_proj",
                        "up_proj"
                        ],
        task_type=TaskType.CAUSAL_LM,
        lora_alpha=16,
        lora_dropout=0.05
    )
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()

model.to("cuda")
optimizer = torch.optim.AdamW(model.parameters())

text = "今天天气不错。"
input = tokenizer(text, return_tensors="pt")
input = {k: v.to("cuda") for k, v in input.items()}

#设置labels和inputs一致
input["labels"] = input["input_ids"].clone()

output = model(**input)

#获取模型的loss
loss = output.loss
loss.backward()
optimizer.step()
optimizer.zero_grad()

#保存模型
model.save_pretrained("output_dir")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值