Глибоке навчання

Reading time: 21 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Глибоке навчання

Глибоке навчання є підмножиною машинного навчання, яка використовує нейронні мережі з кількома шарами (глибокі нейронні мережі) для моделювання складних патернів у даних. Воно досягло вражаючого успіху в різних сферах, включаючи комп'ютерне зору, обробку природної мови та розпізнавання мови.

Нейронні мережі

Нейронні мережі є будівельними блоками глибокого навчання. Вони складаються з взаємопов'язаних вузлів (нейронів), організованих у шари. Кожен нейрон отримує вхідні дані, застосовує зважену суму та передає результат через функцію активації для отримання виходу. Шари можна класифікувати наступним чином:

  • Вхідний шар: Перший шар, який отримує вхідні дані.
  • Сховані шари: Проміжні шари, які виконують перетворення вхідних даних. Кількість схованих шарів і нейронів у кожному шарі може варіюватися, що призводить до різних архітектур.
  • Вихідний шар: Останній шар, який генерує вихід мережі, наприклад, ймовірності класів у завданнях класифікації.

Функції активації

Коли шар нейронів обробляє вхідні дані, кожен нейрон застосовує вагу та зміщення до вхідних даних (z = w * x + b), де w — це вага, x — вхід, а b — зміщення. Вихід нейрона потім передається через функцію активації, щоб ввести нелінійність у модель. Ця функція активації вказує, чи повинен наступний нейрон "активуватися і на скільки". Це дозволяє мережі вивчати складні патерни та зв'язки в даних, що дозволяє їй апроксимувати будь-яку неперервну функцію.

Отже, функції активації вводять нелінійність у нейронну мережу, дозволяючи їй вивчати складні зв'язки в даних. Загальні функції активації включають:

  • Sigmoid: Відображає вхідні значення в діапазоні від 0 до 1, часто використовується в бінарній класифікації.
  • ReLU (Rectified Linear Unit): Виводить вхід безпосередньо, якщо він позитивний; в іншому випадку, виводить нуль. Широко використовується через свою простоту та ефективність у навчанні глибоких мереж.
  • Tanh: Відображає вхідні значення в діапазоні від -1 до 1, часто використовується в схованих шарах.
  • Softmax: Перетворює сирі оцінки в ймовірності, часто використовується у вихідному шарі для багатокласової класифікації.

Зворотне поширення

Зворотне поширення — це алгоритм, що використовується для навчання нейронних мереж шляхом коригування ваг зв'язків між нейронами. Він працює, обчислюючи градієнт функції втрат щодо кожної ваги та оновлюючи ваги в протилежному напрямку градієнта, щоб мінімізувати втрати. Кроки, що входять до зворотного поширення, включають:

  1. Прямий прохід: Обчислити вихід мережі, пропустивши вхід через шари та застосувавши функції активації.
  2. Обчислення втрат: Обчислити втрати (помилку) між передбаченим виходом та справжньою метою, використовуючи функцію втрат (наприклад, середньоквадратична помилка для регресії, крос-ентропія для класифікації).
  3. Зворотний прохід: Обчислити градієнти втрат щодо кожної ваги, використовуючи правило ланцюга з математичного аналізу.
  4. Оновлення ваг: Оновити ваги, використовуючи алгоритм оптимізації (наприклад, стохастичний градієнтний спуск, Adam), щоб мінімізувати втрати.

Згорткові нейронні мережі (CNN)

Згорткові нейронні мережі (CNN) — це спеціалізований тип нейронної мережі, призначений для обробки даних у вигляді сітки, таких як зображення. Вони особливо ефективні в завданнях комп'ютерного зору завдяки своїй здатності автоматично вивчати просторові ієрархії ознак.

Основні компоненти CNN включають:

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

Усередині CNN Згорткові шари також можна розрізнити:

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

tip

CNN особливо ефективні для класифікації зображень, виявлення об'єктів та сегментації зображень завдяки їх здатності вивчати просторові ієрархії ознак у даних у вигляді сітки та зменшувати кількість параметрів через спільне використання ваг. Більше того, вони працюють краще з даними, що підтримують принцип локальності ознак, де сусідні дані (пікселі) більш ймовірно пов'язані, ніж віддалені пікселі, що може не бути випадком для інших типів даних, таких як текст. Крім того, зверніть увагу, як CNN зможуть ідентифікувати навіть складні ознаки, але не зможуть застосувати жодний просторовий контекст, що означає, що одна й та ж ознака, знайдена в різних частинах зображення, буде однаковою.

Приклад визначення CNN

Тут ви знайдете опис того, як визначити Згорткову Нейронну Мережу (CNN) у PyTorch, яка починається з пакету RGB зображень розміром 48x48 і використовує згорткові шари та максимальну підвибірку для виділення ознак, після чого йдуть повністю з'єднані шари для класифікації.

Ось як ви можете визначити 1 згортковий шар у PyTorch: self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1).

  • in_channels: Кількість вхідних каналів. У випадку RGB зображень це 3 (по одному для кожного кольорового каналу). Якщо ви працюєте з чорно-білими зображеннями, це буде 1.

  • out_channels: Кількість вихідних каналів (фільтрів), які навчиться згортковий шар. Це гіперпараметр, який ви можете налаштувати залежно від архітектури вашої моделі.

  • kernel_size: Розмір згорткового фільтра. Загальним вибором є 3x3, що означає, що фільтр покриває область 3x3 вхідного зображення. Це як кольоровий штамп 3×3×3, який використовується для генерації вихідних каналів з вхідних каналів:

  1. Помістіть цей штамп 3×3×3 у верхній лівий кут куба зображення.
  2. Помножте кожну вагу на піксель під ним, додайте їх усі, додайте зміщення → ви отримуєте одне число.
  3. Запишіть це число в порожню карту на позиції (0, 0).
  4. Зсунути штамп на один піксель вправо (крок = 1) і повторюйте, поки не заповните всю сітку 48×48.
  • padding: Кількість пікселів, доданих до кожної сторони вхідних даних. Доповнення допомагає зберегти просторові розміри вхідних даних, дозволяючи більше контролювати розмір виходу. Наприклад, з ядром 3x3 та вхідними даними 48x48 пікселів, доповнення 1 зберігає розмір виходу таким же (48x48) після операції згортки. Це тому, що доповнення додає кордон з 1 пікселя навколо вхідного зображення, дозволяючи ядру ковзати по краях, не зменшуючи просторові розміри.

Тоді кількість навчальних параметрів у цьому шарі становить:

  • (3x3x3 (розмір ядра) + 1 (зміщення)) x 32 (вихідні канали) = 896 навчальних параметрів.

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

plaintext
Y = f(W * X + b)

де W - це матриця ваг (навчені фільтри, 3x3x3 = 27 параметрів), b - це вектор зсуву, який дорівнює +1 для кожного вихідного каналу.

Зверніть увагу, що вихід self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1) буде тензором форми (batch_size, 32, 48, 48), оскільки 32 - це нова кількість згенерованих каналів розміром 48x48 пікселів.

Тоді ми можемо підключити цей згортковий шар до іншого згорткового шару, як: self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1).

Це додасть: (32x3x3 (розмір ядра) + 1 (зсув)) x 64 (вихідні канали) = 18,496 навчальних параметрів і вихід форми (batch_size, 64, 48, 48).

Як ви можете бачити, кількість параметрів швидко зростає з кожним додатковим згортковим шаром, особливо коли збільшується кількість вихідних каналів.

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

Це можна оголосити як: self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2). Це в основному вказує на використання сітки з 2x2 пікселів і взяття максимального значення з кожної сітки, щоб зменшити розмір карти ознак вдвічі. Більше того, stride=2 означає, що операція підсумовування буде переміщатися на 2 пікселі за раз, у цьому випадку запобігаючи будь-якому перекриттю між областями підсумовування.

З цим шаром підсумовування вихідна форма після першого згорткового шару буде (batch_size, 64, 24, 24) після застосування self.pool1 до виходу self.conv2, зменшуючи розмір до 1/4 від попереднього шару.

tip

Важливо підсумовувати після згорткових шарів, щоб зменшити просторові розміри карт ознак, що допомагає контролювати кількість параметрів і обчислювальну складність, зберігаючи при цьому важливі ознаки. Ви можете розглядати згортки перед шаром підсумовування як спосіб витягнення ознак з вхідних даних (як лінії, краї), ця інформація все ще буде присутня у підсумованому виході, але наступний згортковий шар не зможе бачити оригінальні вхідні дані, лише підсумований вихід, який є зменшеною версією попереднього шару з цією інформацією. У звичайному порядку: Conv → ReLU → Pool кожне вікно підсумовування 2×2 тепер конкурує з активаціями ознак (“край присутній / відсутній”), а не з сирими інтенсивностями пікселів. Збереження найсильнішої активації дійсно зберігає найзначніші докази.

Тоді, після додавання стільки згорткових і підсумкових шарів, скільки потрібно, ми можемо сплющити вихід, щоб подати його в повнозв'язні шари. Це робиться шляхом зміни форми тензора в 1D вектор для кожного зразка в партії:

python
x = x.view(-1, 64*24*24)

І з цим 1D вектором з усіма параметрами навчання, згенерованими попередніми згортковими та пулінговими шарами, ми можемо визначити повнозв'язний шар, як:

python
self.fc1 = nn.Linear(64 * 24 * 24, 512)

Який візьме сплющений вихід попереднього шару і відобразить його на 512 прихованих одиницях.

Зверніть увагу, що цей шар додав (64 * 24 * 24 + 1 (bias)) * 512 = 3,221,504 навчальних параметрів, що є значним збільшенням у порівнянні з згортковими шарами. Це пов'язано з тим, що повнозв'язні шари з'єднують кожен нейрон в одному шарі з кожним нейроном в наступному шарі, що призводить до великої кількості параметрів.

Нарешті, ми можемо додати вихідний шар для отримання фінальних логітів класу:

python
self.fc2 = nn.Linear(512, num_classes)

Це додасть (512 + 1 (bias)) * num_classes навчальних параметрів, де num_classes - це кількість класів у завданні класифікації (наприклад, 43 для набору даних GTSRB).

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

python
self.dropout = nn.Dropout(0.5)

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

CNN Code example

python
import torch
import torch.nn as nn
import torch.nn.functional as F

class MY_NET(nn.Module):
def __init__(self, num_classes=32):
super(MY_NET, self).__init__()
# Initial conv layer: 3 input channels (RGB), 32 output channels, 3x3 kernel, padding 1
# This layer will learn basic features like edges and textures
self.conv1 = nn.Conv2d(
in_channels=3, out_channels=32, kernel_size=3, padding=1
)
# Output: (Batch Size, 32, 48, 48)

# Conv Layer 2: 32 input channels, 64 output channels, 3x3 kernel, padding 1
# This layer will learn more complex features based on the output of conv1
self.conv2 = nn.Conv2d(
in_channels=32, out_channels=64, kernel_size=3, padding=1
)
# Output: (Batch Size, 64, 48, 48)

# Max Pooling 1: Kernel 2x2, Stride 2. Reduces spatial dimensions by half (1/4th of the previous layer).
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
# Output: (Batch Size, 64, 24, 24)

# Conv Layer 3: 64 input channels, 128 output channels, 3x3 kernel, padding 1
# This layer will learn even more complex features based on the output of conv2
# Note that the number of output channels can be adjusted based on the complexity of the task
self.conv3 = nn.Conv2d(
in_channels=64, out_channels=128, kernel_size=3, padding=1
)
# Output: (Batch Size, 128, 24, 24)

# Max Pooling 2: Kernel 2x2, Stride 2. Reduces spatial dimensions by half again.
# Reducing the dimensions further helps to control the number of parameters and computational complexity.
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
# Output: (Batch Size, 128, 12, 12)

# From the second pooling layer, we will flatten the output to feed it into fully connected layers.
# The feature size is calculated as follows:
# Feature size = Number of output channels * Height * Width
self._feature_size = 128 * 12 * 12

# Fully Connected Layer 1 (Hidden): Maps flattened features to hidden units.
# This layer will learn to combine the features extracted by the convolutional layers.
self.fc1 = nn.Linear(self._feature_size, 512)

# Fully Connected Layer 2 (Output): Maps hidden units to class logits.
# Output size MUST match num_classes
self.fc2 = nn.Linear(512, num_classes)

# Dropout layer configuration with a dropout rate of 0.5.
# This layer is used to prevent overfitting by randomly setting a fraction of the input units to zero during training.
self.dropout = nn.Dropout(0.5)

def forward(self, x):
"""
The forward method defines the forward pass of the network.
It takes an input tensor `x` and applies the convolutional layers, pooling layers, and fully connected layers in sequence.
The input tensor `x` is expected to have the shape (Batch Size, Channels, Height, Width), where:
- Batch Size: Number of samples in the batch
- Channels: Number of input channels (e.g., 3 for RGB images)
- Height: Height of the input image (e.g., 48 for 48x48 images)
- Width: Width of the input image (e.g., 48 for 48x48 images)
The output of the forward method is the logits for each class, which can be used for classification tasks.
Args:
x (torch.Tensor): Input tensor of shape (Batch Size, Channels, Height, Width)
Returns:
torch.Tensor: Output tensor of shape (Batch Size, num_classes) containing the class logits.
"""

# Conv1 -> ReLU -> Conv2 -> ReLU -> Pool1 -> Conv3 -> ReLU -> Pool2
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.pool1(x)
x = self.conv3(x)
x = F.relu(x)
x = self.pool2(x)
# At this point, x has shape (Batch Size, 128, 12, 12)

# Flatten the output to feed it into fully connected layers
x = torch.flatten(x, 1)

# Apply dropout to prevent overfitting
x = self.dropout(x)

# First FC layer with ReLU activation
x = F.relu(self.fc1(x))

# Apply Dropout again
x = self.dropout(x)
# Final FC layer to get logits
x = self.fc2(x)
# Output shape will be (Batch Size, num_classes)
# Note that the output is not passed through a softmax activation here, as it is typically done in the loss function (e.g., CrossEntropyLoss)
return x

CNN Code training example

Наступний код створить деякі навчальні дані та навчить модель MY_NET, визначену вище. Деякі цікаві значення, на які слід звернути увагу:

  • EPOCHS - це кількість разів, коли модель побачить весь набір даних під час навчання. Якщо EPOCH занадто малий, модель може не навчитися достатньо; якщо занадто великий, вона може перенавчитися.
  • LEARNING_RATE - це розмір кроку для оптимізатора. Малий коефіцієнт навчання може призвести до повільної збіжності, тоді як великий може перевищити оптимальне рішення і завадити збіжності.
  • WEIGHT_DECAY - це термін регуляризації, який допомагає запобігти перенавчанню, караючи великі ваги.

Щодо циклу навчання, ось деяка цікава інформація, яку слід знати:

  • criterion = nn.CrossEntropyLoss() - це функція втрат, що використовується для задач багатокласової класифікації. Вона поєднує активацію softmax і функцію втрат крос-ентропії в одній функції, що робить її придатною для навчання моделей, які видають логіти класів.
  • Якщо від моделі очікувалося б видавати інші типи виходів, такі як бінарна класифікація або регресія, ми б використовували інші функції втрат, такі як nn.BCEWithLogitsLoss() для бінарної класифікації або nn.MSELoss() для регресії.
  • optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY) ініціалізує оптимізатор Adam, який є популярним вибором для навчання моделей глибокого навчання. Він адаптує коефіцієнт навчання для кожного параметра на основі перших і других моментів градієнтів.
  • Інші оптимізатори, такі як optim.SGD (Стохастичний градієнтний спуск) або optim.RMSprop, також можуть бути використані, залежно від специфічних вимог навчального завдання.
  • Метод model.train() встановлює модель в режим навчання, дозволяючи шарам, таким як dropout і нормалізація пакетів, поводитися інакше під час навчання в порівнянні з оцінкою.
  • optimizer.zero_grad() очищає градієнти всіх оптимізованих тензорів перед зворотним проходом, що необхідно, оскільки градієнти за замовчуванням накопичуються в PyTorch. Якщо їх не очистити, градієнти з попередніх ітерацій будуть додані до поточних градієнтів, що призведе до неправильних оновлень.
  • loss.backward() обчислює градієнти втрат відносно параметрів моделі, які потім використовуються оптимізатором для оновлення ваг.
  • optimizer.step() оновлює параметри моделі на основі обчислених градієнтів і коефіцієнта навчання.
python
import torch, torch.nn.functional as F
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from tqdm import tqdm
from sklearn.metrics import classification_report, confusion_matrix
import numpy as np

# ---------------------------------------------------------------------------
# 1. Globals
# ---------------------------------------------------------------------------
IMG_SIZE      = 48               # model expects 48×48
NUM_CLASSES   = 10               # MNIST has 10 digits
BATCH_SIZE    = 64               # batch size for training and validation
EPOCHS        = 5                # number of training epochs
LEARNING_RATE = 1e-3             # initial learning rate for Adam optimiser
WEIGHT_DECAY  = 1e-4             # L2 regularisation to prevent overfitting

# Channel-wise mean / std for MNIST (grayscale ⇒ repeat for 3-channel input)
MNIST_MEAN = (0.1307, 0.1307, 0.1307)
MNIST_STD  = (0.3081, 0.3081, 0.3081)

# ---------------------------------------------------------------------------
# 2. Transforms
# ---------------------------------------------------------------------------
# 1) Baseline transform: resize + tensor (no colour/aug/no normalise)
transform_base = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)),      # 🔹 Resize – force all images to 48 × 48 so the CNN sees a fixed geometry
transforms.Grayscale(num_output_channels=3),  # 🔹 Grayscale→RGB – MNIST is 1-channel; duplicate into 3 channels for convnet
transforms.ToTensor(),                        # 🔹 ToTensor – convert PIL image [0‒255] → float tensor [0.0‒1.0]
])

# 2) Training transform: augment  + normalise
transform_norm = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)),      # keep 48 × 48 input size
transforms.Grayscale(num_output_channels=3),  # still need 3 channels
transforms.RandomRotation(10),                # 🔹 RandomRotation(±10°) – small tilt ⇢ rotation-invariance, combats overfitting
transforms.ColorJitter(brightness=0.2,
contrast=0.2),         # 🔹 ColorJitter – pseudo-RGB brightness/contrast noise; extra variety
transforms.ToTensor(),                        # convert to tensor before numeric ops
transforms.Normalize(mean=MNIST_MEAN,
std=MNIST_STD),          # 🔹 Normalize – zero-centre & scale so every channel ≈ N(0,1)
])

# 3) Test/validation transform: only resize + normalise (no aug)
transform_test = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)),      # same spatial size as train
transforms.Grayscale(num_output_channels=3),  # match channel count
transforms.ToTensor(),                        # tensor conversion
transforms.Normalize(mean=MNIST_MEAN,
std=MNIST_STD),          # 🔹 keep test data on same scale as training data
])

# ---------------------------------------------------------------------------
# 3. Datasets & loaders
# ---------------------------------------------------------------------------
train_set = datasets.MNIST("data",   train=True,  download=True, transform=transform_norm)
test_set  = datasets.MNIST("data",   train=False, download=True, transform=transform_test)

train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True)
test_loader  = DataLoader(test_set,  batch_size=256,          shuffle=False)

print(f"Training on {len(train_set)} samples, validating on {len(test_set)} samples.")

# ---------------------------------------------------------------------------
# 4. Model / loss / optimiser
# ---------------------------------------------------------------------------
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model  = MY_NET(num_classes=NUM_CLASSES).to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY)

# ---------------------------------------------------------------------------
# 5. Training loop
# ---------------------------------------------------------------------------
for epoch in range(1, EPOCHS + 1):
model.train()                          # Set model to training mode enabling dropout and batch norm

running_loss = 0.0                     # sums batch losses to compute epoch average
correct      = 0                       # number of correct predictions
total        = 0                       # number of samples seen

# tqdm wraps the loader to show a live progress-bar per epoch
for X_batch, y_batch in tqdm(train_loader, desc=f"Epoch {epoch}", leave=False):
# 3-a) Move data to GPU (if available) ----------------------------------
X_batch, y_batch = X_batch.to(device), y_batch.to(device)

# 3-b) Forward pass -----------------------------------------------------
logits = model(X_batch)            # raw class scores (shape: [B, NUM_CLASSES])
loss   = criterion(logits, y_batch)

# 3-c) Backward pass & parameter update --------------------------------
optimizer.zero_grad()              # clear old gradients
loss.backward()                    # compute new gradients
optimizer.step()                   # gradient → weight update

# 3-d) Statistics -------------------------------------------------------
running_loss += loss.item() * X_batch.size(0)     # sum of (batch loss × batch size)
preds   = logits.argmax(dim=1)                    # predicted class labels
correct += (preds == y_batch).sum().item()        # correct predictions in this batch
total   += y_batch.size(0)                        # samples processed so far

# 3-e) Epoch-level metrics --------------------------------------------------
epoch_loss = running_loss / total
epoch_acc  = 100.0 * correct / total
print(f"[Epoch {epoch}] loss = {epoch_loss:.4f} | accuracy = {epoch_acc:.2f}%")

print("\n✅ Training finished.\n")

# ---------------------------------------------------------------------------
# 6. Evaluation on test set
# ---------------------------------------------------------------------------
model.eval() # Set model to evaluation mode (disables dropout and batch norm)
with torch.no_grad():
logits_all, labels_all = [], []
for X, y in test_loader:
logits_all.append(model(X.to(device)).cpu())
labels_all.append(y)
logits_all = torch.cat(logits_all)
labels_all = torch.cat(labels_all)
preds_all  = logits_all.argmax(1)

test_loss = criterion(logits_all, labels_all).item()
test_acc  = (preds_all == labels_all).float().mean().item() * 100

print(f"Test loss: {test_loss:.4f}")
print(f"Test accuracy: {test_acc:.2f}%\n")

print("Classification report (precision / recall / F1):")
print(classification_report(labels_all, preds_all, zero_division=0))

print("Confusion matrix (rows = true, cols = pred):")
print(confusion_matrix(labels_all, preds_all))

Рекурентні нейронні мережі (RNN)

Рекурентні нейронні мережі (RNN) — це клас нейронних мереж, призначених для обробки послідовних даних, таких як часові ряди або природна мова. На відміну від традиційних прямопотокових нейронних мереж, RNN мають з'єднання, які повертаються на самих себе, що дозволяє їм підтримувати прихований стан, який захоплює інформацію про попередні входи в послідовності.

Основні компоненти RNN включають:

  • Рекурентні шари: Ці шари обробляють вхідні послідовності по одному кроку часу, оновлюючи свій прихований стан на основі поточного входу та попереднього прихованого стану. Це дозволяє RNN вивчати тимчасові залежності в даних.
  • Прихований стан: Прихований стан — це вектор, який підсумовує інформацію з попередніх кроків часу. Він оновлюється на кожному кроці часу і використовується для прогнозування поточного входу.
  • Вихідний шар: Вихідний шар генерує фінальні прогнози на основі прихованого стану. У багатьох випадках RNN використовуються для завдань, таких як моделювання мови, де вихід є ймовірнісним розподілом наступного слова в послідовності.

Наприклад, у мовній моделі RNN обробляє послідовність слів, наприклад, "Кіт сидів на" і прогнозує наступне слово на основі контексту, наданого попередніми словами, у цьому випадку "килим".

Довгострокова пам'ять (LSTM) та Гейтована рекурентна одиниця (GRU)

RNN особливо ефективні для завдань, що включають послідовні дані, такі як моделювання мови, машинний переклад і розпізнавання мови. Однак вони можуть мати проблеми з дальніми залежностями через такі проблеми, як зникнення градієнтів.

Щоб вирішити цю проблему, були розроблені спеціалізовані архітектури, такі як Довгострокова пам'ять (LSTM) та Гейтована рекурентна одиниця (GRU). Ці архітектури вводять механізми гейтування, які контролюють потік інформації, що дозволяє їм більш ефективно захоплювати дальні залежності.

  • LSTM: Мережі LSTM використовують три гейти (вхідний гейт, гейт забуття та вихідний гейт) для регулювання потоку інформації в клітинному стані та з нього, що дозволяє їм запам'ятовувати або забувати інформацію протягом довгих послідовностей. Вхідний гейт контролює, скільки нової інформації додати на основі входу та попереднього прихованого стану, гейт забуття контролює, скільки інформації відкинути. Поєднуючи вхідний гейт і гейт забуття, ми отримуємо новий стан. Нарешті, поєднуючи новий клітинний стан з входом і попереднім прихованим станом, ми також отримуємо новий прихований стан.
  • GRU: Мережі GRU спрощують архітектуру LSTM, поєднуючи вхідний і гейт забуття в один гейт оновлення, що робить їх обчислювально більш ефективними, при цьому все ще захоплюючи дальні залежності.

LLMs (Великі мовні моделі)

Великі мовні моделі (LLMs) — це тип моделі глибокого навчання, спеціально розроблений для завдань обробки природної мови. Вони навчаються на величезних обсягах текстових даних і можуть генерувати текст, схожий на людський, відповідати на запитання, перекладати мови та виконувати різні інші завдання, пов'язані з мовою. LLMs зазвичай базуються на архітектурах трансформерів, які використовують механізми самоуваги для захоплення відносин між словами в послідовності, що дозволяє їм розуміти контекст і генерувати зв'язний текст.

Архітектура трансформера

Архітектура трансформера є основою багатьох LLM. Вона складається з структури кодувальника-декодувальника, де кодувальник обробляє вхідну послідовність, а декодувальник генерує вихідну послідовність. Ключові компоненти архітектури трансформера включають:

  • Механізм самоуваги: Цей механізм дозволяє моделі оцінювати важливість різних слів у послідовності при генерації представлень. Він обчислює оцінки уваги на основі відносин між словами, що дозволяє моделі зосереджуватися на відповідному контексті.
  • Багатоголове увага: Цей компонент дозволяє моделі захоплювати кілька відносин між словами, використовуючи кілька голів уваги, кожна з яких зосереджується на різних аспектах входу.
  • Позиційне кодування: Оскільки трансформери не мають вбудованого поняття порядку слів, до вхідних векторів додається позиційне кодування, щоб надати інформацію про позицію слів у послідовності.

Моделі дифузії

Моделі дифузії — це клас генеративних моделей, які навчаються генерувати дані, імітуючи процес дифузії. Вони особливо ефективні для завдань, таких як генерація зображень, і набули популярності в останні роки. Моделі дифузії працюють, поступово перетворюючи простий розподіл шуму в складний розподіл даних через серію кроків дифузії. Ключові компоненти моделей дифузії включають:

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

Більше того, щоб згенерувати зображення з текстового запиту, моделі дифузії зазвичай виконують такі кроки:

  1. Кодування тексту: Текстовий запит кодується в латентне представлення за допомогою кодувальника тексту (наприклад, моделі на основі трансформера). Це представлення захоплює семантичне значення тексту.
  2. Вибірка шуму: Випадковий вектор шуму вибирається з гауссового розподілу.
  3. Кроки дифузії: Модель застосовує серію кроків дифузії, поступово перетворюючи вектор шуму в зображення, яке відповідає текстовому запиту. Кожен крок передбачає застосування навчальних перетворень для зменшення шуму в зображенні.

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks