Передача модели данных

Последнее обновление: 14.12.2025

Сама по себе нейронная сети не имеет значения, если в нее не передавать никакие данные. Поэтому рассмотрим на небольшом примере создание модели с передачей ей данных:

import torch
from torch import nn

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

# получаем устройство
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
# перемещаем на устройство
model = NeuralNetwork().to(device)
# формируем входные данные
X = torch.rand(1, 28, 28, device=device)
# передаем модели входные данные в виде тензора X
logits = model(X)
# выводим результат на консоль
print(logits)

После определения модели здесь формируем набор произвольных данных с помощью функции torch.rand():

X = torch.rand(1, 28, 28, device=device)

Фактичеси переменная X здесь представляет тензор с формой (1, 28, 28), где 1 - это размер батча (количество картинок), а 28, 28 - высота и ширина картинки.

Далее передаем эти данные в модель и получаем результат:

logits = model(X)

В своем методе forward() модель с помощью слоя self.flatten = nn.Flatten() "сплющивает" все измерения, начиная со второго (по умолчанию start_dim=1), н о сохраняет размер батча:

x = self.flatten(x)

В результате поулчаем тензор с формой (1, 784), где 1 - одна картинка, а 784 - результат умножения 28*28. В итоге self.flatten подготавливает "квадратные" данные изображения для "линейных" математических слоев нейросети, выстраивая пиксели в один ряд.

Далее полученный ряд передается в последовательность слоев нейронной сети, и возвращает ее результат:

logits = self.linear_relu_stack(x)
return logits

Этот результат мы получаем из модели и выводим на экран:

logits = model(X)
print(logits)

При вызове model(X) модель выполняет метод forward и возвращает результат. Результат (logits) представляет "сырые", ненормализованные предсказания модели. Они могут быть любыми действительными числами (от -infty до +infty).

В итоге мы получим что-о вроде следующего (вывод недетерминирован):

tensor([[-0.0073,  0.0543,  0.0810, -0.0022,  0.0184, -0.0557,  0.1095,  0.0098,
         -0.0218,  0.0296]], device='cuda:0', grad_fn=<AddmmBackward0>)

Вызов модели на входных данных возвращает двумерный тензор размером [1, 10], который содержит 10 чисел. Чем больше число по определенному индексу, тем больше сеть "уверена", что входные данные соответствуют этому классу.

Таким образом, мы можем передавать в нейронную сеть некоторые данные и получать результат. Далее посмотрим, как передавать вместо произвольных значений данные изображений.

Применение Softmax

В конце для получения вероятностей предсказаний мы можем применить nn.Softmax:

import torch
from torch import nn

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

# получаем устройство
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
# перемещаем на устройство
model = NeuralNetwork().to(device)
# формируем входные данные
X = torch.rand(1, 28, 28, device=device)
# передаем модели входные данные в виде тензора X
logits = model(X)
# применяем функцию Softmax и получаем предсказанные моделью вероятности 
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)

print(pred_probab)

Пример консольного вывода:

tensor([[0.1080, 0.1021, 0.0954, 0.0943, 0.0896, 0.1022, 0.1085, 0.1006, 0.1006,
         0.0985]], device='cuda:0', grad_fn=<SoftmaxBackward0>)

Передача FashionMNIST в модель

Аналогичным образом мы можем передать на вход нейронной сети не просто произвольные теноры, а готовые наборы данных, например, встроенный датасет FashionMNIST. Но здесь надо учитывать, что модель ожидает на вход тензор (массив чисел, который представляет изображение). Класс FashionMNIST - это своего рода "контейнер", который хранит ссылки на данные, но сам по себе не является данными для вычислений. Чтобы извлечь данные из датасета, можно использовать DataLoader (загрузчик данных) для подачи данных пакетами (батчами):

import torch
from torch import nn
from torchvision import datasets
from torch.utils.data import DataLoader # Импортируем загрузчик
from torchvision.transforms import ToTensor, Lambda

# нейронная сеть
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits


# набор для обучения
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
    target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
)

# DataLoader берет данные из training_data и собирает их в пакеты (batch)
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)

# получаем устройство
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
# перемещаем нейронную сеть на устройство
model = NeuralNetwork().to(device)

# Получаем пакет (batch) данных для проверки
# next(iter(...)) берет первый пакет из загрузчика
train_features, train_labels = next(iter(train_dataloader))

# Перемещаем данные на то же устройство, где находится модель
train_features = train_features.to(device)

# Передаем модели тензор, а не объект датасета
logits = model(train_features)

# выводим форму тензора
print(logits.shape) # Ожидается [64, 10]
# можно вывесть и сам тензор, но он будет очень большим
# print(logits)

Основные моменты

  1. train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)

    Вместо прямой работы с training_data, мы обернули этот набор в DataLoader. Это позволяет автоматически собирать отдельные картинки в "пачки" (батчи). Нейросети обучаются гораздо эффективнее, когда видят сразу 64 или 128 картинок за раз, а не по одной.

  2. Извлечение тензора

    train_features, train_labels = next(iter(train_dataloader))

    Здесь мы извлекаем реальные данные (картинки train_features и метки train_labels), где train_features - это тензор размером [64, 1, 28, 28] (64 картинки, 1 канал цвета, 28x28 пикселей).

  3. model(train_features)

    Передача в модель тензора с числами.

Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850