Основы нейронных сетей
🎯 Цель
После прочтения этой главы:
- Поймёте, что такое нейронная сеть и как она устроена
- Узнаете Perceptron, MLP, activation functions, loss functions
- Поймёте алгоритмы Forward pass и Backpropagation
- Узнаете Gradient Descent и его варианты
- Сможете написать простую NN на чистом NumPy
Что нужно изучить
- Perceptron — простейший «neuron»
- Multi-Layer Perceptron (MLP) — глубже
- Activation functions — ReLU, Sigmoid, Tanh, Softmax
- Loss functions — MSE, CrossEntropy, Binary CrossEntropy
- Forward pass — путь input → output
- Backpropagation — вычисление gradients
- Варианты Gradient Descent — SGD, Momentum, Adam, RMSprop
- Universal Approximation Theorem — почему работают NN
Библиотеки
pip install numpy matplotlib torch torchvision
Важные темы
Perceptron — простейший neuron
input ─x₁──┐
input ─x₂──┤── (weighted sum) ── activation ── output
input ─x₃──┘
↑
bias
z = w₁x₁ + w₂x₂ + w₃x₃ + b
a = activation(z)
Activation functions — зачем нужны?
Если activation нет, вся NN — одна большая linear regression. Activation добавляет nonlinearity.
| Function | Формула | Диапазон | Когда |
|---|---|---|---|
| Sigmoid | 1/(1+e^-x) | (0, 1) | Binary classification output |
| Tanh | (e^x - e^-x)/(e^x + e^-x) | (-1, 1) | Hidden layers (старое) |
| ReLU | max(0, x) | [0, ∞) | Hidden layers (default) |
| Leaky ReLU | max(0.01x, x) | (-∞, ∞) | Проблема dying neuron в ReLU |
| Softmax | e^xᵢ / Σe^xⱼ | (0, 1), sum=1 | Multi-class output |
| GELU | x * Φ(x) | ~ReLU | В Transformers |
Архитектура MLP
Input Layer Hidden Layer 1 Hidden Layer 2 Output Layer
[x₁] [h₁₁] [h₂₁]
[x₂] ──W₁,b₁──> [h₁₂] ──W₂,b₂──> [h₂₂] ──W₃,b₃──> [y]
[x₃] [h₁₃] [h₂₃]
[x₄] [h₁₄]
input shape: (n,)
W₁ shape: (hidden_1, n)
W₂ shape: (hidden_2, hidden_1)
W₃ shape: (1, hidden_2)
Loss functions
| Задача | Loss | Формула |
|---|---|---|
| Регрессия | MSE | mean((y - ŷ)²) |
| Регрессия | MAE | `mean( |
| Binary Class. | BCE | -mean(y·log(ŷ) + (1-y)·log(1-ŷ)) |
| Multi-class | CCE | -mean(Σ yᵢ·log(ŷᵢ)) |
Backpropagation — распространение градиентов «назад»
Forward: input → ... → output → loss
│
Backward: ∂loss/∂w ← ... ← ∂loss/∂a ← ─┘
Chain rule:
∂L/∂w = ∂L/∂a × ∂a/∂z × ∂z/∂w
В PyTorch/TensorFlow это автоматически (autograd). Но важно понимать интуицию.
Optimizers
| Optimizer | Описание | Default LR |
|---|---|---|
| SGD | Vanilla gradient descent | 0.01 |
| SGD + Momentum | Добавлена инерция | 0.01, momentum=0.9 |
| Adam | Adaptive, default choice | 0.001 |
| AdamW | Adam + better weight decay | 0.001 |
| RMSprop | Adaptive learning rate | 0.001 |
**Совет:**начните с Adam или AdamW. Когда придёт время tuning — попробуйте другие.
Примеры кода
MLP на чистом NumPy (для интуиции)
import numpy as np
class SimpleMLP:
def __init__(self, input_size, hidden_size, output_size):
# Xavier initialization
self.W1 = np.random.randn(hidden_size, input_size) * np.sqrt(2 / input_size)
self.b1 = np.zeros(hidden_size)
self.W2 = np.random.randn(output_size, hidden_size) * np.sqrt(2 / hidden_size)
self.b2 = np.zeros(output_size)
def relu(self, x):
return np.maximum(0, x)
def relu_derivative(self, x):
return (x > 0).astype(float)
def softmax(self, x):
# Numerical stability
exp_x = np.exp(x - np.max(x, axis=1, keepdims=True))
return exp_x / exp_x.sum(axis=1, keepdims=True)
def forward(self, X):
# X shape: (batch, input_size)
self.z1 = X @ self.W1.T + self.b1
self.a1 = self.relu(self.z1)
self.z2 = self.a1 @ self.W2.T + self.b2
self.a2 = self.softmax(self.z2)
return self.a2
def backward(self, X, y_true, learning_rate=0.01):
# y_true: one-hot encoded
batch_size = X.shape[0]
# Output layer gradient
dz2 = (self.a2 - y_true) / batch_size
dW2 = dz2.T @ self.a1
db2 = dz2.sum(axis=0)
# Hidden layer gradient
da1 = dz2 @ self.W2
dz1 = da1 * self.relu_derivative(self.z1)
dW1 = dz1.T @ X
db1 = dz1.sum(axis=0)
# Update weights
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
def train(self, X, y, epochs=100, batch_size=32, learning_rate=0.01):
for epoch in range(epochs):
# Mini-batch
indices = np.random.permutation(len(X))
for start in range(0, len(X), batch_size):
batch_idx = indices[start:start + batch_size]
X_batch = X[batch_idx]
y_batch = y[batch_idx]
self.forward(X_batch)
self.backward(X_batch, y_batch, learning_rate)
# Track loss
y_pred = self.forward(X)
loss = -np.mean(np.sum(y * np.log(y_pred + 1e-9), axis=1))
if epoch % 10 == 0:
print(f"Epoch {epoch}: Loss = {loss:.4f}")
# Пример — Iris (3-class)
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
X = StandardScaler().fit_transform(X)
y_onehot = np.eye(3)[y]
model = SimpleMLP(input_size=4, hidden_size=16, output_size=3)
model.train(X, y_onehot, epochs=200, batch_size=16, learning_rate=0.05)
То же самое в PyTorch — ЗНАЧИТЕЛЬНО проще
import torch
import torch.nn as nn
import torch.optim as optim
class SimpleMLP(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super().__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x # logits (softmax внутри loss)
model = SimpleMLP(4, 16, 3)
optimizer = optim.Adam(model.parameters(), lr=0.05)
loss_fn = nn.CrossEntropyLoss()
X_t = torch.tensor(X, dtype=torch.float32)
y_t = torch.tensor(y, dtype=torch.long)
for epoch in range(200):
optimizer.zero_grad()
logits = model(X_t)
loss = loss_fn(logits, y_t)
loss.backward() # backprop автоматически
optimizer.step()
if epoch % 20 == 0:
accuracy = (logits.argmax(dim=1) == y_t).float().mean()
print(f"Epoch {epoch}: Loss={loss.item():.4f}, Acc={accuracy.item():.4f}")
**Внимание:**такой же результат — pure NumPy 60 строк, PyTorch 20 строк. Productivity = framework.
Интеграция с backend
Пока (основы) — эта глава теоретическая. Production deployment подробно в главе PyTorch и месяце 6 MLOps.
Но ментальная модель: NN — это математическая функция. Как backend dev, вы всегда:
input→output(REST API ровно так же)- Stateless (weights — параметры функции)
- Нужен versioning (model_v1.pt, model_v2.pt)
- Мониторинг (latency, prediction distribution)
Ресурсы
- 3Blue1Brown — Neural Networks playlist(YouTube) — визуально, MUST WATCH
- Andrew Ng — Deep Learning Specialization (Course 1) — теоретические основы
- “Neural Networks and Deep Learning” — Michael Nielsen (бесплатно: neuralnetworksanddeeplearning.com)
- Andrej Karpathy — “Neural Networks: Zero to Hero”(YouTube) — мощный практический курс
- fast.ai — Practical Deep Learning(бесплатный курс)
🏋️ Упражнения
🟢 Easy
- Нарисуйте Sigmoid, ReLU, Tanh функции через Matplotlib.
- Для линейной функции
2x + 1найдитеwиb, минимизирующие MSE loss, через gradient descent. - Создайте
nn.Linear(10, 1)в PyTorch и запустите forward pass для random tensor.
🟡 Medium
- NumPy MLP: настройте код выше на Iris dataset до 90%+ accuracy.
- XOR problem: решите XOR через 2-layer MLP.
- PyTorch vs Numpy speed: сравните training time для модели с 1M параметров.
🔴 Hard
- From-scratch backprop — 3 hidden layer MLP, dropout, batchnorm — всё на чистом NumPy.
- Visualize: нарисуйте loss landscape PyTorch-модели (3D plot по 2 weights).
Capstone
notebooks/month-03/01_neural_network_scratch.ipynb:
- Напишите 2-layer MLP на NumPy
- Обучите на маленькой выборке MNIST (1000 samples, 10 classes)
- Напишите то же самое в PyTorch
- Сравните accuracy и training time
✅ Чек-лист
- Знаю разницу между Perceptron и MLP
- Знаю, когда применять ReLU, Sigmoid, Softmax
- Понимаю интуицию Forward pass и Backprop
- Знаю разницу между Gradient Descent, SGD, Adam
- Знаю, когда применять CrossEntropy, а когда MSE
- Пишу простой
nn.Moduleв PyTorch - Умею строить простой MLP на чистом NumPy
Переходим к Основам PyTorch.