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])

Зворотне поширення в більших нейронних мережах

1. Розширення до багатошарових мереж

У більших нейронних мережах з кількома шарами процес обчислення градієнтів стає більш складним через збільшену кількість параметрів і операцій. Однак основні принципи залишаються незмінними:

  • Прямий прохід: Обчисліть вихід мережі, пропускаючи вхідні дані через кожен шар.

  • Обчислити втрати: Оцініть функцію втрат, використовуючи вихід мережі та цільові мітки.

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

2. Алгоритм зворотного поширення

  • Крок 1: Ініціалізуйте параметри мережі (ваги та зміщення).

  • Крок 2: Для кожного навчального прикладу виконайте прямий прохід для обчислення виходів.

  • Крок 3: Обчисліть втрати.

  • Крок 4: Обчисліть градієнти втрат щодо кожного параметра, використовуючи правило ланцюга.

  • Крок 5: Оновіть параметри, використовуючи алгоритм оптимізації (наприклад, градієнтний спуск).

3. Математичне представлення

Розгляньте просту нейронну мережу з одним прихованим шаром:

4. Реалізація в PyTorch

PyTorch спрощує цей процес за допомогою свого механізму autograd.

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