百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

大模型入门-day13-14:小规模训练(小规模教学)

ztj100 2025-06-09 07:26 27 浏览 0 评论

小规模训练 内容基于 Hugging Face 的 datasets 库加载 WikiText-2 数据集,训练简单 Transformer 模型,并观察 Perplexity 下降。


第 13-14 天:小规模训练(6-10 小时)

学习目标

  • 理解 Transformer 原理:掌握 Self-Attention 等核心概念。
  • 加载数据:用 Hugging Face 的 datasets 库加载 WikiText-2。
  • 构建模型:用 PyTorch 搭建简单 Transformer。
  • 训练与评估:训练模型,观察 Perplexity 下降。
  • 成果:能解释 Transformer,手写简单代码。

时间安排

  • 总计:6-10 小时
  • 第 13 天:3-5 小时(原理、数据加载、模型搭建)
  • 第 14 天:3-5 小时(训练、评估、总结)

第 13 天:准备与搭建

任务 1:理解 Transformer 原理

时间:1-2 小时
内容

  • Transformer 核心:通过 Self-Attention 关注句子中的重要词,用编码器和解码器处理输入和生成输出。
  • 关键组件
  • Self-Attention:让模型关注每个词与其他词的关系。
  • Multi-Head Attention:多角度理解句子。
  • Positional Encoding:给词加上位置信息。
  • 资源
  • The Illustrated Transformer
  • Attention is All You Need(可选)

练习:用自己的话说:“Transformer 怎么预测下一个词?”


任务 2:加载数据集和分词

时间:1 小时
内容:用 datasets 库加载 WikiText-2 数据集,并用分词器处理文本。

代码:

python

# 导入库
from datasets import load_dataset  # 加载数据集
from transformers import AutoTokenizer  # 加载分词器

# 加载 WikiText-2 数据集
dataset = load_dataset("wikitext", "wikitext-2-v1")
# 解释:从 Hugging Face 下载 WikiText-2,包含 train、valid、test 三部分。

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# 解释:用 BERT 的分词器,把文本转为数字 token。

# 分词函数
def tokenize_function(examples):
    return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=512)
# 解释:对文本分词,截断或填充到 512 个 token。

# 分词整个数据集
tokenized_dataset = dataset.map(tokenize_function, batched=True)
# 解释:批量处理数据集,分词后返回新数据集。

输出示例:

  • 检查 tokenized_dataset["train"][0]["input_ids"],会看到一串数字(如 [101, 1996, 4937, ...])。

任务 3:数据预处理

时间:1 小时
内容:将分词数据转为 PyTorch 张量,创建 DataLoader。

代码:

python

# 导入库
from torch.utils.data import DataLoader  # 创建 DataLoader
from torch.nn.utils.rnn import pad_sequence  # 填充序列

# 自定义批处理函数
def collate_fn(batch):
    input_ids = [torch.tensor(item["input_ids"]) for item in batch]
    # 解释:从每个样本中提取 input_ids,转为张量。
    input_ids = pad_sequence(input_ids, batch_first=True, padding_value=tokenizer.pad_token_id)
    # 解释:填充序列到相同长度,用 pad_token_id(如 0)填充。
    return {"input_ids": input_ids}
    # 解释:返回字典,包含填充后的 input_ids。

# 创建 DataLoader
train_dataloader = DataLoader(
    tokenized_dataset["train"],  # 训练集
    batch_size=8,  # 每批 8 个样本
    shuffle=True,  # 随机打乱
    collate_fn=collate_fn  # 用自定义函数处理批次
)
# 解释:DataLoader 批量加载数据,方便训练。

输出示例:

  • next(iter(train_dataloader))["input_ids"] 输出形状:(8, 512)。

任务 4:构建简单 Transformer 模型

时间:2-3 小时
内容:用 PyTorch 搭建一个简单 Transformer。

代码:

python

# 导入库
import torch
import torch.nn as nn  # 神经网络模块

# 定义模型
class SimpleTransformer(nn.Module):
    def __init__(self, vocab_size, d_model, nhead, num_encoder_layers, dim_feedforward, max_seq_length, dropout=0.1):
        super(SimpleTransformer, self).__init__()
        # 解释:初始化父类 nn.Module。

        self.embedding = nn.Embedding(vocab_size, d_model)
        # 解释:将词索引转为 d_model 维的向量。

        self.positional_encoding = nn.Parameter(torch.zeros(1, max_seq_length, d_model))
        # 解释:可学习的位置编码,记录词的位置。

        encoder_layer = nn.TransformerEncoderLayer(
            d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout, batch_first=True
        )
        # 解释:定义单层编码器,包含注意力机制和前馈网络。

        self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_encoder_layers)
        # 解释:堆叠多层编码器。

        self.fc_out = nn.Linear(d_model, vocab_size)
        # 解释:将编码器输出映射到词汇表大小。

    def forward(self, src):
        seq_length = src.size(1)
        # 解释:获取输入序列长度。
        src = self.embedding(src) + self.positional_encoding[:, :seq_length, :]
        # 解释:词嵌入加上位置编码。
        output = self.transformer_encoder(src)
        # 解释:通过 Transformer 编码器处理。
        return self.fc_out(output)
        # 解释:输出预测结果。

# 初始化模型
vocab_size = tokenizer.vocab_size  # 词汇表大小(如 30522)
model = SimpleTransformer(
    vocab_size=vocab_size, d_model=512, nhead=8, num_encoder_layers=6,
    dim_feedforward=2048, max_seq_length=512, dropout=0.1
)
# 解释:创建模型实例,设置超参数。

参数说明:

  • d_model:词嵌入维度(512)。
  • nhead:注意力头数(8)。
  • num_encoder_layers:编码器层数(6)。

第 14 天:训练与评估

任务 5:训练模型

时间:2-3 小时
内容:编写训练循环,训练模型。

代码:

python

# 导入库
import torch.optim as optim  # 优化器

# 设置设备和损失函数
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)

# 训练函数
def train(model, dataloader, epochs=3):  # 减少 epoch 以节省时间
    model.train()
    for epoch in range(epochs):
        total_loss = 0
        for batch in dataloader:
            input_ids = batch["input_ids"].to(device)
            # 解释:将输入移到 GPU/CPU。
            labels = input_ids  # 语言模型用输入预测下一个词
            optimizer.zero_grad()
            # 解释:清空上一次梯度。
            output = model(input_ids)
            # 解释:模型前向传播。
            loss = criterion(output.view(-1, vocab_size), labels.view(-1))
            # 解释:计算损失,view(-1) 展平张量。
            loss.backward()
            # 解释:反向传播计算梯度。
            optimizer.step()
            # 解释:更新模型参数。
            total_loss += loss.item()
        avg_loss = total_loss / len(dataloader)
        print(f"Epoch {epoch+1}, Avg Loss: {avg_loss:.3f}")

# 开始训练
train(model, train_dataloader)

输出示例:

Epoch 1, Avg Loss: 7.500
Epoch 2, Avg Loss: 6.800
Epoch 3, Avg Loss: 6.200

任务 6:评估模型

时间:1 小时
内容:计算 Perplexity,观察下降趋势。

代码:

python

import math

def calculate_perplexity(model, dataloader):
    model.eval()
    total_loss = 0
    with torch.no_grad():  # 不计算梯度
        for batch in dataloader:
            input_ids = batch["input_ids"].to(device)
            labels = input_ids
            output = model(input_ids)
            loss = criterion(output.view(-1, vocab_size), labels.view(-1))
            total_loss += loss.item()
    avg_loss = total_loss / len(dataloader)
    perplexity = math.exp(avg_loss)  # Perplexity = e^loss
    return perplexity

# 计算并打印
perplexity = calculate_perplexity(model, train_dataloader)
print(f"Perplexity: {perplexity:.3f}")

输出示例:

Perplexity: 500.000

任务 7:总结与反思

时间:1 小时
内容:回顾学习成果,回答问题:

  1. Perplexity 是否下降? 如果没有,可能是学习率太高(调小 lr)或数据问题。
  2. Self-Attention 怎么工作? 试着解释:“它让模型关注句子中重要的词,比如‘猫’和‘坐’的关系。”
  3. 改进建议:调整 lr(如 0.001)、增加 epochs、减少 batch_size。

成果验收

  • 原理:能用简单语言解释 Transformer。
  • 数据:成功加载并分词 WikiText-2。
  • 模型:手写并运行 Transformer 代码。
  • 评估:观察到 Perplexity 下降(比如从 1800 到 500)。

小 Tips

  • 硬件:没 GPU 用 CPU,调小 batch_size(如 4)。
  • 调试:报错告诉我,我帮你调。
  • 扩展:试试用 valid_dataloader 评估验证集。

完成任务后,告诉我 Perplexity 结果和你的 Transformer 解释,我帮你确认!动手开始吧!

相关推荐

这个 JavaScript Api 已被废弃!请慎用!

在开发过程中,我们可能会不自觉地使用一些已经被标记为废弃的JavaScriptAPI。这些...

JavaScript中10个“过时”的API,你的代码里还在用吗?

JavaScript作为一门不断发展的语言,其API也在持续进化。新的、更安全、更高效的API不断涌现,而一些旧的API则因为各种原因(如安全问题、性能瓶颈、设计缺陷或有了更好的替代品)被标记为“废...

几大开源免费的 JavaScript 富文本编辑器测评

MarkDown编辑器用的时间长了,发现发现富文本编辑器用起来是真的舒服。...

比较好的网页里面的 html 编辑器 推荐

如果您正在寻找嵌入到网页中的HTML编辑器,以便用户可以直接在网页上编辑HTML内容,以下是几个备受推荐的:CKEditor:CKEditor是一个功能强大的、开源的富文本编辑器,可以嵌入到...

Luckysheet 实现excel多人在线协同编辑

前言前些天看到Luckysheet支持协同编辑Excel,正符合我们协同项目的一部分,故而想进一步完善协同文章,但是遇到了一下困难,特此做声明哈,若侵权,请联系我删除文章!若侵犯版权、个人隐私,请联系...

从 Element UI 源码的构建流程来看前端 UI 库设计

作者:前端森林转发链接:https://mp.weixin.qq.com/s/ziDMLDJcvx07aM6xoEyWHQ引言...

手把手教你如何用 Decorator 装饰你的 Typescript?「实践」

作者:Nealyang转发连接:https://mp.weixin.qq.com/s/PFgc8xD7gT40-9qXNTpk7A...

推荐五个优秀的富文本编辑器

富文本编辑器是一种可嵌入浏览器网页中,所见即所得的文本编辑器。对于许多从事前端开发的小伙伴来说并不算陌生,它的应用场景非常广泛,平时发个评论、写篇博客文章等都能见到它的身影。...

基于vue + element的后台管理系统解决方案

作者:林鑫转发链接:https://github.com/lin-xin前言该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(WebManagementSystem)开发。基于v...

开源富文本编辑器Quill 2.0重磅发布

开源富文本编辑器Quill正式发布2.0版本。官方TypeScript声明...

Python之Web开发框架学习 Django-表单处理

在Django中创建表单实际上类似于创建模型。同样,我们只需要从Django类继承,则类属性将是表单字段。让我们在myapp文件夹中添加一个forms.py文件以包含我们的应用程序表单。我们将创建一个...

Django测试入门:打造坚实代码基础的钥匙

这一篇说一下django框架的自动化测试,...

Django ORM vs SQLAlchemy:到底谁更香?从入门到上头的选择指南

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。...

超详细的Django 框架介绍,它来了!

时光荏苒,一晃小编的Tornado框架系列也结束了。这个框架虽然没有之前的FastAPI高流量,但是,它也是小编的心血呀。总共16篇博文,从入门到进阶,包含了框架的方方面面。虽然小编有些方面介绍得不是...

20《Nginx 入门教程》使用 Nginx 部署 Python 项目

今天的目标是完成一个PythonWeb项目的线上部署,我们使用最新的Django项目搭建一个简易的Web工程,然后基于Nginx服务部署该PythonWeb项目。1.前期准备...

取消回复欢迎 发表评论: