Я обучил модель DistilBERT с помощью DistilBertForTokenClassification на данных ConLL для прогнозирования NER. Кажется, что обучение завершилось без проблем, но на этапе оценки у меня возникли 2 проблемы.
У меня отрицательная сумма убытка
Во время обучения я использовал shuffle = True для DataLoader. Но во время оценки, когда я выполняю shuffle = True для DataLoader, я получаю очень плохие метрические результаты (f_1, точность, отзыв и т. Д.). Но если я делаю shuffle = False или использую Sampler вместо перемешивания, я получаю довольно хорошие метрические результаты. Мне интересно, что-то не так с моим кодом.
Вот код оценки:
print('Prediction started on test data')
model.eval()
eval_loss = 0
predictions , true_labels = [], []
for batch in val_loader:
b_input_ids = batch['input_ids'].to(device)
b_input_mask = batch['attention_mask'].to(device)
b_labels = batch['labels'].to(device)
with torch.no_grad():
outputs = model(b_input_ids,
attention_mask=b_input_mask)
logits = outputs[0]
logits = logits.detach().cpu().numpy()
label_ids = b_labels.detach().cpu().numpy()
predictions.append(logits)
true_labels.append(label_ids)
eval_loss += outputs[0].mean().item()
print('Prediction completed')
eval_loss = eval_loss / len(val_loader)
print("Validation loss: {}".format(eval_loss))
из:
Prediction started on test data
Prediction completed
Validation loss: -0.2584906197858579
Я считаю, что здесь неправильно рассчитываю убыток. Можно ли получить отрицательные значения потерь с помощью BERT?
Для DataLoader, если я использую приведенный ниже фрагмент кода, у меня нет проблем с результатами метрики.
val_sampler = SequentialSampler(val_dataset)
val_loader = DataLoader(val_dataset, sampler=val_sampler, batch_size=128)
Но если я сделаю это, я получу очень плохие метрические результаты
val_loader = DataLoader(val_dataset, batch_size=128, shuffle=True)
Это нормально, что я получаю совершенно разные результаты с shuffle = True vs shuffle = False?
код для расчета метрики:
metric = load_metric("seqeval")
results = metric.compute(predictions=true_predictions, references=true_labels)
results
из:
{'LOCATION': {'f1': 0.9588207767898924,
'number': 2134,
'precision': 0.9574766355140187,
'recall': 0.9601686972820993},
'MISC': {'f1': 0.8658965344048217,
'number': 995,
'precision': 0.8654618473895582,
'recall': 0.8663316582914573},
'ORGANIZATION': {'f1': 0.9066332916145182,
'number': 1971,
'precision': 0.8947628458498024,
'recall': 0.9188229325215627},
'PERSON': {'f1': 0.9632426988922457,
'number': 2015,
'precision': 0.9775166070516096,
'recall': 0.9493796526054591},
'overall_accuracy': 0.988255561629313,
'overall_f1': 0.9324058459808882,
'overall_precision': 0.9322748349023465,
'overall_recall': 0.932536893886156}
Вышеуказанные показатели печатаются, когда я использую Sampler или shuffle = False. Если я использую shuffle = True, я получаю:
{'LOCATION': {'f1': 0.03902284263959391,
'number': 2134,
'precision': 0.029496402877697843,
'recall': 0.057638238050609185},
'MISC': {'f1': 0.010318142734307824,
'number': 995,
'precision': 0.009015777610818933,
'recall': 0.012060301507537688},
'ORGANIZATION': {'f1': 0.027420984269014285,
'number': 1971,
'precision': 0.019160951996772892,
'recall': 0.04819888381532217},
'PERSON': {'f1': 0.02119907254057635,
'number': 2015,
'precision': 0.01590852597564007,
'recall': 0.03176178660049628},
'overall_accuracy': 0.5651741788003777,
'overall_f1': 0.02722600361161272,
'overall_precision': 0.020301063389034663,
'overall_recall': 0.041321152494729445}
ОБНОВЛЕНИЕ: я изменил код потери для оценки. Кажется, с этим кодом проблем нет. Вы можете увидеть новый код ниже:
print('Prediction started on test data')
model.eval()
eval_loss = 0
predictions , true_labels = [], []
for batch in val_loader:
b_labels = batch['labels'].to(device)
batch = {k:v.type(torch.long).to(device) for k,v in batch.items()}
with torch.no_grad():
outputs = model(**batch)
loss, logits = outputs[0:2]
logits = logits.detach().cpu().numpy()
label_ids = b_labels.detach().cpu().numpy()
predictions.append(logits)
true_labels.append(label_ids)
eval_loss += loss
print('Prediction completed')
eval_loss = eval_loss / len(val_loader)
print("Validation loss: {}".format(eval_loss))
Хотя у меня до сих пор нет ответа на вопрос о DataLoader. Также я просто понял, что когда я делаю print(model.eval())
, я все еще получаю выпадение из модели в режиме оценки.
f_1, accuracy, recall
- person mujjiga   schedule 21.12.2020