7 полезных советов по PyTorch

PyTorch
7 полезных советов по PyTorch

оригинал:воооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо

Оригинальное название: a_few_helpful_pytorch_tips_examples_included

Автор перевода: kbsc13

Контакты:

Гитхаб:GitHub.com/CCC013/AI_Ah…

Публичный аккаунт WeChat:Примечания к алгоритму ИИ


предисловие

Это раздел машинного обучения зарубежного форума reddit. Кто-то обобщил около 7 полезных навыков PyTorch, а также привел примеры кода и видео colab. Код и ссылки на видео выглядят следующим образом:

Код:col AB.research.Google.com/drive/15VG только…

видео:youtu.be/BoC8SGaT3GE

Видео так же заливается на мою б станцию ​​синхронно, ссылка такая:

вооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо

Кроме того, код и видео можно получить, ответив на «12» на фоне официального аккаунта.


1. Создавайте тензоры прямо на целевом устройстве

Первый трюк заключается в использованииdeviceПараметры создают тензоры непосредственно на целевом устройстве.Вот время работы двух подходов.

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

start_time = time.time()

for _ in range(100):
  # Creating on the CPU, then transfering to the GPU
  cpu_tensor = torch.ones((1000, 64, 64))
  gpu_tensor = cpu_tensor.cuda()

print('Total time: {:.3f}s'.format(time.time() - start_time))

Второй — создать тензор непосредственно на целевом устройстве, код выглядит следующим образом:

start_time = time.time()

for _ in range(100):
  # Creating on GPU directly
  cpu_tensor = torch.ones((1000, 64, 64), device='cuda')

print('Total time: {:.3f}s'.format(time.time() - start_time))

Время выполнения для обоих методов следующее:

fig1.png

Видно, что скорость создания тензоров непосредственно на целевом устройстве очень высока;

2. Используйте как можно большеSequentialЭтаж

Вторая техника заключается в использованииSequentialслой, чтобы код выглядел более лаконичным.

Первый код для построения сетевой модели выглядит следующим образом:

class ExampleModel(nn.Module):
  def __init__(self):
    super().__init__()

    input_size = 2
    output_size = 3
    hidden_size = 16

    self.input_layer = nn.Linear(input_size, hidden_size)
    self.input_activation = nn.ReLU()

    self.mid_layer = nn.Linear(hidden_size, hidden_size)
    self.mid_activation = nn.ReLU()

    self.output_layer = nn.Linear(hidden_size, output_size)

  def forward(self, x):
    z = self.input_layer(x)
    z = self.input_activation(z)
    
    z = self.mid_layer(z)
    z = self.mid_activation(z)
    
    out = self.output_layer(z)

    return out

Эффект от его работы следующий:

fig2.png

с использованиемSequentialСпособ построения сетевой модели следующий:

class ExampleSequentialModel(nn.Module):
  def __init__(self):
    super().__init__()

    input_size = 2
    output_size = 3
    hidden_size = 16

    self.layers = nn.Sequential(
      nn.Linear(input_size, hidden_size),
      nn.ReLU(),
      nn.Linear(hidden_size, hidden_size),
      nn.ReLU(),
      nn.Linear(hidden_size, output_size))

  def forward(self, x):
    out = self.layers(x)
    return out

Эффект от его работы следующий:

fig3.png

можно увидеть сnn.SequentialКод для построения сетевой модели более лаконичен.

3. Не используйте списки для хранения сетевых слоев

Третий прием заключается в том, что не рекомендуется использовать список для хранения созданных сетевых слоев, т.к.nn.ModuleКлассы не могут успешно зарегистрировать их. Вместо этого список должен быть передан вnn.Sequentialсередина.

Первый — показать плохой пример:

class BadListModel(nn.Module):
  def __init__(self):
    super().__init__()

    input_size = 2
    output_size = 3
    hidden_size = 16

    self.input_layer = nn.Linear(input_size, hidden_size)
    self.input_activation = nn.ReLU()

    # Fairly common when using residual layers
    self.mid_layers = []
    for _ in range(5):
      self.mid_layers.append(nn.Linear(hidden_size, hidden_size))
      self.mid_layers.append(nn.ReLU())

    self.output_layer = nn.Linear(hidden_size, output_size)

  def forward(self, x):
    z = self.input_layer(x)
    z = self.input_activation(z)
    
    for layer in self.mid_layers:
      z = layer(z)
    
    out = self.output_layer(z)

    return out
  
bad_list_model = BadListModel()
print('Output shape:', bad_list_model(torch.ones([100, 2])).shape)
gpu_input = torch.ones([100, 2], device='cuda')
gpu_bad_list_model = bad_list_model.cuda()
print('Output shape:', bad_list_model(gpu_input).shape)

Приведенная выше запись сообщит об ошибке при печати второго предложения:

fig4.png

Правильное написание:

class CorrectListModel(nn.Module):
  def __init__(self):
    super().__init__()

    input_size = 2
    output_size = 3
    hidden_size = 16

    self.input_layer = nn.Linear(input_size, hidden_size)
    self.input_activation = nn.ReLU()

    # Fairly common when using residual layers
    self.mid_layers = []
    for _ in range(5):
      self.mid_layers.append(nn.Linear(hidden_size, hidden_size))
      self.mid_layers.append(nn.ReLU())
    self.mid_layers = nn.Sequential(*self.mid_layers)

    self.output_layer = nn.Linear(hidden_size, output_size)

  def forward(self, x):
    z = self.input_layer(x)
    z = self.input_activation(z)
    z = self.mid_layers(z)
    out = self.output_layer(z)

    return out

correct_list_model = CorrectListModel()
gpu_input = torch.ones([100, 2], device='cuda')
gpu_correct_list_model = correct_list_model.cuda()
print('Output shape:', correct_list_model(gpu_input).shape)

Его результат печати:

fig5.png

4. Используйте это правильноdistributions

Четвертый трюк — это PyTorch.torch.distributionsВ библиотеке есть отличные объекты и методы для реализации дистрибутива, но они не очень хорошо используются, ссылка на официальную документацию:

py torch.org/docs/stable…

Вот пример использования:

fig6.png

fig7.png

5. Использование на долгосрочных индикаторахdetach

Пятая хитрость заключается в том, что если вам нужно хранить тензорные метрики между эпохами, используйте.detach()для предотвращения утечек памяти.

Ниже приведен пример кода для иллюстрации, первая — начальная конфигурация:

# Setup
example_model = ExampleModel()
data_batches = [torch.rand((10, 2)) for _ in range(5)]
criterion = nn.MSELoss(reduce='mean')

Пример плохого кода:

losses = []

# Training loop
for batch in data_batches:
  output = example_model(batch)

  target = torch.rand((10, 3))
  loss = criterion(output, target)
  losses.append(loss)

  # Optimization happens here

print(losses)

Результат печати следующий:

fig8.png

Правильное написание

losses = []

# Training loop
for batch in data_batches:
  output = example_model(batch)

  target = torch.rand((10, 3))
  loss = criterion(output, target)
  losses.append(loss.item()) # Or `loss.item()`

  # Optimization happens here

print(losses)

Результат печати следующий:

fig9.png

следует позвонить сюдаloss.item()метод сохранения значения потерь в каждую эпоху.

6. Советы по удалению моделей на GPU

Шестой прием заключается в использованииtorch.cuda.empty_cache()Чтобы очистить кэш графического процессора, этот метод полезен при работе с ноутбуками, особенно если вы хотите удалить и воссоздать большую модель.

Пример использования следующий:

import gc

example_model = ExampleModel().cuda()

del example_model

gc.collect()
# The model will normally stay on the cache until something takes it's place
torch.cuda.empty_cache()

7. Звоните перед тестированиемeval()

Последнее не забудьте позвонить перед началом тестаmodel.eval(), это просто, но легко забыть. Эта операция внесет необходимые изменения в некоторые сетевые уровни, которые по-разному устанавливаются на этапах обучения и проверки. Затронутые модули включают:

  • Dropout
  • Batch Normalization
  • RNNs
  • Lazy Variants

Это может относиться к:stackoverflow.com/questions/6…

Пример использования следующий:

example_model = ExampleModel()

# Do training

example_model.eval()

# Do testing

example_model.train()

# Do training again