2097 字
10 分钟
复刻GPT2对话模型

参考文献#

卷积神经网络

GPT3

前言#

  • 首先你需要会熟练使用python
  • 熟悉Transformer架构
  • 熟悉pytorch框架
  • 熟悉TensorFlow
  • 需要一定的空间想象运算能力
  • 能够熟练使用 Linux 系统
  • 具备NLP 相关基础知识
  • 需要一定的数学基础
  • 当然还需要一张好的GPU

教程还算硬,2025/1/19日创建文章,,进行编写如有问题,欢迎提出

  • 主要围绕熟悉神经网络进行讲解,不能说和GPT一样,但是底层逻辑大致相同
  • 当然GPT目前使用的更先进的,openai逐渐不是很开源了我们也就无从得知
  • 毕竟在今年我自己的目标中是需要训练一个属于自己的模型,当然秉承着开源精神,使用我们开放教程,不一定开源模型

声明#

本项目为个人学习项目,仅供学习参考,本教程只提供我理解的思路,不保证准确性。

  • 欢迎各位指出问题,提出改进意见。
  • 我所追求的是小模型,大能力,这只是个开始
  • 创作灵感来源于[Andrej Karpathy]大佬开源的nanoGPT项目,进行简单的解读代码

模型结构#

  1. transformer架构

图片

说明#

  1. 大模型并非入门简单,所以需要一定门槛

  2. 大模型的几个阶段为:

  • 预训练->有监督微调->奖励建模->强化学习

对应

  • 小学生->中学生->大学生->社会人

开始#

当然我们既然是还原这个GPT2的大模型,那么作为硬核教程来说肯定不止这一期,好的我们就不废话了,本期教程从网络神经开始教学

网络神经#

神经网络是一种模拟人脑的神经网络以期能够实现类人工智能的机器学习技术,成人的大脑中估计有1000亿个神经元之多

  1. 输入层 输入层就是输入数据,比如一个图片,一个文本,一个音频等,输入层就是输入的数据
  2. 隐藏层 隐藏层就是中间层
  3. 输出层 输出层就是输出数据的

如图

简单理解一下即可

这时候我们需要理解神经网络的原理,首先我们需要知道一个x,这个x为网络神经的向量,也就是第一层,但是需要明白文字和图像的区分,图像是把像素通过灰度图象化,并把你图像的x和y像素转换为一条x的长度值,转换后的就是输入层

假如一张28x28的灰度图象,那么就是784个像素点,也就是784个输入层,这些输入层为一条轴长为784的参数,高度为1,这就是图像识别的最简单方法

文字版本的则为通过把文字转换为对应的数字,再把数字转成文字的方式,即为(好比我把你好的字分开储存,记为向量的156,710)那么机器人在回答时就会回答156,710,也就是你好

pytorch#

理解完成我们下一步就是熟悉pytorch

PyTorch 是一个开源的深度学习框架

按照国际惯例我们先安装我们来到PyTorch进行安装选择对应型号加载即可,需要保证电脑上有python环境

python --version

我的python版本为3.10.5版本,同时我们还需要查看显卡的CUDA国际惯例输入

nvidia-smi

我自己的显卡为RTX3060,所以安装CUDA为12.7这个命令适用于英伟达显卡

所以选择后复制命令

使用代码进行检查安装是否到位

import torch

# 当前安装的 PyTorch 库的版本
print(torch.__version__)
# 检查 CUDA 是否可用,即你的系统有 NVIDIA 的 GPU
print(torch.cuda.is_available())

输出 True,则说明 PyTorch 成功识别到你的 GPU

网络神经模型搭建#

我们首先使用这个库简单搭建一个神经网络模型,我们单纯演示一下

以下是对代码逐步拆解的详细讲解,适合写入门级的PyTorch教程。

1. 导入必要的库#

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
  • torch:PyTorch的核心库,用于张量操作和自动微分。
  • torch.nn:包含定义神经网络模型的模块。
  • torch.optim:提供优化器,如SGD和Adam,用于更新模型参数。
  • torchvision:提供图像相关的数据集和工具,特别适合处理视觉任务。
  • DataLoader:负责将数据集打包成小批量(mini-batch),提高训练效率。

2. 数据准备#

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])
  • ToTensor():将图像数据转为PyTorch张量,同时归一化到[0, 1]。
  • Normalize((0.5,), (0.5,)):对数据进行标准化处理,使均值为0,标准差为1,提升训练稳定性。
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
  • datasets.MNIST:加载MNIST数据集,这是一个手写数字(0-9)分类任务的经典数据集。
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
  • DataLoader:将数据集分成小批量,batch_size=64表示每次训练64张图像。

3. 定义神经网络#

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 128)  # 输入层到第一个隐藏层
        self.fc2 = nn.Linear(128, 64)       # 第一个隐藏层到第二个隐藏层
        self.fc3 = nn.Linear(64, 10)       # 第二个隐藏层到输出层
    
    def forward(self, x):
        x = x.view(-1, 28 * 28)            # 将图像展平成一维张量
        x = torch.relu(self.fc1(x))       # 第一层 + ReLU激活函数
        x = torch.relu(self.fc2(x))       # 第二层 + ReLU激活函数
        x = self.fc3(x)                   # 输出层(无激活函数,因为CrossEntropyLoss内部会处理)
        return x
  • nn.Module:所有模型的基类。
  • nn.Linear:全连接层,in_features是输入维度,out_features是输出维度。
  • torch.relu:激活函数,引入非线性,使网络能学习复杂模式。
  • forward:定义前向传播的计算逻辑。

4. 损失函数和优化器#

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
  • CrossEntropyLoss:用于分类任务的损失函数,结合了softmax和负对数似然损失。
  • SGD:随机梯度下降优化器,lr=0.01是学习率,控制参数更新的步伐。

5. 训练模型#

def train(model, loader, criterion, optimizer, epochs=5):
    model.train()  # 切换到训练模式
    for epoch in range(epochs):
        total_loss = 0
        for images, labels in loader:  # 遍历每个批次
            optimizer.zero_grad()      # 梯度清零
            outputs = model(images)    # 前向传播
            loss = criterion(outputs, labels)  # 计算损失
            loss.backward()            # 反向传播
            optimizer.step()           # 更新参数
            total_loss += loss.item()  # 累积损失
        print(f"Epoch {epoch + 1}/{epochs}, Loss: {total_loss / len(loader):.4f}")

每个步骤说明:

  1. model.train():启用Dropout等训练时独有的操作。
  2. optimizer.zero_grad():清除上一次梯度计算的残留值。
  3. loss.backward():计算损失对每个参数的梯度。
  4. optimizer.step():使用梯度更新参数。
  5. 打印每轮的平均损失

6. 测试模型#

def test(model, loader):
    model.eval()  # 切换到评估模式
    correct = 0
    total = 0
    with torch.no_grad():  # 禁用梯度计算,加速推理
        for images, labels in loader:
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)  # 获取预测结果
            total += labels.size(0)              # 样本总数
            correct += (predicted == labels).sum().item()  # 正确预测的样本数
    print(f"Accuracy: {100 * correct / total:.2f}%")

步骤说明:

  1. model.eval():关闭Dropout等训练时独有的操作。
  2. torch.no_grad():禁用梯度计算,节省内存。
  3. torch.max(outputs, 1):获取每个样本概率最大的类别。

7. 执行训练和测试#

train(model, train_loader, criterion, optimizer, epochs=5)
test(model, test_loader)

调用训练函数进行训练,随后用测试集评估模型性能。

我们就得到了

NOTE

Epoch 1/5, Loss: 1.0917

Epoch 2/5, Loss: 0.3857

Epoch 3/5, Loss: 0.3251

Epoch 4/5, Loss: 0.2942

Epoch 5/5, Loss: 0.2703

Accuracy: 92.81%

类似这样的数据,不方便观看?当然

这样就方便观看了

我们可以直观看到通过不断学习逐渐下降的曲度,当然在代码中为了清晰所以这个图像并不会生成

这个是训练过程中loss的变化,同时这个代码起参考作用,这个代码是展示了卷积神经网络,这个是图像识别的 数据来源于tensorflow

总结#

这个代码是一个简单的神经网络模型,用于图像分类任务。它使用了MNIST数据集,一个经典的手写数字分类数据集

预告#

下一期我们将讲解和学习文字的生成模型和文字储存训练

复刻GPT2对话模型
https://fengyegf.cn/blog/posts/gpt/1/
作者
MLeaf-coder
发布于
2025-01-19
许可协议
CC BY-NC-SA 4.0