Убыток не уменьшается.

Вопрос или проблема

Я строю проект на основе генерации текста с использованием архитектуры трансформера. Я использовал токенизатор Huggingface для токенизации, мой набор данных – daily-dialog, а архитектура моей модели следующая:

class languageModel(nn.Module):

def __init__(self):
    super().__init__()
    self.encoder_embedding_layer = nn.Embedding(vocab_size, n_embd)
    self.encoder_positional_encoder = PositionalEncoding(n_embd, block_size)
    

    self.decoder_embedding_layer = nn.Embedding(vocab_size, n_embd)
    self.decoder_positional_encoder = PositionalEncoding(n_embd, block_size)
    
    self.transformer = nn.Transformer(n_embd, n_head, num_encoder_layers=6, num_decoder_layers=6, activation="gelu", device=device, norm_first=True)
    self.fin = nn.Linear(n_embd, vocab_size)

def forward(self, encoder_idx, decoder_idx, target=None, encoder_attention_mask=None, decoder_attention_mask=None):
    B, T = encoder_idx.shape
    
    encoder_embed = self.encoder_embedding_layer(encoder_idx)
    enc = self.encoder_positional_encoder(encoder_embed)  # Shape: (1, T, n_embd)
    
    B, T = decoder_idx.shape
    decoder_embed = self.decoder_embedding_layer(decoder_idx)
    decoder_idx = self.decoder_positional_encoder(decoder_embed)
    
    output = self.transformer(enc, decoder_idx, src_key_padding_mask=encoder_attention_mask, tgt_key_padding_mask=decoder_attention_mask)
    return self.fin(output)

и мой блок тренировки выглядит так:

model = languageModel().to(device)
model.apply(init_weights)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1000, gamma=0.9)
itrs = 0
criterion = nn.CrossEntropyLoss()
num_batches = data["input_ids"].size(0)
batch_losses = []
for epoch in range(5):
  for i in range(num_batches):
    encoder_idx = data["input_ids"][i].to(device)
    decoder_idx = data["target_inputs"][i].to(device)
    targets = data["target_labels"][i].to(device)
    encoder_attention_mask = data["attention_mask"][i].to(device).transpose(1, 0)
    decoder_attention_mask = data["target_attention_mask"][i].to(device).transpose(1, 0)
    
    batch_size, seq_len = encoder_idx.shape
    
    output = model(encoder_idx, decoder_idx, targets, encoder_attention_mask, decoder_attention_mask)
    mask = targets != tokenizer.eos_token_id
    loss = criterion(output.view(-1, vocab_size)[mask.view(-1)], targets[mask].view(-1))
    batch_losses.append(loss.item())
    if i%500 == 0 or math.isnan(loss.item()):
        current_lr = optimizer.param_groups[0]['lr'] 
        print(f"Итерация {i}, Обучающая скорость: {current_lr}, Потеря: {loss}")
    optimizer.zero_grad(set_to_none=True)
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    optimizer.step()
    scheduler.step()
    if i == 6300:
        break
print("Эпоха завершена")

потеря постепенно снижается с ~11 до ~5, но затем колеблется вокруг 5. Как я могу снизить ее дальше?
Я уже пробовал менять оптимизаторы между AdamW, Adagrad, SGD, а также пробовал обрезку градиентов, но проблема все еще сохраняется.

Ответ или решение

Проблема: Уровень потерь не снижается

Введение

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

1. Параметры обучения

На начальном этапе попробуйте оптимизировать параметры обучения. Вы упоминали об использовании оптимизаторов, таких как AdamW, Adagrad и SGD. Возможно, стоит провести более глубокий анализ для выбора оптимального шага обучения:

  • Учебная ставка (Learning Rate): Попробуйте использовать разные значения учебной ставки. Нередко высокая скорость обучения приводит к колебаниям потерь. Существуют техники, такие как циклические шаги обучения, которые могут помочь в этом случае.
  • Уменьшение скорости обучения (Learning Rate Scheduler): Ваша реализация StepLR может не быть оптимальной для вашей задачи. Вы можете рассмотреть другие методы, например, ReduceLROnPlateau, который уменьшает скорость обучения только в случае, если потери не улучшаются в течение определенного количества эпох.

2. Архитектура модели

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

  • Количество слоев и голов самовнимания: Проверьте, достаточно ли выбранное вами количество слоев и голов самовнимания. Увеличение этих параметров может позволить модели лучше захватывать сложные зависимости в данных.
  • Инициализация весов: Вы можете улучшить инициализацию весов вашей модели. Обратите внимание на использование различных инициализаций, таких как xavier_uniform или kaiming_uniform, чтобы добиться лучшего старта для вашей модели.

3. Предобработка данных

Качество входных данных часто критично для успешного обучения модели:

  • Очистка и аугментация данных: Убедитесь, что ваши входные данные правильно очищены от шума, а также рассмотрите возможность увеличения размера данных с помощью аугментации.
  • Обратите внимание на разметку данных: Проверьте, качественно ли размечен ваш набор данных. Неправильные или неоптимальные метки могут приводить к "застреванию" модели на определённом уровне потерь.

4. Мониторинг и отладка

Иногда полезно более подробно отслеживать процесс обучения:

  • Логирование потерь: Расширьте логирование, добавив дополнительные метрики, такие как точность, для более глубокого понимания того, что происходит во время обучения.
  • Визуализация: Используйте инструменты для визуализации потерь (например, TensorBoard или Matplotlib), что поможет вам лучше проаналізировать поведение модели.

5. Регуляризация

Регуляризация возможностей вашей модели может также помочь:

  • Дроп-аут (Dropout): Внедрение дроп-аута для предотвращения переобучения. Это может быть особенно полезно в трансформерах, где система может легко переполниться признаками.
  • L2-регуляризация (Weight Decay): Включите L2-регуляризацию в оптимизаторе для борьбы с переобучением.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...