Разработка реального и продвинутого ИИ‑проекта на Python

Введение

В этой статье мы рассмотрим разработку реального проекта машинного обучения на языке Python с использованием нейронных сетей. Будем строить модель для классификации изображений, подробно объясняя каждый шаг и весь исходный код.

t.me/ai_machinelearning_big_data – здесь мы показываем самые топовые Ai инструменты и разьираем как работать с ними, на это стоит посмотреть.

Постановка задачи

Мы создаём классификатор рукописных цифр на основе нейронной сети. Задача — определить цифру на изображении из набора MNIST, содержащего тысячи изображен

Настройка окружения

Для начала подготовим виртуальное окружение и установим необходимые библиотеки.

# Создаём виртуальное окружение и активируем его
python3 -m venv venv
source venv/bin/activate

# Устанавливаем PyTorch и torchvision
pip install torch torchvision

В этом коде мы создаём изолированную среду и ставим фреймворк PyTorch, который будем использовать для построения сети и работы с данными.

Подготовка данных

Теперь подготовим набор данных. Мы будем использовать встроенный датасет MNIST из библиотеки torchvision. Сначала определим трансформации для нормализации изображений и преобразования их в тензоры. Затем загрузим обучающую и тестовую выборки, автоматически скачивая их при первом запуске. Наконец, создадим загрузчики данных (DataLoader) с указанным размером батча и перемешиванием.

from torchvision import datasets, transforms
from torch.utils.data import DataLoader

transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])

train_dataset = datasets.MNIST(root="./data", train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root="./data", train=False, download=True, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)

В данном коде мы определяем цепочку преобразований для изображений, которые нормализуют значения пикселей. Затем создаём экземпляры классов MNIST для обучающей и тестовой выборок, где указана директория хранения данных и применяемая трансформация. DataLoader разбивает датасет на батчи и обеспечивает удобный итератор с возможностью перемешивания.

Проектирование модели

Мы спроектируем простую сверчточную нейронную сеть (CNN), которая будет состоять из нескольких сверчточных слоев с активацией ReLU и слоев субдискретизации (MaxPool). Затем, после преобразования карты признаков в вектор, добавим полносвязные слои для классификации десяти цифр.

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

class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)

def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 64 * 7 * 7)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x

В этом классе мы определяем два сверчточных слоя, каждый из которых увеличивает количество каналов, а функция MaxPool2d уменьшает размер карты признаков. После двух сверчточных блоков мы преобразуем тензор в плоский вектор и передаём его в два полносвязных слоя. В результате сеть выводит 10-мерный вектор вероятностей для каждой цифры.

Обучение модели

Для обучения модели мы используем функцию потерь CrossEntropyLoss, которая подходит для многоклассовой классификации, и оптимизатор Adam для адаптивного подбора весов. В ходе обучения мы итерируемся по мини‑батчам обучающего набора, вычисляем выходные данные сети, рассчитываем значение потерь, производим обратное распространение ошибки (backpropagation) и обновляем параметры модели. Повторив несколько эпох, модель постепенно минимизирует функцию потерь и улучшает точность.

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)


def train(model, device, train_loader, optimizer, criterion, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if batch_idx % 100 == 0:
print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} '
f'({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}')

for epoch in range(1, 6):
train(model, device, train_loader, optimizer, criterion, epoch)

Этот код определяет функцию train, которая принимает модель, устройство, загрузчик данных, оптимизатор, функцию потерь и номер эпохи. Она ставит модель в режим обучения, проходится по мини‑батчам, пересылает данные на GPU/CPU, вычисляет прогнозы, считает потери, выполняет обратное распространение и обновляет веса. В конце каждой сотой итерации она выводит информацию о прогрессе. Затем цикл эпох запускает функцию train пять раз для обучения модели на пяти эпохах.

Оценка и применение

После завершения обучения модель необходимо оценить на отложенной тестовой выборке. Мы переводим модель в режим оценки (eval), отключая слои Dropout и BatchNorm, и проходим по тестовому набору без обновления градиентов. Затем мы вычисляем точность классификации, сравнивая предсказания модели и реальные метки. Мы также можем применять модель для прогнозирования меток для новых изображений, предварительно применив те же преобразования.

def evaluate(model, device, test_loader):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
outputs = model(data)
_, predicted = torch.max(outputs.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()
accuracy = 100. * correct / total
print(f"Test Accuracy: {accuracy:.2f}%")
return accuracy
evaluate(model, device, test_loader)
def predict(model, device, image_tensor):
model.eval()
with torch.no_grad():
image_tensor = image_tensor.to(device).unsqueeze(0) # add batch dimension and move to device
output = model(image_tensor)
_, predicted_label = torch.max(output.data, 1)
return predicted_label.item()

Функция evaluate переводит модель в режим оценки, проходится по тестовым данным без вычисления градиентов, подсчитывает количество правильных предсказаний и выводит точность. Функция predict позволяет выполнить инференс для одного изображения: мы добавляем размер батча, передаем изображение в модель и по максимальному логиту определяем предсказанный класс.

Заключение

В этой статье мы подробно рассмотрели процесс создания реального и продвинутого проекта ИИ на Python. Мы определили задачу классификации рукописных цифр, подготовили окружение, загрузили и нормализовали данные, спроектировали свёрточную нейронную сеть, обучили модель, оценили её точность и реализовали функции для последующего применения. На практике вы можете улучшить проект, экспериментируя с архитектурой, увеличивая глубину сети, применяя регуляризацию, а также оптимизируя гиперпараметры. Такой системный подход позволяет создавать надёжные и масштабируемые ИИ‑решения.

Разработка реального и продвинутого ИИ‑проекта на Python

+1
2
+1
2
+1
0
+1
0
+1
1

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *