Проект для распознавания рукописных цифр (от 0 до 9) с использованием библиотеки PyTorch и датасета MNIST.
Цель проекта — научить компьютер распознавать рукописные цифры с помощью нейронной сети. Используем датасет MNIST — популярный набор из 70,000 изображений цифр размером 28x28 пикселей.
Что делает проект:
- Загружает датасет MNIST
- Обучает простую нейронную сеть
- Тестирует модель на новых данных
- Показывает точность распознавания
- Визуализирует примеры цифр
- Python 3.x
- PyTorch - библиотека для создания нейронных сетей
- TorchVision - загрузка и обработка изображений
- NumPy - работа с массивами и числами
- Matplotlib - создание графиков и визуализаций
- tqdm - красивый индикатор прогресса
- Клонируйте репозиторий:
git clone https://github.com/Gando4lapi/-Multilayer-Perceptron-Determining-the-handmade-number-using-PyTorch
cd -Multilayer-Perceptron-Determining-the-handmade-number-using-PyTorch- Установите зависимости:
pip install torch torchvision numpy matplotlib tqdmВ представленном коде создаётся многослойный персептрон для MNIST: импортируются библиотеки, определяется класс модели с тремя полносвязными слоями и ReLU между ними, загружается датасет, настраиваются загрузчики, функция потерь и оптимизатор.
import torch — подключает ядро PyTorch: тензоры, автодифференцирование, устройство CPU/GPU.
import torch.nn as nn — модуль нейронных сетей с готовыми слоями и базовым классом nn.Module.
import torch.nn.functional as F — функциональные версии операций (ReLU, Conv2d и т.д.); в текущем фрагменте не используется, но часто вызывают F.relu.
from torchvision import datasets, transforms — наборы данных и преобразования изображений; отсюда берётся MNIST и превращение в тензоры.
import numpy as np — библиотека численных массивов; прямо в этом коде не используется.
import matplotlib.pyplot as plt — построение графиков; прямо в этом коде не используется.
from tqdm.notebook import tqdm — прогресс‑бар, удобный в Jupyter для визуализации итераций обучения/теста.
class MNIST_Multilayer_Perceptron(nn.Module): — объявляет класс модели как наследника nn.Module, чтобы PyTorch мог зарегистрировать слои и их параметры.
def init(self): — конструктор класса; здесь создаются и регистрируются слои модели. Важно именно двойное подчёркивание с обеих сторон.
super().init() — инициализация базового nn.Module; регистрирует внутренние структуры для параметров и подмодулей.
self.net = nn.Sequential( ... ) — контейнер, который последовательно применяет слои:
nn.Linear(784, 256) — полносвязный слой, принимает развёрнутое изображение 28×28=784 признаков и выводит 256 признаков.
nn.ReLU() — нелинейная активация поэлементно, добавляет выразительность.
nn.Linear(256, 128) — второй полносвязный слой: 256 → 128.
nn.ReLU() — вторая нелинейность.
nn.Linear(128, 10) — выходной слой: 10 логитов (по одному на класс цифры 0–9).
def forward(self, x): — метод прямого прохода; определяет вычисление выхода по входу.
return self.net(x) — прогоняет вход через последовательность слоёв и возвращает логиты без softmax (он встроен внутрь CrossEntropyLoss).
Важно: ранее у вас были ошибки из‑за опечаток init вместо init, super.init вместо super().init и из‑за того, что forward был с неправильным отступом внутри конструктора. Это приводило к пустому списку параметров у модели и ошибке оптимизатора. В рабочем варианте имя конструктора и super должны быть с двойными подчёркиваниями, а forward — на том же уровне отступа, что и init.
mnist_train = datasets.MNIST(root="./datasets", train=True, transform=transforms.ToTensor(), download=True) — загружает тренировочную часть MNIST в папку ./datasets; ToTensor преобразует PIL‑изображение 28×28 в тензор формы с нормированием значений в.
mnist_test = datasets.MNIST(root="./datasets", train=False, transform=transforms.ToTensor(), download=True) — загружает тестовую часть аналогично.
train_loader = torch.utils.data.DataLoader(mnist_train, batch_size=100, shuffle=True) — итератор по мини‑батчам тренировочных данных: по 100 изображений, с перемешиванием батчей перед каждой эпохой.
test_loader = torch.utils.data.DataLoader(mnist_test, batch_size=100, shuffle=False) — итератор по тестовым данным: по 100 изображений, без перемешивания.
Практический совет: к ToTensor() обычно добавляют Normalize((0.1307,), (0.3081,)) для стандартизации MNIST, что помогает обучению.
model = MNIST_Multilayer_Perceptron() — создаёт экземпляр МLP с тремя линейными слоями и двумя ReLU.
criterion = nn.CrossEntropyLoss() — функция потерь для многоклассовой классификации; ожидает сырые логиты размера [batch, 10] и целочисленные метки классов [batch].
optimizer = torch.optim.SGD(model.parameters(), lr=0.1) — оптимизатор стохастического градиентного спуска; получает список параметров модели (веса и смещения слоёв) и шаг обучения 0.1. При желании можно добавить momentum=0.9 или заменить на Adam(lr=1e-3).
Если при создании оптимизатора появляется ValueError: optimizer got an empty parameter list, почти всегда проблема в том, что слои не зарегистрированы (например, из‑за init вместо init) или optimizer создаётся до инициализации модели. После исправления конструктора и порядка строк ошибка исчезнет.
Перед обучением включают режим обучения: model.train().
В цикле по train_loader на каждом батче:
optimizer.zero_grad() — обнуляет накопленные градиенты.
x = images.view(-1, 28*28) — разворачивает батч из формы [B, 1, 28, 28] в [B, 784] для подачи в линейный слой.
y = model(x) — прямой проход, получаем логиты [B, 10].
loss = criterion(y, labels) — вычисление кросс‑энтропии.
loss.backward() — обратное распространение градиентов.
optimizer.step() — обновление параметров.
model.eval() — включает режим оценки (важно при наличии Dropout/BatchNorm).
with torch.no_grad(): — отключает вычисление градиентов для экономии ресурсов.
Прогон по test_loader: разворот входа, прямой проход, preds = torch.argmax(y, dim=1), сравнение с labels и подсчёт доли верных предсказаний.
Технические детали:
- Тип: Многослойный персептрон (нелинейный классификатор)
- Входной размер: 784 (28×28 пикселей)
- Выходной размер: 10 (классы 0-9)
- Функция потерь: CrossEntropyLoss
- Оптимизатор: SGD с learning rate = 0.1
- Точность на тестовых данных: ~91%
Капник Данил
- GitHub: @Gando4lapi
- Email: kapnik.dan@gmail.com
⭐ Поставьте звездочку, если проект был полезен!