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, тензор є основною структурою даних, яка слугує як багатовимірний масив, узагальнюючи концепції, такі як скаляри, вектори та матриці, до потенційно вищих вимірів. Тензори є основним способом представлення та маніпулювання даними в PyTorch, особливо в контексті глибокого навчання та нейронних мереж.

Mathematical Concept of Tensors

  • Скалярі: Тензори рангу 0, що представляють одне число (нульовий вимір). Наприклад: 5

  • Вектори: Тензори рангу 1, що представляють одновимірний масив чисел. Наприклад: [5,1]

  • Матриці: Тензори рангу 2, що представляють двовимірні масиви з рядками та стовпцями. Наприклад: [[1,3], [5,2]]

  • Тензори вищого рангу: Тензори рангу 3 або більше, що представляють дані у вищих вимірах (наприклад, 3D тензори для кольорових зображень).

Tensors as Data Containers

З обчислювальної точки зору, тензори діють як контейнери для багатовимірних даних, де кожен вимір може представляти різні характеристики або аспекти даних. Це робить тензори надзвичайно придатними для обробки складних наборів даних у завданнях машинного навчання.

PyTorch Tensors vs. NumPy Arrays

Хоча тензори PyTorch подібні до масивів NumPy у своїй здатності зберігати та маніпулювати числовими даними, вони пропонують додаткові функціональні можливості, які є критично важливими для глибокого навчання:

  • Автоматичне диференціювання: Тензори PyTorch підтримують автоматичний розрахунок градієнтів (autograd), що спрощує процес обчислення похідних, необхідних для навчання нейронних мереж.

  • Прискорення на GPU: Тензори в 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), тоді похідна y по відношенню до x є:

2. Обчислювальний граф

В AD обчислення представлені як вузли в обчислювальному графі, де кожен вузол відповідає операції або змінній. Пересуваючись цим графом, ми можемо ефективно обчислювати похідні.

  1. Приклад

Розглянемо просту функцію:

Де:

  • σ(z) — це сигмоїдальна функція.

  • 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