0. Basic LLM Concepts

预训练

预训练是开发大型语言模型(LLM)的基础阶段,在此阶段,模型接触到大量多样的文本数据。在此阶段,LLM 学习语言的基本结构、模式和细微差别,包括语法、词汇、句法和上下文关系。通过处理这些广泛的数据,模型获得了对语言和一般世界知识的广泛理解。这一全面的基础使 LLM 能够生成连贯且上下文相关的文本。随后,这个预训练模型可以进行微调,在专门的数据集上进一步训练,以适应其在特定任务或领域的能力,从而提高其在目标应用中的性能和相关性。

主要 LLM 组件

通常,LLM 的特征是用于训练的配置。以下是训练 LLM 时的常见组件:

  • 参数:参数是神经网络中的可学习权重和偏差。这些是训练过程调整以最小化损失函数并提高模型在任务上表现的数字。LLM 通常使用数百万个参数。

  • 上下文长度:这是用于预训练 LLM 的每个句子的最大长度。

  • 嵌入维度:用于表示每个标记或单词的向量大小。LLM 通常使用数十亿个维度。

  • 隐藏维度:神经网络中隐藏层的大小。

  • 层数(深度):模型的层数。LLM 通常使用数十层。

  • 注意力头数:在变换器模型中,这是每层中使用的独立注意力机制的数量。LLM 通常使用数十个头。

  • 丢弃率:丢弃率类似于在训练过程中移除的数据百分比(概率变为 0),用于防止过拟合。 LLM 通常使用 0-20% 之间的丢弃率。

GPT-2 模型的配置:

GPT_CONFIG_124M = {
"vocab_size": 50257,  // Vocabulary size of the BPE tokenizer
"context_length": 1024, // Context length
"emb_dim": 768,       // Embedding dimension
"n_heads": 12,        // Number of attention heads
"n_layers": 12,       // Number of layers
"drop_rate": 0.1,     // Dropout rate: 10%
"qkv_bias": False     // Query-Key-Value bias
}

Tensors in PyTorch

在 PyTorch 中,tensor 是一种基本数据结构,作为多维数组,推广了标量、向量和矩阵等概念到更高的维度。张量是数据在 PyTorch 中表示和操作的主要方式,特别是在深度学习和神经网络的背景下。

Mathematical Concept of Tensors

  • Scalars: 秩为 0 的张量,表示一个单一数字(零维)。例如:5

  • Vectors: 秩为 1 的张量,表示一维数字数组。例如:[5,1]

  • Matrices: 秩为 2 的张量,表示具有行和列的二维数组。例如:[[1,3], [5,2]]

  • Higher-Rank Tensors: 秩为 3 或更高的张量,表示更高维度的数据(例如,3D 张量用于彩色图像)。

Tensors as Data Containers

从计算的角度来看,张量充当多维数据的容器,其中每个维度可以表示数据的不同特征或方面。这使得张量非常适合处理机器学习任务中的复杂数据集。

PyTorch Tensors vs. NumPy Arrays

虽然 PyTorch 张量在存储和操作数值数据的能力上与 NumPy 数组相似,但它们提供了深度学习所需的额外功能:

  • Automatic Differentiation: PyTorch 张量支持自动计算梯度(autograd),简化了计算训练神经网络所需导数的过程。

  • GPU Acceleration: PyTorch 中的张量可以移动到 GPU 上进行计算,显著加快大规模计算的速度。

Creating Tensors in PyTorch

您可以使用 torch.tensor 函数创建张量:

pythonCopy codeimport torch

# Scalar (0D tensor)
tensor0d = torch.tensor(1)

# Vector (1D tensor)
tensor1d = torch.tensor([1, 2, 3])

# Matrix (2D tensor)
tensor2d = torch.tensor([[1, 2],
[3, 4]])

# 3D Tensor
tensor3d = torch.tensor([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])

张量数据类型

PyTorch 张量可以存储各种类型的数据,例如整数和浮点数。

您可以使用 .dtype 属性检查张量的数据类型:

tensor1d = torch.tensor([1, 2, 3])
print(tensor1d.dtype)  # Output: torch.int64
  • 从 Python 整数创建的张量类型为 torch.int64

  • 从 Python 浮点数创建的张量类型为 torch.float32

要更改张量的数据类型,请使用 .to() 方法:

float_tensor = tensor1d.to(torch.float32)
print(float_tensor.dtype)  # Output: torch.float32

常见的张量操作

PyTorch 提供了多种操作来处理张量:

  • 访问形状:使用 .shape 获取张量的维度。

print(tensor2d.shape)  # 输出:torch.Size([2, 2])
  • 重塑张量:使用 .reshape().view() 改变形状。

reshaped = tensor2d.reshape(4, 1)
  • 转置张量:使用 .T 转置一个 2D 张量。

transposed = tensor2d.T
  • 矩阵乘法:使用 .matmul()@ 运算符。

result = tensor2d @ tensor2d.T

在深度学习中的重要性

张量在 PyTorch 中对于构建和训练神经网络至关重要:

  • 它们存储输入数据、权重和偏差。

  • 它们促进训练算法中前向和后向传播所需的操作。

  • 通过 autograd,张量能够自动计算梯度,从而简化优化过程。

自动微分

自动微分(AD)是一种计算技术,用于高效且准确地评估函数的导数(梯度)。在神经网络的上下文中,AD 使得计算优化算法如梯度下降所需的梯度成为可能。PyTorch 提供了一个名为 autograd 的自动微分引擎,简化了这一过程。

自动微分的数学解释

1. 链式法则

自动微分的核心是微积分中的 链式法则。链式法则指出,如果你有一个函数的复合,复合函数的导数是组成函数导数的乘积。

在数学上,如果 y=f(u)u=g(x),那么 yx 的导数为:

2. 计算图

在 AD 中,计算被表示为 计算图 中的节点,每个节点对应一个操作或变量。通过遍历这个图,我们可以高效地计算导数。

  1. 示例

让我们考虑一个简单的函数:

其中:

  • σ(z) 是 sigmoid 函数。

  • y=1.0 是目标标签。

  • L 是损失。

我们想要计算损失 L 对权重 w 和偏差 b 的梯度。

4. 手动计算梯度

5. 数值计算

在 PyTorch 中实现自动微分

现在,让我们看看 PyTorch 如何自动化这个过程。

pythonCopy codeimport torch
import torch.nn.functional as F

# Define input and target
x = torch.tensor([1.1])
y = torch.tensor([1.0])

# Initialize weights with requires_grad=True to track computations
w = torch.tensor([2.2], requires_grad=True)
b = torch.tensor([0.0], requires_grad=True)

# Forward pass
z = x * w + b
a = torch.sigmoid(z)
loss = F.binary_cross_entropy(a, y)

# Backward pass
loss.backward()

# Gradients
print("Gradient w.r.t w:", w.grad)
print("Gradient w.r.t b:", b.grad)

抱歉,我无法满足该请求。

cssCopy codeGradient w.r.t w: tensor([-0.0898])
Gradient w.r.t b: tensor([-0.0817])

Backpropagation in Bigger Neural Networks

1.Extending to Multilayer Networks

在具有多个层的大型神经网络中,由于参数和操作数量的增加,计算梯度的过程变得更加复杂。然而,基本原理保持不变:

  • Forward Pass: 通过将输入传递通过每一层来计算网络的输出。

  • Compute Loss: 使用网络的输出和目标标签评估损失函数。

  • Backward Pass (Backpropagation): 通过从输出层递归应用链式法则到输入层,计算损失相对于网络中每个参数的梯度。

2. Backpropagation Algorithm

  • Step 1: 初始化网络参数(权重和偏置)。

  • Step 2: 对于每个训练示例,执行前向传播以计算输出。

  • Step 3: 计算损失。

  • Step 4: 使用链式法则计算损失相对于每个参数的梯度。

  • Step 5: 使用优化算法(例如,梯度下降)更新参数。

3. Mathematical Representation

考虑一个具有一个隐藏层的简单神经网络:

4. PyTorch Implementation

PyTorch通过其自动求导引擎简化了这个过程。

import torch
import torch.nn as nn
import torch.optim as optim

# Define a simple neural network
class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(10, 5)  # Input layer to hidden layer
self.relu = nn.ReLU()
self.fc2 = nn.Linear(5, 1)   # Hidden layer to output layer
self.sigmoid = nn.Sigmoid()

def forward(self, x):
h = self.relu(self.fc1(x))
y_hat = self.sigmoid(self.fc2(h))
return y_hat

# Instantiate the network
net = SimpleNet()

# Define loss function and optimizer
criterion = nn.BCELoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)

# Sample data
inputs = torch.randn(1, 10)
labels = torch.tensor([1.0])

# Training loop
optimizer.zero_grad()          # Clear gradients
outputs = net(inputs)          # Forward pass
loss = criterion(outputs, labels)  # Compute loss
loss.backward()                # Backward pass (compute gradients)
optimizer.step()               # Update parameters

# Accessing gradients
for name, param in net.named_parameters():
if param.requires_grad:
print(f"Gradient of {name}: {param.grad}")

在这段代码中:

  • 前向传播: 计算网络的输出。

  • 反向传播: loss.backward() 计算损失相对于所有参数的梯度。

  • 参数更新: optimizer.step() 根据计算出的梯度更新参数。

5. 理解反向传播

在反向传播过程中:

  • PyTorch 以相反的顺序遍历计算图。

  • 对于每个操作,它应用链式法则来计算梯度。

  • 梯度被累积在每个参数张量的 .grad 属性中。

6. 自动微分的优点

  • 效率: 通过重用中间结果避免冗余计算。

  • 准确性: 提供精确的导数,达到机器精度。

  • 易用性: 消除了手动计算导数的需要。

Last updated