clearwind

clearwind

首页
分类
登录 →
clearwind

clearwind

首页 分类
登录
  1. 首页
  2. 🚀AI
  3. 🔧LLM
  4. GPT 模型微调

GPT 模型微调

0
  • 🔧LLM
  • 发布于 2025-01-03
  • 21 次阅读
clearwind
clearwind

GPT-2 是一种基于 Transformer 的生成模型,专注于生成连贯的文本。在 Hugging Face 的Transformers 库中,GPT-2 已经被应用于多种中文文本生成任务,如古诗词、歌词和对联生成等。

GPT-2模型

from transformers import BertTokenizer,GPT2LMHeadModel,TextGenerationPipeline

tokenizer = BertTokenizer.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3")
model = GPT2LMHeadModel.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3")

print(model)
“”“
GPT2LMHeadModel(
  (transformer): GPT2Model(
    (wte): Embedding(21128, 768)
    (wpe): Embedding(1024, 768)
    (drop): Dropout(p=0.1, inplace=False)
    (h): ModuleList(
      (0-11): 12 x GPT2Block(
        (ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
        (attn): GPT2SdpaAttention(
          (c_attn): Conv1D(nf=2304, nx=768)
          (c_proj): Conv1D(nf=768, nx=768)
          (attn_dropout): Dropout(p=0.1, inplace=False)
          (resid_dropout): Dropout(p=0.1, inplace=False)
        )
        (ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
        (mlp): GPT2MLP(
          (c_fc): Conv1D(nf=3072, nx=768)
          (c_proj): Conv1D(nf=768, nx=3072)
          (act): NewGELUActivation()
          (dropout): Dropout(p=0.1, inplace=False)
        )
      )
    )
    (ln_f): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
  )
  (lm_head): Linear(in_features=768, out_features=21128, bias=False)
)

”“”

模型输入数据信息

  • 输入文本:输入文本需要先通过分词器(如 BertTokenizer)进行编码,转换为模型可以理解的格式。具体来说,输入文本会被分割成一个个token(词汇或字符),并映射到模型的词汇表中对应的ID。

  • 输入张量

    • input_ids:这是一个二维张量,形状为 [batch_size, sequence_length],其中 batch_size 是批次大小,`sequence_length` 是序列长度。每个元素是词汇表中的token ID。

      attention_mask(可选):用于指示哪些位置是有效的token(值为1),哪些位置是填充的(值为0)。形状为 [batch_size, sequence_length]。

      position_ids(可选):用于指示每个token在序列中的位置。形状为 [batch_size, sequence_length]。

      token_type_ids(可选):用于区分不同类型的token(例如,在句子对任务中区分两个句子)。形状为 [batch_size, sequence_length]。

模型输出数据信息

  • 输出张量

    • logits:这是模型生成的每个位置上所有可能token的概率分布。形状为 [batch_size, sequence_length, vocab_size],其中 vocab_size 是词汇表的大小(21128)。每个位置上的概率分布可以通过softmax函数转换为概率值。

    • past_key_values(可选):用于加速推理过程中的自回归生成。包含之前计算的注意力键和值,可以在生成下一个token时复用。

模型结构

  • Embedding层

    • wte (word embeddings):将输入的token ID嵌入到768维的向量空间中。形状为 [vocab_size, hidden_size],其中 hidden_size=768。

    • wpe (position embeddings):将每个token的位置信息嵌入到768维的向量空间中。形状为 [max_position_embeddings, hidden_size],其中 max_position_embeddings=1024。

  • Dropout层:在嵌入层之后应用一个dropout层,以防止过拟合。dropout概率为0.1。

  • Transformer层:包含12个 GPT2Block,每个块由以下部分组成:

    • LayerNorm (ln_1):在多头自注意力机制之前应用层归一化。

    • Attention (attn):多头自注意力机制,用于捕捉输入序列中的依赖关系。包括三个子模块:

      • c_attn:线性变换,将输入映射到查询、键和值的组合空间。

      • c_proj:线性变换,将注意力结果映射回隐藏状态空间。

      • attn_dropout 和 resid_dropout:分别应用于注意力权重和残差连接的dropout层。

    • LayerNorm (ln_2):在前馈神经网络之前应用层归一化。

    • MLP (mlp):两层全连接网络,激活函数为 NewGELUActivation,并在最后一层应用dropout。

  • Final LayerNorm:在所有Transformer层之后应用最终的层归一化。

  • Language Model Head (lm_head):线性变换,将隐藏状态映射回词汇表大小的空间。形状为 [hidden_size, vocab_size],没有偏置项。

工作流程

1. 输入处理:输入文本通过分词器编码为 input_ids,并可能附加 attention_mask 和 position_ids。

2. 嵌入层:将 input_ids 和 position_ids 转换为嵌入向量,并应用dropout。

3. Transformer层:嵌入向量依次通过12个 GPT2Block,每个块内部进行多头自注意力计算和前馈神经网络变换。

4. 输出层:最终的隐藏状态通过 lm_head 线性变换,得到每个位置上所有可能token的概率分布。

5. 生成文本:使用生成策略(如贪心搜索、束搜索或采样)从概率分布中选择最合适的token,逐步生成新的文本。

GPT-2 中文模型推理调用

中文白话文生成

from transformers import BertTokenizer,GPT2LMHeadModel,TextGenerationPipeline

tokenizer = BertTokenizer.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3")
model = GPT2LMHeadModel.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3")

#device=0,device="coda" 指定当前的推理设备为第一块GPU;如果没有GPU环境,就去掉该参数
text_generator = TextGenerationPipeline(model,tokenizer)
#使用过text_generator生成文本
out = text_generator("这是很久之前的事情了,",max_length=100,do_sample=True)
print(out)

# do_sample是否进行随机采样,True:每次生成结果不通过。False:每次生成结果想通过
for i in range(3):
    print(text_generator("这是很久之前的事情了,",max_length=100,do_sample=True))

for i in range(3):
    print(text_generator("这是很久之前的事情了,",max_length=100,do_sample=False))

BertTokenizer :用于将输入文本转换为模型可以处理的格式。这里我们使用预训练的uer/gpt2-chinese-lyric 模型的分词器。

GPT2LMHeadModel :GPT-2 模型的实现,专注于语言模型的生成任务。

TextGenerationPipeline :Hugging Face 提供的简化工具,用于快速生成文本。它结合了模型和分词器,简化了推理过程。

do_sample=True :启用随机采样,使得每次生成的文本可能不同,这有助于生成多样化的结果。

device=0 :指定使用第一个 GPU 进行计算。如果系统有多个 GPU,可以通过改变设备编号选择其他 GPU。

max_length=100 :设置生成文本的最大长度,以确保生成的文本不会超出指定的字符数。

[{'generated_text': '这是很久之前的事情了, 大 二 的 时 候 , 来 过 几 次 , 主 要 是 陪 女 友 去 过 一 次 。 因 为 没 有 什 么 时 间 。 第 一 次 看 见 这 家 店 , 是 小 学 的 时 候 老 去 。 里 面 满 满 的 都 是 阿 姨 , 还 有 老 师 。 那 次 是 和 女 友 去 了 , 所 以 老 师 就 送 我 们 一 张 纸 画 。 我'}]

[{'generated_text': '这是很久之前的事情了, 啊 ! 在 里 面 逛 街 , 饿 了 , 就 会 叫 外 卖 吃 , 一 般 都 是 半 小 时 就 送 到 了 ~ 一 般 没 什 么 特 别 的 , 除 了 牛 肉 饭 之 外 , 还 配 有 凉 拌 菜 和 凉 菜 。 送 来 的 速 度 很 快 , 里 面 的 卤 蛋 和 小 笼 都 很 好 吃 呢 ~ , 这 里 有 一 段 时'}]

[{'generated_text': '这是很久之前的事情了, 么 上 次 就 想 换 换 口 味 , 就 来 吃 了 。 本 来 就 是 冲 着 那 个 锅 来 的 , 哈 哈 ! 而 且 都 没 怎 么 吃 啊 ! 里 面 就 加 面 吧 , 当 然 啦 加 的 面 是 要 钱 的 , 加 的 就 是 面 条 。 本 来 想 加 个 青 菜 , 结 果 点 了 很 多 的 。 么 下 次 去 吃 。'}]

[{'generated_text': '这是很久之前的事情了, 前 段 时 间 才 知 道 呢 。 离 单 位 很 近 , 所 以 经 常 去 , 老 板 很 热 情 , 但 是 我 觉 得 没 什 么 事 的 时 候 就 会 去 小 店 , 也 很 快 乐 , 挺 好 的 , 就 是 价 格 贵 了 些 。 每 次 去 , 感 觉 都 不 太 好 , 人 气 好 像 也 不 是 很 旺 吧 。 记 得'}]

[{'generated_text': '这是很久之前的事情了, 前 几 天 和 朋 友 去 吃 了 一 次 , 感 觉 还 不 错 , 就 是 环 境 差 了 点 , 不 过 味 道 还 是 不 错 的 , 价 格 也 不 贵 , 很 适 合 朋 友 聚 会 , 情 侣 约 会 , 家 庭 聚 会 , 朋 友 聚 会 , 都 是 不 错 的 选 择 。'}]

[{'generated_text': '这是很久之前的事情了, 前 几 天 和 朋 友 去 吃 了 一 次 , 感 觉 还 不 错 , 就 是 环 境 差 了 点 , 不 过 味 道 还 是 不 错 的 , 价 格 也 不 贵 , 很 适 合 朋 友 聚 会 , 情 侣 约 会 , 家 庭 聚 会 , 朋 友 聚 会 , 都 是 不 错 的 选 择 。'}]

[{'generated_text': '这是很久之前的事情了, 前 几 天 和 朋 友 去 吃 了 一 次 , 感 觉 还 不 错 , 就 是 环 境 差 了 点 , 不 过 味 道 还 是 不 错 的 , 价 格 也 不 贵 , 很 适 合 朋 友 聚 会 , 情 侣 约 会 , 家 庭 聚 会 , 朋 友 聚 会 , 都 是 不 错 的 选 择 。'}]

中文歌词生成

#中文歌词生成模型
from transformers import GPT2LMHeadModel,BertTokenizer,TextGenerationPipeline

tokenizer = BertTokenizer.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-lyric/snapshots/4a42fd76daab07d9d7ff95c816160cfb7c21684f")
model = GPT2LMHeadModel.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-lyric/snapshots/4a42fd76daab07d9d7ff95c816160cfb7c21684f")
#创建模型推理对象
text_generator = TextGenerationPipeline(model,tokenizer)
out = text_generator("这是很久之前的事了",max_length=100,do_sample=True)
print(out)

[{'generated_text': '这是很久之前的事了 曾 经 的 我 在 ktv 里 唱 了 一 首 儿 歌 , 这 首 歌 是 送 给 我 曾 经 的 她 , 不 知 道 她 是 不 是 很 会 写 歌 , 感 觉 自 己 在 偷 偷 写 信 给 她 , 她 已 经 很 久 都 没 有 我 了 , 她 已 经 好 久 都 没 有 我 了 , 我 一 直 很 挂 念 从 前 的 , 我 一 直 好 希 望 能'}]

中文文言文生成

#中文文言文生成
from transformers import BertTokenizer,GPT2LMHeadModel,TextGenerationPipeline

tokenizer = BertTokenizer.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-ancient/snapshots/3b264872995b09b5d9873e458f3d03a221c00669")
model = GPT2LMHeadModel.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-ancient/snapshots/3b264872995b09b5d9873e458f3d03a221c00669")
#device=0 指定当前的推理设备为第一块GPU;如果没有GPU环境,就去掉该参数
text_generator = TextGenerationPipeline(model,tokenizer,device=0)
out = text_generator("于是乎",max_length=100,do_sample=True)
print(out)

[{'generated_text': '于是乎 神 曰 : 中 央 何 以 太 古 之 大 吕 为 宫 , 以 太 簇 之 律 计 自 乘 八 十 四 徽 至 六 十 一 徽 , 凡 五 徽 之 用 , 以 二 寸 为 商 , 上 为 无 射 之 商 , 下 为 无 射 之 商 , 应 钟 之 商 , 不 应 中 吕 之 商 , 应 钟 之 商 , 不 应 黄 钟 之 商 , 此 不 以 正 声 为 商 也 。 正 声 之'}]

中文对联生成

from transformers import BertTokenizer, GPT2LMHeadModel, TextGenerationPipeline
# 加载中文对联模型的 tokenizer 和模型
tokenizer = BertTokenizer.from_pretrained("uer/gpt2-chinese-couplet")
model = GPT2LMHeadModel.from_pretrained("uer/gpt2-chinese-couplet")
# 创建文本生成管道
text_generator = TextGenerationPipeline(model, tokenizer)
# 生成对联,以 [CLS] 为对联的开头
print(text_generator("[CLS]十口心思,思乡思国思社稷 -", max_length=28,do_sample=True))

[CLS] 标记:特殊标记,用于标记对联的开头。生成的对联会以 [CLS] 为开头,模型将生成后续部分。

中文古诗生成

from transformers import BertTokenizer, GPT2LMHeadModel, TextGenerationPipeline
# 加载中文古诗模型的 tokenizer 和模型
tokenizer = BertTokenizer.from_pretrained("uer/gpt2-chinese-poem")
model = GPT2LMHeadModel.from_pretrained("uer/gpt2-chinese-poem")
# 创建文本生成管道
text_generator = TextGenerationPipeline(model, tokenizer)
# 生成古诗,指定古诗的开头部分
print(text_generator("[CLS]梅 山 如 积 翠 ,", max_length=50, do_sample=True))

max_length=50 :设置生成文本的最大长度,确保古诗生成结果不超出指定长度。

文古诗生成格式

本地训练GPT-2中文模型个

训练数据集结构

在训练模型之前,需要准备好符合要求的数据集。例如, chinese_poems.txt 文件应该包含每行一首古诗。示例内容如下:

床前明月光,疑是地上霜。
举头望明月,低头思故乡。
  • 每行一首古诗:数据集中的每一行代表一个训练样本。数据的格式和内容直接影响模型的训练效果。

  • 文件编码:确保文件使用 UTF-8 编码,以正确处理中文字符。

数据准备

from torch.utils.data import Dataset

class MyDataset(Dataset):
    def __init__(self):
        with open("data/chinese_poems.txt",encoding="utf-8") as f:
            lines = f.readlines()
        #读取数据文件并去除每行的空白字符,确保数据清洁
        lines = [i.strip() for i in lines]
        self.lines = lines
    def __len__(self):
        return len(self.lines)
    def __getitem__(self, item):
        return self.lines[item]

if __name__ == '__main__':
    dataset = MyDataset()
    print(len(dataset),dataset[-1])

训练模型

# 导入transformers库中的AdamW优化器
from transformers import AdamW
# 导入transformers库中的优化器调度器获取函数
from transformers.optimization import get_scheduler
# 导入PyTorch库
import torch
# 导入自定义的数据集类MyDataset
from data import MyDataset
# 导入transformers库中的自动分词器
from transformers import AutoTokenizer
# 导入transformers库中的因果语言模型和GPT2模型
from transformers import AutoModelForCausalLM, GPT2Model

# 实例化自定义数据集
dataset = MyDataset()

# 加载预训练的编码器(分词器)
tokenizer = AutoTokenizer.from_pretrained(r"D:\PycharmProjects\demo_16\model\models--uer--gpt2-chinese-cluecorpussmall\snapshots\c2c0249d8a2731f269414cc3b22dff021f8e07a3")
# 加载预训练的模型
model = AutoModelForCausalLM.from_pretrained(r"D:\PycharmProjects\demo_16\model\models--uer--gpt2-chinese-cluecorpussmall\snapshots\c2c0249d8a2731f269414cc3b22dff021f8e07a3")
# 打印模型结构(已注释)
# print(model)

# 定义数据预处理函数,用于将文本编码成模型所需的格式
def collate_fn(data):
    # 使用分词器对数据进行编码,并添加必要的填充和截断
    data = tokenizer.batch_encode_plus(data,
                                       padding=True,  # 填充序列
                                       truncation=True,  # 截断序列
                                       max_length=512,  # 最大序列长度
                                       return_tensors='pt')  # 返回PyTorch张量

    # 创建标签,与输入ID相同
    data['labels'] = data['input_ids'].clone()

    return data

# 创建数据加载器,用于批量加载数据
loader = torch.utils.data.DataLoader(
    dataset=dataset,  # 指定数据集
    batch_size=6,  # 指定批量大小
    collate_fn=collate_fn,  # 指定预处理函数
    shuffle=True,  # 打乱数据
    drop_last=True,  # 如果最后一个批次不足,则丢弃
)
# 打印数据加载器中的批次数量
print(len(loader))

# 定义训练函数
def train():
    global model  # 使用全局变量model
    # 确定使用CPU还是GPU
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    # 将模型移动到指定设备
    model = model.to(device)

    # 实例化优化器
    optimizer = AdamW(model.parameters(), lr=2e-5)
    # 获取优化器调度器
    scheduler = get_scheduler(name='linear',  # 线性调度器
                              num_warmup_steps=0,  # 预热步数
                              num_training_steps=len(loader),  # 总训练步数
                              optimizer=optimizer)

    # 设置模型为训练模式
    model.train()
    # 遍历数据加载器中的每个批次
    for i, data in enumerate(loader):
        # 将数据移动到指定设备
        for k in data.keys():
            data[k] = data[k].to(device)
        # 前向传播
        out = model(**data)
        # 获取损失
        loss = out['loss']

        # 反向传播
        loss.backward()
        # 梯度裁剪,防止梯度爆炸
        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

        # 更新模型参数
        optimizer.step()
        # 更新学习率
        scheduler.step()

        # 清空梯度
        optimizer.zero_grad()
        model.zero_grad()

        # 每隔50个批次打印一次训练信息
        if i % 50 == 0:
            # 准备标签和输出用于计算准确率
            labels = data['labels'][:, 1:]
            #通过‘logits’获取模型的原始输出值
            out = out['logits'].argmax(dim=2)[:, :-1]

            # 移除在数据预处理阶段添加的填充(通常是0),以便只计算实际数据部分的损失和准确率,避免填充部分对模型性能评估的影响。
            select = labels != 0
            labels = labels[select]
            out = out[select]
            del select

            # 计算准确率
            accuracy = (labels == out).sum().item() / labels.numel()

            # 获取当前学习率
            lr = optimizer.state_dict()['param_groups'][0]['lr']

            # 打印批次索引、损失、学习率和准确率
            print(i, loss.item(),lr, accuracy)
    # 保存模型参数,不保存模型结构
    torch.save(model.state_dict(), 'net.pt')
    # 打印模型参数保存成功信息
    print("权重保存成功!")

# 当脚本作为主程序运行时,执行以下代码
if __name__ == '__main__':
    # 进行1000个训练周期
    for epoch in range(1000):
        # 调用训练函数
        train()

标签: #Fine-Tuning 7 #Model 8 #HuggingFace 7 #Transformer 7
相关文章
简述 Transformer 训练计算过程(刷新渲染)

简述 Transformer 训练计算过程(刷新渲染) 2025-01-11 23:54

Step1-定义数据集 用于创建 ChatGPT 的数据集为 570 GB。假设数据集为一下内容: 白日依山尽,黄河入海流。 马无夜草不肥,人无横财不富。 天行健,君子以自强不息,地势坤,君子以厚德载物。 Step2-计算词汇量

基于 internlm2 和 LangChain 搭建你的知识库

基于 internlm2 和 LangChain 搭建你的知识库 2025-02-27 14:25

环境配置 internlm2 模型部署 创建虚拟环境 conda create -n deepseek_rag python=3.10 -y conda activate deepseek_rag 并在环境中安装运行 demo 所需要的依赖 # 升级pip python -m pip install

Llama-Factory 微调全过程

Llama-Factory 微调全过程 2025-01-13 22:28

数据集 数据集下载:通过ModelScope获取原始数据集https://modelscope.cn/datasets/w10442005/ruozhiba_qa/summary git clone https://www.modelscope.cn/datasets/w10442005/ruozh

矩阵分解 2025-01-11 15:48

矩阵分解是一种通过将较大的矩阵分解为多个小矩阵已降低计算复杂度的技术,在模型训练微调上,通常用于简化模型、提高训练效率。矩阵分解有多种形式,一下是几种常见的模型微调权重分解方法: 奇异值分解 将矩阵分解为三个矩阵乘积的方法: W=U \Sigma V^{T} 其中: W是原始权重矩阵。 U和V是正交

LLM奥秘

LLM奥秘 2025-01-09 21:47

本文旨在通过最基础的数学内容,剔除机器学习中复杂的术语,从零描述LLM的工作原理。

GPT 模型微调

GPT 模型微调 2025-01-03 22:51

GPT-2 是一种基于 Transformer 的生成模型,专注于生成连贯的文本。在 Hugging Face 的Transformers 库中,GPT-2 已经被应用于多种中文文本生成任务,如古诗词、歌词和对联生成等。 GPT-2模型 from transformers import BertTo

目录
  • clearwind
  • 微信小程序

导航菜单

  • 首页
  • 分类
Copyright © 2024 your company All Rights Reserved. Powered by clearwind.
皖ICP备19023482号