Накопление градиента

искусственный интеллект

Когда мы обучаем нейронную сеть, размер пакета гиперпараметров будет иметь большое влияние на окончательный эффект модели. При определенных условиях, чем больше размер партии, тем более стабильной будет модель. Значение размера пакета обычно устанавливается в диапазоне от 8 до 32, но когда мы выполняем некоторые вычислительно сложные задачи (такие как семантическая сегментация, GAN и т. д.) или когда размер входного изображения слишком велик, наш размер пакета часто может быть установлен только на 2 или 4, иначе будет форс-мажорная ошибка "CUDA OUT OF MEMORY".

Бедность — это лестница для продвижения человеческого прогресса Как использовать больший размер партии для обучения в условиях ограниченных вычислительных ресурсов? Это технология накопления градиента (Gradient Accumulation).

На примере Pytorch процесс обучения нейронной сети обычно выглядит следующим образом:

for i, (inputs, labels) in enumerate(trainloader):
    optimizer.zero_grad()                   # 梯度清零
    outputs = net(inputs)                   # 正向传播
    loss = criterion(outputs, labels)       # 计算损失
    loss.backward()                         # 反向传播,计算梯度
    optimizer.step()                        # 更新参数
if (i+1) % evaluation_steps == 0:
    evaluate_model()

Из кода понятно, как обучается нейросеть:
1. Очистите градиент сети после предыдущего пакетного расчета.
2. Прямое распространение, передача данных в сеть и получение результата прогнозирования.
3. Рассчитайте значение потерь в соответствии с результатом прогноза и меткой
4. Используйте потери для обратного распространения для расчета градиента параметра
5. Обновите параметры сети, используя рассчитанные градиенты параметров.

Давайте посмотрим, как происходит накопление градиента:

model.zero_grad()                                   # 梯度清零
for i, (inputs, labels) in enumerate(training_set):
    predictions = model(inputs)                     # 正向传播
    loss = loss_function(predictions, labels)       # 计算损失
    loss = loss / accumulation_steps                # Normalize our loss (if averaged)
    loss.backward()                                 # 反向传播,计算梯度
    if (i+1) % accumulation_steps == 0:             # 经过几次accumulation_steps
        optimizer.step()                            # 更新参数
        model.zero_grad()                           # 梯度清零
        if (i+1) % evaluation_steps == 0:           # Evaluate the model when we...
            evaluate_model()                        # ...have no gradients accumulated

1. Прямое распространение, передача данных в сеть и получение результатов прогнозирования.
2. Рассчитайте значение потерь в соответствии с результатом прогноза и меткой
3. Используйте потери для обратного распространения для расчета градиента параметра
4. Повторить 1-3, градиент не сбрасывать, а накапливать градиент
5. После того, как накопление градиента достигнет фиксированного количества раз, обновите параметры, а затем очистите градиент до нуля.

Подводя итог, накопление градиента заключается в вычислении градиента пакета, без его очистки, но с накоплением градиента.После накопления до определенного количества раз (accumulation_steps) обновите параметры сети, а затем очистите градиент.

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

image.png