Что такое ПиТорч?

PyTorch — это библиотека машинного обучения с открытым исходным кодом для Python. Он используется для разработки и обучения моделей глубокого обучения. Он разработан исследовательской группой искусственного интеллекта Facebook. PyTorch известен своей эффективностью, гибкостью и динамичностью. Это позволяет разработчикам выполнять вычисления с динамическими графами, что означает, что пользователь может изменять граф на лету во время выполнения. Это отличается от статических графов вычислений, которые используются в других библиотеках глубокого обучения, таких как TensorFlow. PyTorch широко используется в исследовательском сообществе, а также набирает популярность в отрасли.

Подробнее

PyTorch — это мощная платформа глубокого обучения с открытым исходным кодом, созданная на основе популярной библиотеки числовых вычислений NumPy. Он используется для таких приложений, как обработка естественного языка и компьютерное зрение. Одной из ключевых особенностей PyTorch является его способность автоматически вычислять градиенты, что делает его очень подходящим для обучения глубоких нейронных сетей.

В дополнение к базовой библиотеке PyTorch существует несколько популярных пакетов, созданных на основе PyTorch и предоставляющих дополнительные функции. Одним из таких пакетов является torchvision — библиотека компьютерного зрения, упрощающая обучение моделей в PyTorch. Он включает в себя широкий спектр наборов данных, архитектур моделей и распространенных преобразований изображений, что делает его полезным инструментом для быстрого построения и оценки моделей глубокого обучения для таких задач, как классификация изображений и обнаружение объектов.

Другой популярный пакет PyTorch — это torchtext, библиотека обработки естественного языка, которая предоставляет простые в использовании наборы данных и загрузчики данных для задач NLP. Он также включает популярные модели встраивания слов, такие как word2vec и GloVe, что упрощает включение этих моделей в ваши проекты НЛП. В целом, PyTorch и его различные пакеты предлагают мощный и гибкий набор инструментов для создания и обучения моделей глубокого обучения.

Установка PyTorch

Чтобы установить PyTorch, вы можете выполнить следующие действия:

  1. Во-первых, убедитесь, что у вас установлена ​​последняя версия pip, менеджера пакетов для Python. Вы можете проверить версию pip, которую вы установили, выполнив следующую команду:
pip --version

2. Если у вас нет последней версии pip, вы можете обновить ее, выполнив следующую команду:

pip install --upgrade pip

3. После установки последней версии pip вы можете установить PyTorch, выполнив следующую команду:

pip install torch

4. Если вы хотите установить определенную версию PyTorch, вы можете указать номер версии, выполнив следующую команду:

pip install torch==1.7.0

5. Если вы хотите установить PyTorch с поддержкой графического процессора, вам необходимо установить версию PyTorch для графического процессора. Это можно сделать, выполнив следующую команду:

pip install torch-gpu

6. После установки PyTorch вы можете проверить установку, запустив следующий код Python:

import torch
print(torch.__version__)

Это должно напечатать номер версии PyTorch, который вы установили.

Создание тензора

Создавать тензоры с помощью PyTorch очень просто. Чтобы создать тензор в PyTorch, вы можете использовать функцию torch.tensor. Эта функция принимает список или массив и возвращает тензор.

Например, чтобы создать тензор из списка:

import torch

# create a tensor 1D
torch.rand(10)
 
> tensor([0.5998, 0.7840, 0.1017, 0.5188, 0.7417, 0.3671, 0.7304, 0.4467, 0.7782, 0.0533])
 
# create a tensor 2D
torch.rand(4,4)
 
> tensor([[0.8032, 0.8408, 0.6130, 0.8030],
         [0.8343, 0.0078, 0.9008, 0.8328],
         [0.7299, 0.3207, 0.2760, 0.9779],
         [0.5821, 0.5505, 0.0618, 0.4833]])
 
# create a tensor integer
torch.randint(low=0, high=100, size=(4,))
 
> tensor([63, 74, 75, 71])
 
# create a tensor from list
torch.Tensor([1,2,3])
 
> tensor([1., 2., 3.])
 
# create a Long Tensor
torch.LongTensor([1,2,3])
 
> tensor([1, 2, 3])
 
torch.FloatTensor([1.1, 1.2, 1.3])
 
> tensor([1.1000, 1.2000, 1.3000])

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

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

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

softmax(x_i) = exp(x_i) / sum_j(exp(x_j))

где x_i — i-й элемент входного тензора, а sum_j(exp(x_j)) — сумма возведённых в степень элементов тензора.

Другой распространенной функцией активации является функция ReLU (выпрямленная линейная единица), которая определяется как:

relu(x) = max(0, x)

Функция ReLU выводит ввод, если он положительный, и выводит 0, если он отрицательный. Он широко используется, потому что он прост и хорошо работает во многих случаях.

Наконец, сигмовидная функция часто используется в задачах бинарной классификации. Он сопоставляет ввод со значением от 0 до 1, что позволяет легко интерпретировать его как вероятность. Сигмовидная функция определяется как:

sigmoid(x) = 1 / (1 + exp(-x))

Это лишь некоторые из многих функций активации, доступных в PyTorch. Дополнительную информацию о функциях активации и о том, как их использовать, можно найти в документации PyTorch.

Следующий код покажет нам, как мы можем реализовать функции активации для тензора.

import torch

x = torch.rand(10)
print(x)
 
> tensor([0.2791, 0.7676, 0.5146, 0.5865, 0.5029, 0.5618, 0.2659, 0.9412, 0.4960, 0.1228])
         
# apply softmax
torch.softmax(x, dim=0)
 
> tensor([0.0778, 0.1268, 0.0984, 0.1058, 0.0973, 0.1032, 0.0768, 0.1508, 0.0966, 0.0665])
         
# apply sigmoid
torch.sigmoid(x)
 
> tensor([0.5693, 0.6830, 0.6259, 0.6426, 0.6231, 0.6369, 0.5661, 0.7193, 0.6215, 0.5307])
         
# apply relu
torch.relu(x)
 
> tensor([0.2791, 0.7676, 0.5146, 0.5865, 0.5029, 0.5618, 0.2659, 0.9412, 0.4960, 0.1228])

Создайте архитектурную нейронную сеть (UNet для сегментации изображений)

Архитектура U-Net является популярным выбором для задач сегментации изображений, поскольку она способна обрабатывать маленькие и большие объекты и имеет хороший баланс между производительностью и скоростью. Вот один из способов построить U-Net для сегментации изображений с помощью PyTorch:

import torch
import torch.nn as nn


class UNet(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        
        # Encoder layers
        self.conv1 = nn.Conv2d(in_channels, 64, 3, padding=1)
        self.conv2 = nn.Conv2d(64, 64, 3, padding=1)
        self.pool1 = nn.MaxPool2d(2)
        
        self.conv3 = nn.Conv2d(64, 128, 3, padding=1)
        self.conv4 = nn.Conv2d(128, 128, 3, padding=1)
        self.pool2 = nn.MaxPool2d(2)
        
        self.conv5 = nn.Conv2d(128, 256, 3, padding=1)
        self.conv6 = nn.Conv2d(256, 256, 3, padding=1)
        self.pool3 = nn.MaxPool2d(2)
        
        self.conv7 = nn.Conv2d(256, 512, 3, padding=1)
        self.conv8 = nn.Conv2d(512, 512, 3, padding=1)
        self.pool4 = nn.MaxPool2d(2)
        
        self.conv9 = nn.Conv2d(512, 1024, 3, padding=1)
        self.conv10 = nn.Conv2d(1024, 1024, 3, padding=1)
        
        # Decoder layers
        self.up1 = nn.ConvTranspose2d(1024, 512, 2, stride=2)
        self.conv11 = nn.Conv2d(1024, 512, 3, padding=1)
        self.conv12 = nn.Conv2d(512, 512, 3, padding=1)
        
        self.up2 = nn.ConvTranspose2d(512, 256, 2, stride=2)
        self.conv13 = nn.Conv2d(512, 256, 3, padding=1)
        self.conv14 = nn.Conv2d(256, 256, 3, padding=1)
        
        self.up3 = nn.ConvTranspose2d(256, 128, 2, stride=2)
        self.conv15 = nn.Conv2d(256, 128, 3, padding=1)
        self.conv16 = nn.Conv2d(128, 128, 3, padding=1)
        
        self.up4 = nn.ConvTranspose2d(128, 64, 2, stride=2)
        self.conv17 = nn.Conv2d(128, 64, 3, padding=1)
        self.conv18 = nn.Conv2d(64, 64, 3, padding=1)
    
        self.conv19 = nn.Conv2d(64, out_channels, 3, padding=1)
        self.out = nn.Sigmoid()
    
    
    def forward(self, x):
        
        # Encoder
        x = self.conv1(x)
        x = self.conv2(x)
        x1 = self.pool1(x)
        
        x = self.conv3(x1)
        x = self.conv4(x)
        x2 = self.pool2(x)
        
        x = self.conv5(x2)
        x = self.conv6(x)
        x3 = self.pool3(x)
        
        x = self.conv7(x3)
        x = self.conv8(x)
        x4 = self.pool4(x)
        
        x = self.conv9(x4)
        x = self.conv10(x)
        
        # Decoder
        x = self.up1(x)
        x = torch.cat((x, x4), dim=1)
        x = self.conv11(x)
        x = self.conv12(x)
        
        x = self.up2(x)
        x = torch.cat((x, x3), dim=1)
        x = self.conv13(x)
        x = self.conv14(x)
        
        x = self.up3(x)
        x = torch.cat((x, x2), dim=1)
        x = self.conv15(x)
        x = self.conv16(x)
        
        x = self.up4(x)
        x = torch.cat((x, x1), dim=1)
        x = self.conv17(x)
        x = self.conv18(x)
        
        x = self.conv19(x)
        out = self.out(x)
        
        return out

Этот код определяет архитектуру U-Net, в которой часть кодера состоит из ряда сверточных слоев и слоев максимального объединения, а часть декодера состоит из ряда сверточных и транспонированных сверточных слоев. Выходные данные сети проходят через сигмовидную функцию активации, которая отображает выходные данные в диапазоне от 0 до 1.

Затем вы можете создать экземпляр U-Net, вызвав UNet(in_channels, out_channels), где in_channels — это количество каналов во входном изображении, а out_channels — это количество классов в задаче сегментации.

Чтобы создать экземпляр вышеуказанной модели UNet, вы можете использовать следующий код:

# Create an instance of the UNet model
model = UNet(in_channels=3, out_channels=2)
print(model)

Это создаст экземпляр модели UNet с 3 входными каналами (при условии, что входные изображения являются цветными изображениями с 3 каналами: красным, зеленым и синим) и 2 выходными классами. Оператор print(model) выводит сводку модели, включая количество обучаемых параметров.

Построить класс набора данных

Чтобы создать собственный класс набора данных в PyTorch, вы можете создать подкласс класса torch.utils.data.Dataset и переопределить следующие методы:

  • __init__: этот метод используется для инициализации набора данных и может использоваться для сохранения данных в памяти или на диске.
  • __len__: этот метод должен возвращать длину набора данных (т. е. количество выборок).
  • __getitem__: этот метод должен возвращать выборку из набора данных с заданным индексом.

Вот пример пользовательского класса набора данных для набора данных, содержащего изображения и метки:

import torch
from torch.utils.data import Dataset

class ImageLabelDataset(Dataset):
    def __init__(self, images, labels):
        self.images = images
        self.labels = labels
        
    def __len__(self):
        return len(self.images)
    
    def __getitem__(self, idx):
        image = self.images[idx]
        label = self.labels[idx]
        return image, label

Чтобы использовать этот класс набора данных, вы можете создать его экземпляр и передать его загрузчику данных PyTorch. Например:

# Create an instance of the dataset
dataset = ImageLabelDataset(images, labels)

# Create a data loader
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)

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

Оптимизатор и функция потерь

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

Оптимизаторы

В PyTorch есть несколько встроенных оптимизаторов и функций потерь, которые вы можете использовать в своих проектах. Некоторые популярные оптимизаторы включают в себя:

  • Стохастический градиентный спуск (SGD): простой и широко используемый оптимизатор, который обновляет параметры, используя градиент функции потерь по отношению к параметрам.
  • Адам: более продвинутый оптимизатор, который использует адаптивную скорость обучения и импульс для улучшения сходимости.

Чтобы использовать оптимизатор в PyTorch, вы можете создать экземпляр оптимизатора и передать его параметрам модели, которые вы хотите оптимизировать.

Функция потери

Некоторые популярные функции потерь в PyTorch включают в себя:

  • Перекрестная энтропийная потеря: широко используемая функция потерь для задач классификации. Он измеряет разницу между прогнозируемым распределением вероятностей по классам и истинным распределением вероятностей.
  • Среднеквадратическая ошибка (MSE): функция потерь, обычно используемая для задач регрессии. Он измеряет разницу между прогнозируемыми и истинными выходными данными, вычисляя квадрат разницы между ними.

Вот пример кода для нескольких функций оптимизатора и потерь в PyTorch.

# import modules
import torch.nn as nn
import torch.optim as optim
# define optimizer
# using Adam optimizer and learning rate = 0.001
optimizer = optim.Adam(model.parameters(), lr=1e-3)
 
print(optimizer)
 
# define loss function
# if the task is regression probem we can use Mean Squared Error
loss_fn = nn.MSELoss()
 
# if the task is binary classification problem, we can use BCELoss
loss_fn = nn.BCELoss()
 
# if the task is multiclass classification problem, we can use CrossEntropy
loss_fn = nn.CrossEntropyLoss()	

Тренировочная рутина

Чтобы создать программу обучения модели в PyTorch, выполните следующие действия:

  1. Задайте модель, оптимизатор и функцию потерь.
  2. Цикл по количеству эпох.
  3. Прокрутите данные в наборе обучающих данных, используя загрузчик данных.
  4. Передайте данные через модель, чтобы получить прогнозируемый результат.
  5. Вычислите потери, используя функцию потерь.
  6. Обратно распространите потерю, чтобы вычислить градиенты.
  7. Используйте оптимизатор, чтобы обновить параметры модели.
  8. При желании отслеживайте потери и другие показатели для каждой эпохи.

Вот пример процедуры обучения для модели PyTorch:

#Loop over numberof epochs
for epoch in range(num_epochs):
    # Loop over the data in the training dataset
    for data, target in dataloader:
        # Pass the data through the model
        output = model(data)
        
        # Compute the loss
        loss = loss_fn(output, target)
        
        # Backpropagate the loss and update the model parameters
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
    # Print the loss for each epoch
    print(f"Epoch {epoch}: Loss = {loss.item():.4f}")

Заключение

PyTorch — очень обширная библиотека, которую исследователи используют для создания и настройки моделей глубокого обучения для решения реальных задач. Я попытался предоставить обзор того, как мы можем устанавливать, настраивать и создавать модели с помощью PyTorch. Каждый раздел содержит независимый пример блока кода, чтобы познакомить вас с частью PyTorch, связанной с кодированием. Я надеюсь, что эта статья поможет вам познакомиться с PyTorch и создать модели для ваших собственных проектов и исследований.

Пожалуйста, не стесняйтесь обращаться ко мне, если у вас есть какие-либо вопросы или вам нужна помощь.
Электронная почта: [email protected]