Вопрос или проблема
Я работаю над настройкой BLIP-2 на наборе данных RSICD с использованием LORA. Я работаю в colab, используя A100. Странно, но когда я устанавливаю скорость обучения в приведенном ниже коде, это не влияет на результат. Я могу установить ее на 10^55 или на 10^(-55), и потеря по-прежнему колеблется примерно с одинаковыми интервалами.
Если я печатаю скорость обучения в оптимизаторе, это подтверждает ту скорость, которую я установил. Я даже могу создать планировщик с gamma=0.1, т.е. потеря должна меняться на порядок меньше на каждой эпохе. Когда я печатаю потерю и скорость обучения, скорость обучения действительно уменьшается в 10 раз на каждой эпохе, но потеря продолжает колебаться с одинаковыми размерами, что указывает на то, что печатаемая скорость потери на самом деле не имеет эффекта.
Кто-нибудь знает, что могло бы это вызывать? Мой код приведён ниже.
from accelerate import dispatch_model, infer_auto_device_map
from accelerate.utils import get_balanced_memory
processor = AutoProcessor.from_pretrained("Salesforce/blip2-opt-2.7b")
model = Blip2ForConditionalGeneration.from_pretrained(
"Salesforce/blip2-opt-2.7b",
device_map="auto",
torch_dtype=torch.bfloat16
)
processor.num_query_tokens = model.config.num_query_tokens
image_token = AddedToken("<image>", normalized=False, special=True)
processor.tokenizer.add_tokens([image_token], special_tokens=True)
model.resize_token_embeddings(len(processor.tokenizer), pad_to_multiple_of=64)
model.config.image_token_index = len(processor.tokenizer) - 1
device = "cuda" if torch.cuda.is_available() else "cpu"
n_epochs = 10
learning_rate = 2e-5
batch_size = 16
gradient_accumulation_steps = 1
weight_decay = 0.01
logging_steps = 5
max_grad_norm = 0
seed = 42
evaluation_strategy = "steps"
lr_scheduler_type = "constant"
lora_alpha = 32
lora_dropout = 0.05
lora_dim = 8
targetData=torch.load("/content/drive/Shareddrives/TEMFOM/target_data1.pt")
print("learning rate: " + str(learning_rate))
config = LoraConfig(
r=lora_dim,
lora_alpha=lora_alpha,
lora_dropout=lora_dropout,
bias="none",
target_modules=["q_proj", "k_proj"]
)
model = get_peft_model(model, config)
model.print_trainable_parameters()
if (False):
device_map = infer_auto_device_map(
model,
max_memory=max_memory,
#no_split_module_classes=[ "OPTDecoderLayer", "Linear","Blip2QFormerLayer","Blip2VisionEmbeddings","Blip2EncoderLayer","LayerNorm"],
no_split_module_classes=[ "OPTForCausalLM", "Linear","Blip2QFormerModel","Blip2VisionModel","LayerNorm"],
dtype="float16"
)
model = dispatch_model(model, device_map=device_map)
model.train()
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)
#scheduler = torch.optim.lr_scheduler.LinearLR(optimizer, start_factor=1.0, end_factor=0.5, total_iters=30)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.1, last_epoch=-1, verbose=True)
def fine_tune(model, train_dataloader, optimizer, n_epochs, model_name="fine-tuned"):
for epoch in range(0, n_epochs):
#print("Epoch:", epoch)
for idx, batch in enumerate(train_dataloader):
input_ids = batch.pop("input_ids").to(device)
pixel_values = batch.pop("pixel_values").to(device, torch.float16)
outputs = model(
input_ids=input_ids,
pixel_values=pixel_values,
labels=input_ids
)
loss = outputs.loss
loss.backward()
optimizer.step()
optimizer.zero_grad()
print("Loss:", loss.item())
print("learning rate before: " + str(optimizer.param_groups[0]['lr']))
scheduler.step()
print("learning rate after: " + str(optimizer.param_groups[0]['lr']))
model.save_pretrained(direct + model_name)
return model
train_dataset = ImageCaptioningDataset(targetData, processor)
train_dataloader = DataLoader(
train_dataset,
shuffle=True,
batch_size=batch_size,
collate_fn=collate_fn
)
fine_tuned_model = fine_tune(model, train_dataloader, optimizer, n_epochs, model_name="fine-tuned")
torch.save(fine_tuned_model,"/content/drive/Shareddrives/TEMFOM/target_model_blip2_2.pt")
Ответ или решение
Проблема с тем, что скорость обучения в PyTorch не влияет на поведение потерь (loss), может быть связана с несколькими факторами. Давайте рассмотрим их более подробно и предложим возможные решения.
1. Проверка доступа к параметрам и настройкам оптимизатора
Сначала убедитесь, что параметры модели действительно обновляются. Проверьте, что ваши параметры действительно попадают в optimizer
. Можно сделать это, напечатав исходные параметры модели после их передачи в оптимизатор:
for name, param in model.named_parameters():
if param.requires_grad:
print(name, param.data)
2. Логика обновления параметров
Убедитесь, что оптимизатор и его шаги обновления правильно интегрированы в ваш цикл обучения. В приведенном вами коде:
loss.backward() # Обратное распространение
optimizer.step() # Шаг обновления
optimizer.zero_grad() # Обнуление градиентов
Убедитесь, что loss.backward()
действительно вызывает вычисление градиентов. Если loss
равен NaN или слишком мал, то обновление параметров может быть искажено.
3. Проблема с градиентами
В некоторых случаях градиенты могут "взрываться" или "исчезать", особенно при работе с большими моделями. Вы можете попробовать применить torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)
перед шагом оптимизатора, чтобы контролировать величину градиентов:
torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)
optimizer.step()
4. структура потерь
Убедитесь, что функции потерь, предоставляемые вашей моделью, действительно применяются правильно. Возможно, параметры, передаваемые в модель или функцию потерь, не соответствуют ожиданиям. Убедитесь, что input_ids
, pixel_values
и labels
должным образом передаются и имеют правильные размеры.
5. Снижение скорости обучения
Вы упомянули использование планировщика ExponentialLR
. Убедитесь, что он действительно обновляет скорость обучения. В вашем случае, с γ = 0.1, скорость обучения будет уменьшаться в 10 раз от начального значения, так что если вы не видите изменений, возможно, стоит сначала опробовать более простую стратегию, например, фиксированную скорость обучения или слайдер для понижения её на количество шагов.
6. Вывод для отладки
Для более детального отслеживания поведения вашей модели можно выполнять вывод значений градиентов и весов после шагов оптимизации:
for name, param in model.named_parameters():
if param.requires_grad:
print(name, param.grad)
Таким образом, вы сможете понимать, влияют ли изменения скорости обучения на градиенты и параметры модели.
7. Инициализация модели
Убедитесь, что ваша модель должным образом инициализирована перед началом обучения. Проверьте, что у вас правильно загружены веса и что get_peft_model
действительно возвращает нужный вам объект.
Итог
Следуйте вышеуказанным рекомендациям для отладки проблемы с изменением скорости обучения. Если проблема сохранится, предоставьте дополнительные детали: размер входных данных, значения переменных, а также любые сообщения об ошибках или предупреждения. Это поможет более точно диагностировать причину возникшей ситуации.