13 KiB
0. Podstawowe pojęcia LLM
Pretraining
Pretraining to podstawowa faza w rozwijaniu dużego modelu językowego (LLM), w której model jest narażony na ogromne i różnorodne ilości danych tekstowych. W tym etapie LLM uczy się fundamentalnych struktur, wzorców i niuansów języka, w tym gramatyki, słownictwa, składni i relacji kontekstowych. Przetwarzając te obszerne dane, model nabywa szerokie zrozumienie języka i ogólnej wiedzy o świecie. Ta kompleksowa baza umożliwia LLM generowanie spójnego i kontekstowo odpowiedniego tekstu. Następnie ten wstępnie wytrenowany model może przejść do fine-tuningu, gdzie jest dalej trenowany na wyspecjalizowanych zbiorach danych, aby dostosować swoje możliwości do konkretnych zadań lub dziedzin, poprawiając swoją wydajność i trafność w docelowych zastosowaniach.
Główne komponenty LLM
Zazwyczaj LLM charakteryzuje się konfiguracją używaną do jego trenowania. Oto wspólne komponenty podczas trenowania LLM:
- Parametry: Parametry to uczone wagi i biasy w sieci neuronowej. To są liczby, które proces treningowy dostosowuje, aby zminimalizować funkcję straty i poprawić wydajność modelu w zadaniu. LLM zazwyczaj używa milionów parametrów.
- Długość kontekstu: To maksymalna długość każdego zdania używanego do wstępnego trenowania LLM.
- Wymiar osadzenia: Rozmiar wektora używanego do reprezentacji każdego tokena lub słowa. LLM zazwyczaj używa miliardów wymiarów.
- Wymiar ukryty: Rozmiar warstw ukrytych w sieci neuronowej.
- Liczba warstw (głębokość): Ile warstw ma model. LLM zazwyczaj używa dziesiątek warstw.
- Liczba głów uwagi: W modelach transformatorowych, to ile oddzielnych mechanizmów uwagi jest używanych w każdej warstwie. LLM zazwyczaj używa dziesiątek głów.
- Dropout: Dropout to coś w rodzaju procentu danych, które są usuwane (prawdopodobieństwa stają się 0) podczas treningu, używanego do zapobiegania przeuczeniu. LLM zazwyczaj używa od 0 do 20%.
Konfiguracja modelu 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
W PyTorch, tensor to podstawowa struktura danych, która służy jako wielowymiarowa tablica, uogólniając pojęcia takie jak skalar, wektor i macierz do potencjalnie wyższych wymiarów. Tenzory są głównym sposobem reprezentacji i manipulacji danymi w PyTorch, szczególnie w kontekście uczenia głębokiego i sieci neuronowych.
Mathematical Concept of Tensors
- Scalars: Tenzory rangi 0, reprezentujące pojedynczą liczbę (zero-wymiarowe). Jak: 5
- Vectors: Tenzory rangi 1, reprezentujące jednowymiarową tablicę liczb. Jak: [5,1]
- Matrices: Tenzory rangi 2, reprezentujące dwuwymiarowe tablice z wierszami i kolumnami. Jak: 1,3], [5,2
- Higher-Rank Tensors: Tenzory rangi 3 lub wyższej, reprezentujące dane w wyższych wymiarach (np. 3D tenzory dla obrazów kolorowych).
Tensors as Data Containers
Z perspektywy obliczeniowej, tenzory działają jako pojemniki dla wielowymiarowych danych, gdzie każdy wymiar może reprezentować różne cechy lub aspekty danych. To sprawia, że tenzory są bardzo odpowiednie do obsługi złożonych zbiorów danych w zadaniach uczenia maszynowego.
PyTorch Tensors vs. NumPy Arrays
Chociaż tenzory PyTorch są podobne do tablic NumPy w ich zdolności do przechowywania i manipulacji danymi numerycznymi, oferują dodatkowe funkcjonalności kluczowe dla uczenia głębokiego:
- Automatic Differentiation: Tenzory PyTorch wspierają automatyczne obliczanie gradientów (autograd), co upraszcza proces obliczania pochodnych wymaganych do trenowania sieci neuronowych.
- GPU Acceleration: Tenzory w PyTorch mogą być przenoszone i obliczane na GPU, co znacznie przyspiesza obliczenia na dużą skalę.
Creating Tensors in PyTorch
Możesz tworzyć tenzory za pomocą funkcji 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]]])
Typy danych tensorów
Tensory PyTorch mogą przechowywać dane różnych typów, takich jak liczby całkowite i liczby zmiennoprzecinkowe.
Możesz sprawdzić typ danych tensora, używając atrybutu .dtype
:
tensor1d = torch.tensor([1, 2, 3])
print(tensor1d.dtype) # Output: torch.int64
- Tensory utworzone z liczb całkowitych Pythona są typu
torch.int64
. - Tensory utworzone z liczb zmiennoprzecinkowych Pythona są typu
torch.float32
.
Aby zmienić typ danych tensora, użyj metody .to()
:
float_tensor = tensor1d.to(torch.float32)
print(float_tensor.dtype) # Output: torch.float32
Common Tensor Operations
PyTorch provides a variety of operations to manipulate tensors:
- Accessing Shape: Use
.shape
to get the dimensions of a tensor.
print(tensor2d.shape) # Output: torch.Size([2, 2])
- Reshaping Tensors: Use
.reshape()
or.view()
to change the shape.
reshaped = tensor2d.reshape(4, 1)
- Transposing Tensors: Use
.T
to transpose a 2D tensor.
transposed = tensor2d.T
- Matrix Multiplication: Use
.matmul()
or the@
operator.
result = tensor2d @ tensor2d.T
Importance in Deep Learning
Tensors are essential in PyTorch for building and training neural networks:
- Przechowują dane wejściowe, wagi i biasy.
- Ułatwiają operacje wymagane do przeprowadzania kroków w przód i w tył w algorytmach treningowych.
- Dzięki autograd, tensory umożliwiają automatyczne obliczanie gradientów, upraszczając proces optymalizacji.
Automatic Differentiation
Automatic differentiation (AD) is a computational technique used to evaluate the derivatives (gradients) of functions efficiently and accurately. In the context of neural networks, AD enables the calculation of gradients required for optimization algorithms like gradient descent. PyTorch provides an automatic differentiation engine called autograd that simplifies this process.
Mathematical Explanation of Automatic Differentiation
1. The Chain Rule
At the heart of automatic differentiation is the chain rule from calculus. The chain rule states that if you have a composition of functions, the derivative of the composite function is the product of the derivatives of the composed functions.
Mathematically, if y=f(u)
and u=g(x)
, then the derivative of y
with respect to x
is:
2. Computational Graph
In AD, computations are represented as nodes in a computational graph, where each node corresponds to an operation or a variable. By traversing this graph, we can compute derivatives efficiently.
- Example
Let's consider a simple function:
Where:
σ(z)
is the sigmoid function.y=1.0
is the target label.L
is the loss.
We want to compute the gradient of the loss L
with respect to the weight w
and bias b
.
4. Computing Gradients Manually
5. Numerical Calculation
Implementing Automatic Differentiation in PyTorch
Now, let's see how PyTorch automates this process.
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)
Output:
Podstawowe pojęcia LLM
W tej sekcji omówimy podstawowe pojęcia związane z modelami językowymi (LLM). Zrozumienie tych pojęć jest kluczowe dla skutecznego wykorzystania LLM w różnych zastosowaniach.
Czym jest LLM?
LLM to model językowy, który został wytrenowany na dużych zbiorach danych tekstowych. Jego celem jest generowanie tekstu, który jest spójny i kontekstualny.
Jak działają LLM?
LLM działają na zasadzie analizy wzorców w danych treningowych. Używają zaawansowanych algorytmów, aby przewidzieć, jakie słowo lub fraza powinny pojawić się w danym kontekście.
Zastosowania LLM
LLM mogą być wykorzystywane w różnych dziedzinach, takich jak generowanie treści, tłumaczenie, chatboty i wiele innych.
Wyzwania związane z LLM
Pomimo ich potężnych możliwości, LLM mają również swoje ograniczenia, takie jak tendencyjność w danych treningowych i trudności w rozumieniu kontekstu.
Podsumowanie
Zrozumienie podstawowych pojęć związanych z LLM jest kluczowe dla ich efektywnego wykorzystania w praktyce.
cssCopy codeGradient w.r.t w: tensor([-0.0898])
Gradient w.r.t b: tensor([-0.0817])
Backpropagation w większych sieciach neuronowych
1. Rozszerzenie na sieci wielowarstwowe
W większych sieciach neuronowych z wieloma warstwami proces obliczania gradientów staje się bardziej złożony z powodu zwiększonej liczby parametrów i operacji. Jednak podstawowe zasady pozostają takie same:
- Forward Pass: Oblicz wyjście sieci, przekazując dane wejściowe przez każdą warstwę.
- Compute Loss: Oceń funkcję straty, używając wyjścia sieci i docelowych etykiet.
- Backward Pass (Backpropagation): Oblicz gradienty straty względem każdego parametru w sieci, stosując regułę łańcuchową rekurencyjnie od warstwy wyjściowej do warstwy wejściowej.
2. Algorytm Backpropagation
- Krok 1: Zainicjalizuj parametry sieci (wagi i biasy).
- Krok 2: Dla każdego przykładu treningowego wykonaj forward pass, aby obliczyć wyjścia.
- Krok 3: Oblicz stratę.
- Krok 4: Oblicz gradienty straty względem każdego parametru, stosując regułę łańcuchową.
- Krok 5: Zaktualizuj parametry, używając algorytmu optymalizacji (np. spadek gradientu).
3. Reprezentacja matematyczna
Rozważ prostą sieć neuronową z jedną ukrytą warstwą:
4. Implementacja w PyTorch
PyTorch upraszcza ten proces dzięki swojemu silnikowi 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}")
W tym kodzie:
- Forward Pass: Oblicza wyjścia sieci.
- Backward Pass:
loss.backward()
oblicza gradienty straty względem wszystkich parametrów. - Parameter Update:
optimizer.step()
aktualizuje parametry na podstawie obliczonych gradientów.
5. Zrozumienie Backward Pass
Podczas backward pass:
- PyTorch przeszukuje graf obliczeniowy w odwrotnej kolejności.
- Dla każdej operacji stosuje regułę łańcuchową do obliczania gradientów.
- Gradienty są akumulowane w atrybucie
.grad
każdego tensora parametru.
6. Zalety automatycznej różniczkowania
- Efektywność: Unika zbędnych obliczeń poprzez ponowne wykorzystanie wyników pośrednich.
- Dokładność: Zapewnia dokładne pochodne do precyzji maszyny.
- Łatwość użycia: Eliminuje ręczne obliczanie pochodnych.