Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Основы нейронных сетей

🎯 Цель

После прочтения этой главы:

  • Поймёте, что такое нейронная сеть и как она устроена
  • Узнаете 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ФормулаДиапазонКогда
Sigmoid1/(1+e^-x)(0, 1)Binary classification output
Tanh(e^x - e^-x)/(e^x + e^-x)(-1, 1)Hidden layers (старое)
ReLUmax(0, x)[0, ∞)Hidden layers (default)
Leaky ReLUmax(0.01x, x)(-∞, ∞)Проблема dying neuron в ReLU
Softmaxe^xᵢ / Σe^xⱼ(0, 1), sum=1Multi-class output
GELUx * Φ(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Формула
РегрессияMSEmean((y - ŷ)²)
РегрессияMAE`mean(
Binary Class.BCE-mean(y·log(ŷ) + (1-y)·log(1-ŷ))
Multi-classCCE-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
SGDVanilla gradient descent0.01
SGD + MomentumДобавлена инерция0.01, momentum=0.9
AdamAdaptive, default choice0.001
AdamWAdam + better weight decay0.001
RMSpropAdaptive learning rate0.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, вы всегда:

  • inputoutput (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

  1. Нарисуйте Sigmoid, ReLU, Tanh функции через Matplotlib.
  2. Для линейной функции 2x + 1 найдите w и b, минимизирующие MSE loss, через gradient descent.
  3. Создайте nn.Linear(10, 1) в PyTorch и запустите forward pass для random tensor.

🟡 Medium

  1. NumPy MLP: настройте код выше на Iris dataset до 90%+ accuracy.
  2. XOR problem: решите XOR через 2-layer MLP.
  3. PyTorch vs Numpy speed: сравните training time для модели с 1M параметров.

🔴 Hard

  1. From-scratch backprop — 3 hidden layer MLP, dropout, batchnorm — всё на чистом NumPy.
  2. 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.