Weights and Biases стала одной из любимых библиотек сообщества ИИ. Команда проделала отличную работу, создав платформу, на которой инженер по машинному обучению может без особых усилий:
-
Отслеживайте его/ее эксперименты
-
Визуализируйте тренировочный процесс
-
Поделитесь результатами с командой
-
Улучшить производительность модели
Лично я начал использовать его пару месяцев назад и быстро стал отдельной частью всех моих проектов. Эта статья обобщает мой опыт работы с библиотекой и призвана стать самостоятельным руководством по ее наиболее полезным функциям. Для этого мы рассмотрим, как мы можем интегрировать wandb
библиотека в новом проекте.
Начнем?
Предпосылки
Мы будем использовать стандартную модель глубокого обучения, которая выполняет распознавание изображений в наборе данных CIFAR10. Модель на самом деле не влияет на наши эксперименты, поэтому я решил сделать ее максимально простой. Модель будет обучаться на наборе данных с нуля, чтобы изучить, как мы можем использовать wandb
библиотека.
Вот код Pytorch для нашей модели вместе с обработкой данных:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
(transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))))
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 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, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
Первый шаг — установить библиотеку и создать новую учетную запись.
Установка и инициализация
Если вы еще этого не сделали, вам нужно будет создать новую учетную запись, чтобы иметь возможность использовать Weights and Biases. Библиотека бесплатна для личного использования, но для команд предоставляется ежемесячная плата. Вы можете посетить Веб-сайт и зарегистрируйтесь.
Как только вы это сделаете, вы сможете установить его, используя pip
или conda
. После установки вам нужно будет авторизоваться. Это можно сделать с помощью wandb login
команда. Вам будет предложено скопировать и вставить ключ авторизации, чтобы продолжить.
$ conda install -c conda-forge wandb
$ wandb login
Библиотеку можно инициализировать в нашем коде с помощью init
метод, который, среди прочего, получает необязательное имя проекта и ваше имя пользователя.
import wandb
wandb.init(project='test', entity='serkar')
Теперь, когда мы все настроили, давайте попробуем интегрировать библиотеку в наш цикл обучения.
Отслеживание экспериментов
Основное использование wandb
Библиотека предназначена для отслеживания и визуализации различных экспериментов по машинному обучению, процесса обучения, гиперпараметров и моделей. Давайте посмотрим на некоторые примеры.
Отслеживайте показатели
Удивительной особенностью библиотеки Weights and Biases (W&B) является простота ее использования. Во многих случаях это буквально одна строка кода:
wandb.log({'epoch': epoch, 'loss': running_loss})
.log()
Команда захватит все аргументы и отправит их экземпляру W&B. Это позволит нам получать к ним доступ и отслеживать их из пользовательского интерфейса. Вы можете найти дашборд на сайте W&B под своим проектом.
В нашем приложении пример цикла обучения может выглядеть следующим образом:
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data(0).to(device), data(1).to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print('(%d, %5d) loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
wandb.log({'epoch': epoch+1, 'loss': running_loss/2000})
running_loss = 0.0
print('Finished Training')
Вы заметили wandb.log
линия? Таким образом, мы можем наблюдать за тренировочным процессом в режиме реального времени. Результат будет выглядеть так:
Довольно круто, правда?
Другая команда, которую также можно использовать, это wandb.watch
который автоматически соберет градиенты модели и топологию модели.
wandb.watch(net, criterion, log="all")
Помимо определенных метрик, мы также можем отслеживать многие другие полезные вещи, такие как наши обучаемые параметры.
Или градиенты:
Еще одна особенность, которая меня действительно впечатлила, — это системная панель. Там мы можем проверить наше оборудование и то, как различные компоненты ведут себя во время обучения. Например, можно проверить ЦП, ГП, использование памяти, энергопотребление, температуру и многое другое.
Каждый раз, когда мы выполняем наш сценарий обучения, создается новый «запуск», который добавляется к истории проекта. Каждый «прогон» содержит зарегистрированную информацию с разными метаданными. Конечно, мы можем исследовать все различные прогоны на одной панели инструментов.
Отслеживание гиперпараметров
Помимо метрик, W&B имеет еще одну удобную функцию, которая позволяет нам отслеживать гиперпараметры нашего обучения. wandb.config
объект используется для сохранения конфигурации обучения, такой как гиперпараметры. Но это не ограничивается ими. По сути, мы можем хранить любую часть информации, которую захотим. Примеры включают: имена наборов данных, типы моделей и флаги.
Конфиг можно инициализировать так:
config = wandb.config
config.learning_rate = 0.01
config.momentum = 0.9
Для сложных конфигураций мы также можем использовать файл yaml или словарь python.
Все эти значения можно использовать для анализа экспериментов и воспроизведения результатов. На следующей панели мы видим пять «прогонов» с их гиперпараметрами. Обратите внимание, что мы можем использовать значения конфигурации для их группировки, фильтрации или сортировки.
Визуализируйте модель
Если мы воспользуемся вышеупомянутым watch
Команда, мы также можем проверить топологию модели на панели управления моделью. В нашем случае модель будет выглядеть так:
Проверить журналы
То же самое верно и для фактических журналов, напечатанных в нашей локальной консоли:
Версии данных и моделей
Помимо отслеживания экспериментов, в W&B есть встроенная система управления версиями. Артефакты являются основным средством достижения этой цели. Артефакты обеспечивают управление версиями наборов данных, версий моделей и отслеживание зависимостей.
Артефакт — это не что иное, как версионная папка данных. Давайте рассмотрим пример, используя наш проект. Чтобы создать версию нашего набора данных, все, что нам нужно сделать, это создать артефакт и загрузить его.
cifar10_artifact = wandb.Artifact("cifar10", type="dataset")
file_path = './data/cifar-10-batches-py'
cifar10_artifact.add_dir(file_path)
run.log_artifact(cifar10_artifact)
Вы можете себе представить, что что-то подобное можно сделать для управления версиями модели или зависимостей. Стоит отметить, что вместо использования всего набора данных мы можем создать артефакт с внешней ссылкой на объект, как показано ниже:
artifact.add_reference('s3://my-bucket/my_dataset)
Скачать и использовать уже загруженный артефакт в нашем коде также просто:
artifact = run.use_artifact('cifar10_artifact')
artifact_dir = artifact.download()
Настройка гиперпараметров с разверткой
Weights & Biases Sweeps — это инструмент для автоматизации оптимизации и исследования гиперпараметров. Он устраняет большую часть шаблонного кода и поставляется с очень красивыми визуализациями. Давайте рассмотрим, как мы можем использовать Sweeps в наших проектах.
В нашем случае мы хотим настроить 4 различных параметра: размер последнего линейного слоя в модели, размер пакета, скорость обучения и алгоритм оптимизации. Для этого нам сначала нужно создать конфигурацию с различными параметрами. Вот пример конфигурации:
sweep_config = {
'method': 'random',
'metric': {'goal': 'minimize', 'name': 'loss'},
'parameters': {
'batch_size': {
'distribution': 'q_log_uniform',
'max': math.log(256),
'min': math.log(32),
'q': 1
},
'epochs': {'value': 5},
'fc_layer_size': {'values': (128, 256, 512)},
'learning_rate': {'distribution': 'uniform',
'max': 0.1,
'min': 0},
'optimizer': {'values': ('adam', 'sgd')}
}
}
Сначала мы определяем метод настройки, который является стратегией поиска. У нас есть 3 варианта: случайный, поиск по сетке и байесовский поиск. Метрика — это конечная цель, которую следует минимизировать. Наконец, параметры относятся к гиперпараметрам, которые будут искаться с помощью Sweeps. Как видите, мы настроим следующее:
-
Размер партии должен быть в (лог(32), лог(256)) диапазон. Выбор размера партии будет соответствовать равномерному распределению квантованного логарифма. Доступны и другие варианты.
-
Количество эпох всегда должно быть равно 5.
-
Размер последнего линейного слоя должен быть 128, 256 или 512.
-
Скорость обучения, чтобы быть в (0, 0,1) диапазон после равномерного распределения
-
Оптимизатор должен быть SGD или Adam.
Sweeps будут пробовать все различные комбинации и вычислять потери для каждой из них. Развертки могут быть инициализированы с помощью:
sweep_id = wandb.sweep(sweep_config, project="test")
Затем цикл обучения должен быть преобразован для чтения из предопределенной конфигурации. Взгляните на следующий код:
def train(config=None):
with wandb.init(project='test', entity='serkar', config=config):
config = wandb.config
transform = transforms.Compose(
(transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))))
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=config.batch_size,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform)
net = Net(config.fc_layer_size)
net.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=config.learning_rate)
if config.optimizer == "sgd":
optimizer = optim.SGD(net.parameters(),
lr=config.learning_rate, momentum=0.9)
elif optimizer == "adam":
optimizer = optim.Adam(net.parameters(),
lr=config.learning_rate)
wandb.watch(net, criterion, log="all")
for epoch in range(config.epochs):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data(0).to(device), data(1).to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print('(%d, %5d) loss: %.3f' %
(epoch + 1, i + 1, running_loss / len(trainloader)))
wandb.log({'epoch': epoch + 1, 'loss': running_loss / len(trainloader)})
print('Finished Training')
Здесь следует отметить две вещи:
-
Тренировочный цикл обертывается
with wandb.init(project='test', entity='serkar', config=config)
. Это еще один способ связать библиотеку W&B с нашим кодом. -
Читаем конфиг с помощью
config = wandb.config
а затем мы передаем каждый параметр в обучающий код. Мы должны убедиться, что используемые гиперпараметры взяты из файла конфигурации, чтобы Sweeps выполнялся правильно.
Наконец, мы можем выполнить настройку с помощью приведенной ниже команды.
wandb.agent(sweep_id, function=train, count=5)
Это указывает Sweeps запускать функцию обучения только 5 раз, выбирая 5 случайных комбинаций гиперпараметров. Результаты проиллюстрированы ниже:
Обратите внимание, что мы получаем наилучшие результаты для следующего набора гиперпараметров:
-
Размер партии = 55
-
Размер линейного слоя = 256
-
Скорость обучения = 0,02131
-
Оптимизатор = SGD
При использовании этой комбинации убыток стал равен 0,003.
Еще одна очень интересная диаграмма:
Здесь мы исследуем, какие параметры оказывают большее влияние на потери и как. Это называется графиком важности гиперпараметра. Он указывает, какие гиперпараметры были лучшими предикторами наших показателей. Важность признаков определяется с помощью модели случайного леса, а корреляция — с помощью линейной модели.
Визуализация данных
Еще одна функция, которая мне очень нравится, — это визуализация данных. W&B позволяет нам определить таблицу данных и визуализировать ее на платформе. Таблица может состоять практически из чего угодно: таких данных, как изображения, текст или аудио, градиенты, обучаемые параметры и т. д. Помимо визуализации, мы также можем фильтровать, сортировать, группировать и в целом исследовать данные.
Чтобы было понятно, приведем простой пример. Давайте создадим небольшую таблицу со всеми изображениями из первой партии наших данных и их метками. Создать таблицу можно с помощью wandb.Table
сорт. Чтобы синхронизировать таблицу, нам нужно будет ее зарегистрировать.
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
columns=('image','label')
data = ()
for i, batch in enumerate(trainloader, 0):
inputs, labels = batch(0), batch(1)
for j, image in enumerate(inputs,0):
data.append((wandb.Image(image),classes(labels(j).item())))
break
table= wandb.Table(data=data, columns=columns)
run.log({"cifar10_images": table})
Обратите внимание, что мы используем встроенный тип данных wandb.Image
так что мы можем просмотреть изображение. Как только мы запустим приведенный выше код, мы сможем проверить нашу таблицу на панели инструментов.
Вы можете себе представить, что, используя ту же логику, мы можем визуализировать практически все, что угодно.
отчеты
Наконец, я хочу завершить этот учебник функцией, которая больше ориентирована на команды. Отчеты. Отчеты позволяют нам, разработчикам, организовывать различные визуализации, сообщать о наших результатах и документировать нашу работу.
W&B предоставляет редактор WYSIWYG с множеством функций. Он поддерживает уценку и латекс для текста, фрагментов кода, а также множество других диаграмм. Примеры включают: линейные графики, гистограммы, точечные диаграммы и многое другое. Команда усердно работает над добавлением дополнительных функций, таких как встроенное видео, HTML, аудио и многое другое.
Отчеты могут совместно использоваться и редактироваться другими людьми, что обеспечивает полное сотрудничество между нашими коллегами.
Заключение
На этом наше путешествие по библиотеке Weights and Biases завершается. W&B стал одним из моих личных фаворитов и значительно улучшил мой рабочий процесс. Очень рекомендую вам попробовать, если вы еще этого не сделали. Более подробную информацию вы можете найти в их документация, очень хорошо написано. Многие примеры также приведены в их Репозиторий на гитхабе.
Получайте удовольствие, играя с ним. Дайте нам знать, если у вас есть какие-либо вопросы или вы хотите, чтобы мы более подробно рассказали о W&B в будущем. Как обычно, делитесь этой статьей, если считаете ее полезной. Это действительно важно для нас, чтобы продолжать писать контент.
* Раскрытие информации: обратите внимание, что некоторые из приведенных выше ссылок могут быть партнерскими ссылками, и мы без дополнительных затрат для вас получим комиссию, если вы решите совершить покупку после перехода по ссылке.