Все, что вам нужно знать для вашего первого проекта в PyTorch!
Для экстремальных новичков - от новичков!
Предварительные требования:
Добро пожаловать, изучающие глубокое обучение! Эта статья станет началом вашего первого в истории проекта глубокого обучения на pytorch.
Чтобы получить право читать эту историю, убедитесь, что любой из этих пунктов лучше всего описывает вас:
- Вы должны быть тем, у кого есть «DL Enthusiast» в вашем профиле LinkedIn, но вы строите модели только с помощью keras! Поздравляю! эта статья полностью посвящена вам!
- Вам, должно быть, было трудно понять сеансы, переменные, классы и т. Д. В тензорном потоке и вы планировали перейти на pytorch. Ага! Вы находитесь в нужном месте!
- Вы тот, кто построил достаточно сложные модели в pytorch и ищет некоторые подробные вещи. Пока-пока! вы можете перейти к последнему разделу!
Фактический старт!
Если вы это читаете, поздравляем! вы полностью готовы к дальнейшим действиям!
Первый вопрос:
Что такое pytorch и чем он отличается от keras?
Как новичок, довольно легко построить нейронную сеть, добавив плотные слои и некоторые выпадения с помощью этих двух команд:
from keras.models import Sequential from keras.layers import Dense, Dropout
Это так же просто, как сказать….
import Andrew as ng !
Если вам нужно иметь дело с тензорами, строить достаточно сложные модели, создавать какие-то собственные функции потерь или понимать, что именно происходит внутри каждого отдельного слоя, pytorch спасает вас! Это идеальный инструмент для n-мерных данных! Он имеет упрощенный край keras-i в сочетании с множеством полезной документации.
Это удобно для новичков!
Pytorch известен своими возможностями отладки, отличной поддержкой сообщества и низкоуровневой абстракцией. Более быстрые реализации лучше выполнять с помощью pytorch, поскольку он не требует тяжелого вычислительного мусора, как в keras.
Погрузитесь в мир!
Шаг 1: Настройка оборудования. Модели глубокого обучения всегда сопровождаются большим количеством данных. Очевидно, нужен графический процессор. для настройки cuda и nvidia: обратитесь к этой замечательной статье.
Шаг 2: Установка: Pytorch устанавливается в течение нескольких секунд с помощью одной строки ctrl + C - ctrl + V со своего официального сайта. Перейдите на их веб-сайт, прокрутите вниз, выберите параметры настройки, скопируйте ссылку и вставьте ее в свой терминал! Выполнено! готов к использованию! Также установите tensorboardX для визуализации результатов. Обратитесь к этому репозиторию github для инструкций по установке.
Шаг 3: Основы: есть отличные курсы по udemy, в которых обсуждаются базовый синтаксис, использование и функции. Поверьте мне! pytorch не требует особых усилий! Он очень похож на Numpy и имеет множество предопределенных функций. Вы можете открывать для себя что-то, как только начнете кодировать.
Самое интересное!
Шаг 3: Импорт необходимого:
import torch import torch.nn as nn from torch.utils import data import torch.nn.functional as F from torch.autograd import Variable as V import torch.optim as optim from tqdm import tqdm from tensorboardX import SummaryWriter
Это библиотеки, необходимые для любой модели глубокого обучения. В модуле nn есть все необходимые функции потерь, слои, последовательные модели, функции активации и т. д. nn.functional - это особый сегмент, используемый для функций активации. Остальные обсуждаются по мере того, как вы продвигаетесь дальше.
Второй вопрос:
В чем разница между TorchTensor и переменной?
Вы, должно быть, заметили, что мы импортировали библиотеку переменных из torch.autograd. Тензоры - это просто nd-массивы. Для таких функций, как обратное распространение, тензоры должны быть связаны с соответствующим им градиентом. То же самое и с переменной torch. Это тензор с соответствующим градиентом, что значительно упрощает все тензорные операции! Взгляните на это вопросы и ответы, чтобы узнать подробности.
Имея все это основание, давайте приступим к построению нашей модели!
Первый этап: класс сети:
шаг 1: Наследование:. Чтобы построить архитектуру нейронной сети, необходимо создать класс, унаследованный от nn.Module. nn.Module дает структуру для создания нашей сети.
class Network(nn.Module): def __init__(self): super(Network, self).__init__()
шаг 2: Слои: различные типы слоев, такие как линейный, LSTM, выпадающий и т. д., непосредственно присутствуют в модуле nn. Если вы привыкли к настройке последовательной модели keras, то nn.sequential точно такой же. Лично я предлагаю не использовать последовательный, поскольку он не раскрывает истинную цель использования pytorch. Лучший способ добавить слои к вашей модели:
- Создайте один слой с nn и назначьте его частному члену вашего сетевого класса.
Выглядит это примерно так:
self.linear = nn.linear(input dim, output dim)
Объявите все ваши слои как переменные класса в init вашего сетевого класса.
Шаг 3. Функция пересылки. Это сердце и душа вашей сети. Каждый раз, когда вы вызываете свою архитектуру для обучения или прогнозирования, выполняются шаги, которые вы записываете в функции пересылки. Здесь мы перезаписываем функцию пересылки из класса nn.Module, который точно сообщает модели, что делать. Если вы укажете какие-либо параметры для своей функции forward, кроме self, они должны передаваться каждый раз при вызове модели.
Например ,
def forward(self,x): out = self.linear1(x) out = self.linear2(out) return out
Здесь вы можете заметить, что связь между двумя слоями устанавливается путем передачи выходных данных в виде тензоров факела или переменных.
Шаг 4: Дополнительные функции:. Все действия, описанные выше, готовы! Иногда, когда ваша модель имеет слои LSTM, требуется функция инициализации скрытых слоев. Аналогичным образом, если вы пытаетесь построить сеть машин Больцмана, требуется выборка скрытых и видимых узлов. поэтому можно создавать и использовать новые функции-члены нашего сетевого класса.
Шаг 5. Параметры вашего класса. При построении сети с классом убедитесь, что вы используете минимальные значения или их отсутствие. Скорость обучения, размеры скрытых слоев и т. Д. Могут быть переданы при создании экземпляра вашего класса.
Если вы успешно поняли все вышеперечисленные шаги и смогли визуализировать, как именно выглядит ваш сетевой класс,
Поздравляю! 100/100 на вашем первом этапе !!
Поскольку этот этап был достаточно длинным, давайте посмотрим на небольшой, но важный!
Вторая веха: пользовательский загрузчик данных:
Вы когда-нибудь делали тестовое разделение поездов, разделение поездов val, разделение размеров пакетов, перемешивание и т. Д. Для ваших данных с нуля? У Keras есть параметр «размер партии», который заботится о нестандартных размерах партий. Но, если вам нужно сделать это в pytorch, это потребует довольно много усилий.
Не волнуйся! пользовательский DataLoader уже здесь!
DataLoader - это термин, используемый для создания данных для обучения, тестирования и проверки данных из ваших данных с такими функциями, как размер пакета, перемешивание и количество рабочих.
pytorch имеет класс загрузчика данных по умолчанию, который можно импортировать с помощью torch.utils.data.dataloader. Вы можете напрямую подготовить свою модель данных!
Вместо использования загрузчика данных по умолчанию довольно легко создать собственный загрузчик данных в соответствии с вашими требованиями. Посмотрим, как это сделать!
Вы помните, как импортировали данные из torch.utils? Надеюсь, да!
Создать собственный загрузчик данных так же просто, как выполнить следующие шаги:
Шаг 1. Наследование:. Подобно тому, как мы унаследовали nn.Module для нашего сетевого класса, мы наследуем класс data.Dataset для нашего DataLoader. Вам не нужно вызывать конструктор инициализации, как это было раньше.
Что-то вроде этого :
class dataset(data.Dataset):
Шаг 2. Последовательности и метки: класс data.Dataset имеет члены, называемые последовательностями, которые относятся к данным X или обучающим данным, а метки относятся к y. Вы можете создать параметр, называемый разделом, который будет возвращать соответствующие данные.
Например,
class dataset(data.Dataset): def __init__(self, partition): if partition==’train’: self.sequences = X_train self.labels = y_train
Вы можете убедиться, что ваши данные относятся к типу torch.tensor, преобразовав их изначально.
self.sequences = torch.tensor(self.sequences)
Шаг 3: метод len: __len __ () - это метод класса data.Dataset, который необходимо перезаписать, чтобы наш загрузчик данных работал. Просто верните длину сгенерированных последовательностей этим методом.
Шаг 4: метод getitem: __getitem__ (self, index) - это метод, который возвращает последовательности и метки по заданному индексу. Это должно быть перезаписано, чтобы сделать загрузчик данных полностью функциональным.
Шаг 5: генераторы и параметр dict:. С помощью описанных выше шагов создание пользовательского класса загрузчика данных завершено. Пришло время использовать это!
Данные, которые отправляются загрузчиком данных, используются в виде генераторов. Итак, необходимо создать параметр dict, на основе которого будут генерироваться данные. этот dict содержит ключи: batch_size, shuffle, num_workers. объект для класса загрузчика данных будет создан и передан генератору вместе с параметром dict:
params= { ‘batch_size’ : 10, ‘shuffle’ : True, ‘num_workers’ : 20} training_set = dataset(X, y, ‘train') training_generator = torch.utils.data.dataloader(training_set, **params)
Дополнительные параметры смотрите в официальной документации здесь.
Получил ваши данные довольно легко ?! Если да,
🎊Престиж !! Еще 100/100 на втором этапе! 👏
Теперь, когда у нас есть и архитектура, и данные, наша модель готова к работе! Итак, перейдем к нашему третьему этапу!
Третья веха: функция поезда:
Теперь у вас есть 2 класса: один для архитектуры, а другой для данных. Наша функция поезда - это то, что объединяет и то, и другое, и позволяет нашей модели учиться.
Шаг 1. Параметры:. Первый и самый важный параметр нашей функции train - это объект нашего класса Network. Далее идут обучающий генератор и генератор проверки из загрузчика данных. После этих обязательных параметров можно передать количество эпох, скорость обучения, размер пакета, клип, потерю и т. Д. Как уже упоминалось, не жестко кодируйте значения. Вместо этого передайте их как параметры.
Шаг 2: Инициализация. Считаем «сеть» объектом нашего сетевого класса. Чтобы начать обучение, его необходимо установить в режим обучения. Делается это командой:
net.train()
Функции потерь и оптимизаторы должны быть назначены с помощью модуля nn.
Например :
criterion = nn.MSELoss() optimizer = torch.optim.Adam(net.parameters(), lr=lr)
Теперь, когда мы инициализировали значения, модель готова к обучению.
шаг 3: цикл эпох: запускает цикл, который повторяется n раз, где n означает количество эпох. В конце цикла выведите потери (как для обучения, так и для проверки), соответствующие этой эпохе.
Шаг 4: цикл tqdm: Циклы могут работать бесконечно! Специально для моделей глубокого обучения с большим количеством данных! Разобраться, что происходит внутри и сколько времени потребуется, чтобы закончить, довольно сложно. tqdm уже здесь! Это индикатор выполнения для каждой итерации. Посмотрите его официальную документацию здесь. Итератор должен быть назначен tqdm и использоваться в цикле.
Для каждой эпохи наша функция выполняет итерацию по размеру пакета. Итак, наш итератор - это обучающий генератор.
Циклы tqdm выглядят примерно так:
t = tqdm(iter(training_generator), leave=False, total=len(training_generator)) for i, batch in enumerate(t): x_batch, y_batch = next(iter(training_generator))
Шаг 5: доступность графического процессора. Переменные, объекты и т. д. могут быть перенесены в графический процессор с помощью одной единственной команды pytorch.
Включите одну строку:
torch.cuda.set_ device(0)
в начале вашего кода. 0 - это номер используемого графического процессора.
Когда вы чувствуете необходимость передать некоторую переменную в cuda,
сделать: X = X.cuda ()
Однако наш код должен работать независимо от базового оборудования. Если графического процессора не существует, вы не можете передавать переменные в cuda. Код показывает ошибку в этой строке. Чтобы избавиться от этих зависимостей, рассмотрим переменную, которая содержит логическое значение доступности графического процессора.
Ваш код можно просто изменить как:
if gpu_available: X= X.cuda()
Шаг 6. Процедура обучения:. После настройки начинается обучение с использованием объекта класса архитектуры как:
output = net(x)
Здесь передаются параметры, указанные в функции forward.
После получения результатов потери рассчитываются как:
loss = criterion(output, targets)
Обратное распространение осуществляется с помощью:
loss.backward() optimizer.step()
Optimizer.step () используется для обновления параметров (весов и смещений) на основе потерь, которые распространяются обратно.
Вы можете распечатать прогресс потери с помощью итератора tqdm как:
t.set_postfix(loss=train_loss)
Шаг 7. Оценка. После обучения можно выполнить оценку, для которой модель должна быть переведена в режим оценки:
net.eval()
В конце оценки убедитесь, что вы вернули режим обучения с помощью net.train ().
шаг 8: сохранение модели и state_dict:. После успешного завершения обучения модели необходимо сохранить ее для использования в будущем. Есть 2 основных способа сохранения обученной модели в pytorch.
- torch.save (): этот метод сохраняет всю модель вместе со структурой каталогов. Его можно использовать с двумя строками кода:
torch.save(net, path) #saving net = torch.load(path) #loading
2. model.state_dict (): функция state_dict сохраняет только параметры вашей модели (веса, смещения и т. Д.) Вместо сохранения всей модели. Для использования сохраненной модели необходимо создать объект класса архитектуры и назначить соответствующие параметры.
torch.save(net.state_dict(), path) #saving net = Network(*args, **kwargs) #loading net.load_state_dict(torch.load(path))
Третий вопрос:
Когда использовать torch.save (), а когда - model.state_dict ()?
Как упоминалось выше, torch.save сохраняет всю модель. Чтобы загрузить его, вам не нужно создавать экземпляр класса Network. В случаях, когда ваша модель должна работать на совершенно другой платформе независимо от базового кода, torch.save () очень подходит.
Напротив, если вы проводите эксперименты, state_dict () очень удобен, поскольку он просто сохраняет параметры вашей модели и является гибким для любых дальнейших модификаций. это относительно дружественно к памяти.
Посмотрите эти ответы stackoverflow для более подробной информации.
Поздравляю! если вы здесь, вы почти построили свою модель до совершенства! Чтобы упорядочить свой код и провести эксперименты, давайте взглянем на одну последнюю веху. Кстати,
A 100/100 и для этой вехи !! 🎊
Заключительный этап: организация
Поскольку многочисленные эксперименты, настройки параметров часто выполняются на модели глубокого обучения, очень важно хранить их в правильной структуре каталогов. Вот несколько шагов, которые необходимо выполнить:
Шаг 1. Файл конфигурации: такие параметры, как скорость обучения, функция потерь, количество эпох, всегда меняются. Чтобы отслеживать все эти параметры, создайте файл конфигурации и упомяните все те параметры, с которыми можно поиграть. Вместо того, чтобы упоминать значения при создании экземпляра класса или вызове функции, вы можете импортировать эти переменные как:
from config import *
и пользуйся. Когда вам нужно использовать различные методы проб и ошибок, достаточно изменить файл конфигурации.
Шаг 2. Tensorboard: Помните, как импортировать SummaryWriter из tensorboardX? Как упоминалось ранее, визуализацию потерь, точности и т. Д. Можно выполнить с помощью тензорной доски.
Чтобы включить тензорную доску, просто добавьте одну строку перед функцией поезда:
writer = SummaryWriter(path)
В цикл, который продолжается для каждой эпохи, включают:
writer.add_scalar(‘loss’, loss, epoch_number) writer.add_scalar('accuracy', accuracy, epoch_number)
Вы можете добавить сколько угодно графиков с различными параметрами.
В конце обучения близкий писатель с:
writer.close()
Не забудьте изменить путь последующих записей тензорной доски, поскольку графики могут быть перезаписаны или перекрыты.
Шаг 3: файл требований: Может быть слишком банальным, чтобы упоминать его, но рекомендуется иметь файл требований, содержащий все библиотеки с их используемыми версиями. Одна команда справится со всеми вашими зависимостями.
Посмотрите эту ссылку, чтобы узнать, как заморозить все свои требования.
Шаг 4: ознакомительные сведения: После всей тяжелой работы ваше право хвастаться своей работой и направлять людей по использованию вашего кода! Ридми делает то же самое. Завершите свой проект, добавив качественный и количественный ридми!
Готово !!
Наконец-то !!! Поздравляем с успешным прохождением всех четырех этапов! Вы получите еще 100/100 за последний этап и в целом:
🎊 Награда «Лучший новичок в pytorch» !! 🎉
Дополнительно: проведение нескольких экспериментов - трюк с JSON!
Для крупномасштабных экспериментов требуется много человеческого вмешательства для изменения файла конфигурации каждый раз, когда вы запускаете эксперимент. Чтобы минимизировать это, один набор параметров конфигурации может быть преобразован в один объект json.
Учитывая, что ваш файл конфигурации выглядит так:
lr = 0.01
эпох = 100
……
Код ниже преобразует весь текст в объект json.
import json
data = dict(zip(parameter, value)) #create a dictionary
json.dumps(data) #json object
Можно создать несколько объектов JSON, каждый из которых представляет отдельный эксперимент. Они сформируют массив объектов JSON, по которым можно рекурсивно перемещаться, передав в main только один раз!
Лучшее заключение!
Давайте быстро посмотрим на полную схему структуры нашего проекта:
Надеюсь, структура вашего проекта выглядит так же! Не стесняйтесь комментировать любые сомнения!
Конец статьи! Сделайте перерыв, создайте сеть! 😬
P.S: Я благодарю А.Маноджа Гухана и Нияти Чхая за то, что они наставляли меня на всем пути, исправляли мои глупые ошибки и придали мне уверенности в теме!