Шпаргалка по training pipeline в PyTorch на одной странице
Краткая шпаргалка по базовому пайплайну обучения в PyTorch: tensors, nn.Module, autograd, backpropagation, gradient descent и optimizer step.
Источник: пост kozue в X.
Вся «машина» deep learning работает за счёт крошечных, непрерывных корректировок весов модели.
Это шпаргалка по training pipeline в PyTorch. Если заметите ошибки или захотите предложить улучшения — оставляйте комментарии. Надеюсь, материал будет полезен.
1. Tensor
В PyTorch тензор — это базовая структура данных для хранения и обработки чисел, основной строительный блок нейронных сетей.
Input:
data= [[1,2,3],[4,5,6]]
x = torch.tensor(data)Output:
tensor([[1, 2, 3],
[4, 5, 6]])Q. Что внутри тензора?
Три вещи: shape, dtype и device.
- Shape: кортеж, описывающий размерности. Около 90% ошибок в PyTorch — это несовпадение shape.
- DType: тип данных чисел.
- Device: где находится тензор — CPU или CUDA/GPU.
Если код ломается, обычно причина в том, что одно из этих трёх свойств не совпало.
Input:
#attributes of tensor
tensor = torch.randn(2,3)
print("shape:", tensor.shape)
print("datatype:", tensor.dtype)
print("device:", tensor.device)Output:
shape: torch.Size([2, 3])
datatype: torch.float32
device: cpuПо умолчанию тензор — это просто данные. Чтобы сделать его обучаемым параметром, нужно установить requires_grad=True. После этого PyTorch начинает строить вычислительный граф и записывать каждую операцию над тензором, чтобы затем автоматически вычислить градиенты при backpropagation.
Input:
#data vs parameter
#standard data tensor
x_data = torch.tensor([[1.,2.],[3.,4.]])
#parameter tensor
w = torch.tensor([[1.0],[2.0]], requires_grad=True)
print("Data tensor requires_grad:",x_data.requires_grad)
print("Parameter tensor requires_grad:", w.requires_grad)Output:
Data tensor requires_grad: False
Parameter tensor requires_grad: TrueQ. Что такое параметр?
Это специальный тензор, у которого requires_grad=True по умолчанию. Он автоматически регистрируется внутри модели и берёт на себя служебную «бухгалтерию» обучения.
2. Models
Модель — это архитектура нейронной сети, описанная как Python-объект, наследующийся от базового класса torch.nn.Module.
- Модель — это просто
nn.Module, содержащий слои. - Слой — это контейнер параметров, выполняющих математическую операцию.
- Обучение — это обновление параметров через
zero_grad,backward,step. - Параметры модели — веса и bias — должны быть float-типа, обычно
float32.
Q. Почему float32?
Веса должны изменяться на очень маленькие величины. С целыми числами это невозможно. Числа с плавающей точкой позволяют модели делать микроскопические улучшения на каждой итерации.
Самая простая нейронная сеть:
y = X @ W + bгде:
y→ предсказаниеX→ входW→ весаb→ bias/смещение
Prediction = Input × Knowledge + Adjustment
3. Matrix Multiplication
X @ WЭто сердце deep learning. Почти каждая современная нейронная сеть построена на повторяющихся матричных умножениях.
Используйте оператор @, когда строите линейный слой. В PyTorch @ выполняет matrix multiplication — ключевую операцию за каждым nn.Linear.
Правило: число столбцов M1 = числу строк M2.
Input:
#Matrix Multiplication
#shape (2,3)
m1 = torch.tensor([[1,2,3], [4,5,6]])
#shape {3,2)
m2 = torch.tensor([[7,8], [9,10], [11,12]])
#shape (2,2)
matrix_product = m1 @ m2
print(matrix_product)Output:
tensor([[ 58, 64],
[139, 154]])Не путайте @ и *: @ делает матричное умножение, а * перемножает соответствующие элементы один к одному.
4. Autograd: автоматическое дифференцирование
torch.autograd — это движок автоматического дифференцирования PyTorch, на котором держится обучение нейронных сетей. Во время forward pass он динамически строит направленный ациклический граф (DAG), отслеживает операции над тензорами и позволяет автоматически вычислять градиенты через backpropagation.
Autograd фактически говорит: «пройди назад от loss и вычисли градиенты для всех параметров с requires_grad=True».
Input:
#y=2x+1
#batch of data has 10 points
N=10
#each data point has 1 input feature and 1 output value
D_in = 1
D_out = 1
#create out input data X
X = torch.randn(N, D_in)
#create our true target labels y by using the "true" W,B
#the "true" W is 2.0, the "true" b is 1.0
true_w = torch.tensor([[2.0]])
true_b = torch.tensor([[1.0]])
y_true = X @ true_w + true_b + torch.randn(N, D_out) * 1.0 #added littile noise
W = torch.randn(D_in, D_out, requires_grad = True)
b = torch.randn(1, requires_grad = True)
print("Initial Weight W:\n",W)
print("Initial bias b:\n",b)
y_hat = X @ W + b
print(y_hat)
#error
error = y_hat - y_true
squared_error = error ** 2
loss = squared_error.mean()
print("Loss:",loss,"\n")
loss.backward()
print("gradient for w:\n", W.grad)
print("gradient for b:\n", b.grad)Output:
Initial Weight W:
tensor([[-0.5669]], requires_grad=True)
Initial bias b:
tensor([0.0011], requires_grad=True)
tensor([[ 0.0604],
[ 0.5645],
[ 0.6193],
[-0.2863],
[ 1.2082],
[ 0.6468],
[ 0.5936],
[-0.2940],
[ 0.6108],
[ 0.8328]], grad_fn=<AddBackward0>)
Loss: tensor(6.5599, grad_fn=<MeanBackward0>)
gradient for w:
tensor([[-5.0230]])
gradient for b:
tensor([1.8041])5. Backpropagation: backward pass
loss.backward()∂L/∂w= градиент loss по весуw.∂L/∂b= градиент loss по biasb.
Они вычисляются автоматически через loss.backward().
6. Gradient Descent: оптимизация
После вычисления градиентов мы обновляем параметры модели, чтобы уменьшить loss.
Правило обновления:
New Weight = Old Weight - Learning Rate × GradientГде:
θ(theta) = параметры модели: веса и bias.η(eta) = learning rate.∇θL= градиент loss по параметрам, напримерw.grad,b.grad.
Input:
#training (gradient descent)
#Hyperparameters
learning_rate, epochs = 0.01, 100
#re-initialize parameters
W,b = torch.randn(1,1, requires_grad=True), torch.randn(1, requires_grad=True)
#Training Loop
for epoch in range(epochs):
#forward pass and loss
y_hat = X @ W + b
loss = torch.mean((y_hat - y_true)**2)
#backward pass
loss.backward()
#update parameters
with torch.no_grad():
W -= learning_rate * W.grad; b -= learning_rate * b.grad
#zero gradients (reset for new learning cycle)
W.grad.zero_(); b.grad.zero_()
print(W.grad,"\n",b.grad)7. nn.Module
Вместо того чтобы писать всё вручную, PyTorch предоставляет готовые строительные блоки:
nn.Linearnn.ReLUnn.GELUnn.Softmaxnn.Embeddingnn.LayerNormnn.Dropout
Это переиспользуемые компоненты нейросетей.
Input:
#NN.LINEAR
#input has 1 feature ans the putput has 1 value
D_in = 1
D_out = 1
linear_layer = torch.nn.Linear(in_features=D_in, out_features=D_out)
print("Layer's weight (W):" ,linear_layer.weight)
print("Layer's bias (b):", linear_layer.bias)
#forward pass
y_hat_nn = linear_layer(X)
print("Output of nn.Liner (first 3):\n", y_hat_nn[:3])Output:
Layer's weight (W): Parameter containing:
tensor([[0.5193]], requires_grad=True)
Layer's bias (b): Parameter containing:
tensor([-0.2911], requires_grad=True)
Output of nn.Liner (first 3):
tensor([[-0.3454],
[-0.8072],
[-0.8574]], grad_fn=<SliceBackward0>)Input:
#NN.RELU (RECTIFIED LINEAR UNIT)
#Rule: if an input is negative make it zero 'ReLU(x)=max(0,x)'
relu = torch.nn.ReLU()
sample_data = torch.tensor([-2.0,-5.0,0.0,0.5,2.0])
activated_data = relu(sample_data)
print("Original Data:", sample_data)
print("Data after ReLU:", activated_data)Output:
Original Data: tensor([-2.0000, -5.0000, 0.0000, 0.5000, 2.0000])
Data after ReLU: tensor([0.0000, 0.0000, 0.0000, 0.5000, 2.0000])Input:
#NN.GELU (GAUSSIAN ERROR LINEAR UNIT)
#modern standard for transformers (GPT,Llama). A smoother, gently curving version of ReLU
gelu = torch.nn.GELU()
sample_data = torch.tensor([-2.0,-0.5,0.0,0.5,2.0])
activated_data = gelu(sample_data)
print("Original Data:", sample_data)
print("Data after gelu:",activated_data)Output:
Original Data: tensor([-2.0000, -0.5000, 0.0000, 0.5000, 2.0000])
Data after gelu: tensor([-0.0455, -0.1543, 0.0000, 0.3457, 1.9545])Input:
#NN.SOFTMAX
#used on final output layer for classification
#converts logits -> probability distribution
softmax = torch.nn.Softmax(dim=-1)
logits = torch.tensor([[1.0,3.0,0.5,1.5],[-1.0,2.0,1.0,0.0]])
prob = softmax(logits)
print("output prob:", prob)
print("sum of prob:", prob[0].sum())Output:
output prob: tensor([[0.0939, 0.6942, 0.0570, 0.1549],
[0.0321, 0.6439, 0.2369, 0.0871]])
sum of prob: tensor(1.)Input:
#NN.EMBEDDING
#turns word -> numbers
vocab_size = 10
embedding_dim = 3
embedding_layer = torch.nn.Embedding(vocab_size, embedding_dim)
input_ids = torch.tensor([[1,5,0,8]])
word_vector = embedding_layer(input_ids)
word_vectorOutput:
tensor([[[-0.3875, -1.7026, -0.8399],
[-0.3027, -0.0060, 0.7160],
[-2.0736, 0.3490, -0.0605],
[ 1.3206, 0.8779, 0.4340]]], grad_fn=<EmbeddingBackward0>)Input:
#nn.layernorm
#prevents values from exploding/vanishing, it rescales to stable range
norm_layer = torch.nn.LayerNorm(normalized_shape=3)
input_features = torch.tensor([[1.0,2.0,3.0],[4.0,5.0,6.0]])
normalized_features = norm_layer(input_features)
print("Mean (should be ~0):", normalized_features.mean(dim=-1))
print("std dev (should be ~1):", normalized_features.std(dim=-1))Output:
Mean (should be ~0): tensor([0., 0.], grad_fn=<MeanBackward1>)
std dev (should be ~1): tensor([1.2247, 1.2247], grad_fn=<StdBackward0>)Input:
#NN.DROPOUT
#prevent overfitting, randomly zero neurons during training forces network robustness
dropout_layer = torch.nn.Dropout(p=0.5)
input_tensor = torch.ones(1,10)
dropout_layer.train()
output_during_train = dropout_layer(input_tensor)
dropout_layer.eval()
output_during_eval = dropout_layer(input_tensor)8. Правило трёх
optimizer.zero_grad()loss.backward()optimizer.step()
9. Demo toy model
import torch
import torch.nn as nn
print(torch.cuda.is_available())
class LinearRegressionModel(nn.Module):
def __init__(self,in_features,out_features):
super().__init__()
#inside the constructor, we define the layer
self.linear_layer = nn.Linear(in_features, out_features)
def forward(self, x):
#in the forward pass, we connect the layers
return self.linear_layer(x)
model = LinearRegressionModel(in_features=1, out_features=1)
print("Model Architecture:")
print(model)
#torch.optim
import torch.optim as optim
#hyperaramater
learning_rate = 0.01
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
loss_fn = nn.MSELoss()
epochs = 100
for epoch in range(epochs):
#forward pass
y_hat = model(X)
loss = loss_fn(y_hat,y_true)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 ==0:
print("Epoch:",epoch,"Loss:",loss.item())Output:
TRUE
Model Architecture:
LinearRegressionModel(
(linear_layer): Linear(in_features=1, out_features=1, bias=True)
)
Epoch: 0 Loss: 11.082582473754883
Epoch: 10 Loss: 9.987239837646484
Epoch: 20 Loss: 8.982141494750977
Epoch: 30 Loss: 8.073999404907227
Epoch: 40 Loss: 7.263952732086182
Epoch: 50 Loss: 6.5487494468688965
Epoch: 60 Loss: 5.9224066734313965
Epoch: 70 Loss: 5.377523899078369
Epoch: 80 Loss: 4.90612268447876
Epoch: 90 Loss: 4.500123500823975Надеюсь, это поможет чуть лучше понять PyTorch. Удачной сборки.