По какой-то причине на этапе проверки он выдает только eval_loss.
Хотя это хорошо, меня действительно интересовали и другие показатели (например, точность), но я пока не смог понять, как это сделать.
Я видел много примеры для класса Trainer, и я знаю, что SFTTrainer поддерживает параметр Compute_metrics в своем методе __init__, но мне не удалось соединить все части вместе.Быстрый просмотр обнаружил на GitHub следующие проблемы: https://github.com/huggingface/trl/issues/862 и https://github.com/huggingface/trl/issues/862
Как бы то ни было, мой набор данных отформатирован следующим образом:
- Train ==> приглашение + данные + ответ
Train ==> приглашение + данные + ответ
li>
Оценка ==> приглашение + данные + ответ (я знаю, что ответ следует удалить)
Тест ==> приглашение + данные
def create_trainer(self):
train_args = TrainingArguments(
per_device_train_batch_size=2,
gradient_accumulation_steps=2,
warmup_steps=200,
gradient_checkpointing=True,
per_device_eval_batch_size=1,
# num_train_epochs=self.num_of_epochs,
max_steps=10,
learning_rate=2e-4,
fp16=not is_bfloat16_supported(),
bf16=is_bfloat16_supported(),
logging_steps=1,
optim="adamw_8bit",
weight_decay=0.01,
lr_scheduler_type="cosine",
report_to="none",
seed=3407,
output_dir=self.output_dir,
eval_strategy="steps",
eval_steps=0.1,
)
trainer = SFTTrainer(
model=self.model,
compute_metrics=self.compute_metrics,
preprocess_logits_for_metrics=self.preprocess_logits_for_metrics,
tokenizer=self.tokenizer,
train_dataset=self.train_data,
eval_dataset=self.eval_data,
dataset_text_field="text",
max_seq_length=self.max_seq_length,
dataset_num_proc=2,
packing=False, # Can make training 5x faster for short sequences.
args=train_args,
dataset_kwargs={
"add_special_tokens": False,
"append_concat_token": False,
}
)
return trainer
а также
@staticmethod
def preprocess_logits_for_metrics(logits, labels):
"""
Original Trainer may have a memory leak.
This is a workaround to avoid storing too many tensors that are not needed.
"""
pred_ids = torch.argmax(logits[0], dim=-1)
return pred_ids, labels
@staticmethod
def compute_metrics(eval_pred):
# Unpack predictions and labels
predictions, _ = eval_pred.predictions
labels = eval_pred.label_ids
# Flatten labels if necessary
if labels.ndim > 1:
labels = labels.flatten()
# Ensure predictions are in the same format
if predictions.ndim > 1:
predictions = predictions.flatten()
# Remove invalid labels if necessary (e.g., -100)
valid_indices = labels != -100
# Handle size mismatch if needed
if len(predictions) != len(labels):
# You might need to slice or pad arrays here
min_len = min(len(predictions), len(labels))
labels = labels[:min_len]
predictions = predictions[:min_len]
valid_indices = valid_indices[:min_len]
# Filter out invalid indices
labels = labels[valid_indices]
predictions = predictions[valid_indices]
# Calculate accuracy, precision, recall, and F1 score
accuracy = accuracy_score(labels, predictions)
precision, recall, f1, _ = precision_recall_fscore_support(labels, predictions, average='weighted')
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1': f1,
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... sfttrainer