modelscope--ms-swift
471 行
23 KiB
Python
471 行
23 KiB
Python
# Copyright (c) ModelScope Contributors. All rights reserved.
|
|
import torch
|
|
import torch.nn as nn
|
|
import torch.nn.functional as F
|
|
import warnings
|
|
from accelerate.utils import gather_object
|
|
from contextlib import contextmanager, nullcontext
|
|
from peft import PeftModel
|
|
from transformers import PreTrainedModel
|
|
from transformers.utils.versions import require_version
|
|
from trl import DPOTrainer as HFDPOTrainer
|
|
from trl.trainer.dpo_config import DPOConfig
|
|
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
|
|
|
from swift.trainers import DataLoaderMixin, SwiftMixin
|
|
from swift.utils import get_logger, to_device
|
|
from .rlhf_mixin import RLHFTrainerMixin
|
|
|
|
try:
|
|
from trl.trainer.utils import RunningMoments
|
|
except ImportError:
|
|
# trl >= 0.29
|
|
from trl.experimental.bco.bco_trainer import RunningMoments
|
|
|
|
_ALPHA_DIVERGENCE_COEF_KEY = 'alpha_divergence_coef'
|
|
_ALPHA_DIVERGENCE_COEF_DEFAULT = 1.0
|
|
|
|
del HFDPOTrainer.__init__
|
|
logger = get_logger()
|
|
|
|
|
|
def _get_exp_cap(value, decimal=4):
|
|
vdtype_max = torch.zeros([1]).to(value.dtype) + torch.finfo(value.dtype).max
|
|
vdtype_log_max = torch.log(vdtype_max).to(value.device)
|
|
return torch.floor(vdtype_log_max * 10**decimal) / 10**decimal if decimal > 0 else vdtype_log_max
|
|
|
|
|
|
def _cap_exp(value, cap=-1):
|
|
cap = _get_exp_cap(value) if cap < 0 else cap
|
|
return torch.exp(torch.clamp(value, max=cap))
|
|
|
|
|
|
def new_gather_function(tensor):
|
|
tensor_list = gather_object([tensor])
|
|
tensor_list = [t[None] if t.ndim == 0 else t for t in tensor_list]
|
|
return torch.concat(to_device(tensor_list, tensor.device), dim=0)
|
|
|
|
|
|
class DPOTrainer(RLHFTrainerMixin, SwiftMixin, DataLoaderMixin, HFDPOTrainer):
|
|
|
|
def __init__(self,
|
|
model: Optional[Union[PreTrainedModel, nn.Module, str]] = None,
|
|
ref_model: Optional[Union[PreTrainedModel, nn.Module, str]] = None,
|
|
*_args,
|
|
**kwargs):
|
|
args = kwargs['args']
|
|
self.label_smoothing = args.label_smoothing
|
|
if 'loss_weights' in DPOConfig.__dict__:
|
|
# trl >= 0.20
|
|
self.loss_type = args.loss_type if isinstance(args.loss_type, list) else [args.loss_type]
|
|
self.loss_weights = args.loss_weights
|
|
else:
|
|
self.loss_type = args.loss_type
|
|
|
|
loss_types = self.loss_type if isinstance(self.loss_type, list) else [self.loss_type]
|
|
for loss_type in loss_types:
|
|
if (loss_type in ['hinge', 'ipo', 'bco_pair', 'sppo_hard', 'nca_pair', 'apo_zero', 'apo_down']
|
|
and args.label_smoothing > 0):
|
|
warnings.warn(
|
|
f'You are using the {loss_type} loss type that does not support label smoothing. The '
|
|
'`label_smoothing` parameter will be ignored. '
|
|
'Set `label_smoothing` to `0.0` to remove this warning.',
|
|
UserWarning,
|
|
)
|
|
if loss_type == 'kto_pair':
|
|
raise ValueError('Support for kto_pair has been removed in DPOTrainer. Please use KTOTrainer.')
|
|
|
|
self.precompute_ref_log_probs = args.precompute_ref_log_probs
|
|
self.f_divergence_type = getattr(args, 'f_divergence_type', 'reverse_kl')
|
|
self.f_alpha_divergence_coef = getattr(args, 'f_alpha_divergence_coef', 0.5)
|
|
self.f_divergence_params = {_ALPHA_DIVERGENCE_COEF_KEY: self.f_alpha_divergence_coef}
|
|
|
|
self.ref_adapter_name = getattr(args, 'ref_adapter_name', None)
|
|
self.model_adapter_name = None
|
|
self.reference_free = getattr(args, 'reference_free', None) or False
|
|
self.use_weighting = False
|
|
|
|
super().__init__(model, ref_model, *_args, **kwargs)
|
|
|
|
if 'bco_pair' in loss_types:
|
|
self.running = RunningMoments(self.accelerator)
|
|
|
|
if self.args.ld_alpha is not None:
|
|
require_version('trl>=0.18', '`ld_alpha` requires that "trl>=0.18".')
|
|
|
|
if self.template.packing:
|
|
self.accelerator.gather_for_metrics = new_gather_function
|
|
|
|
def concatenated_forward(
|
|
self,
|
|
model: nn.Module,
|
|
batch: Dict[str, Union[List, torch.LongTensor]],
|
|
is_ref_model: bool = False
|
|
) -> Tuple[torch.FloatTensor, torch.FloatTensor, torch.FloatTensor, torch.FloatTensor, torch.FloatTensor]:
|
|
batch = batch.copy()
|
|
|
|
use_logits_to_keep = self.get_use_logits_to_keep(self.template.sequence_parallel_size == 1)
|
|
if use_logits_to_keep:
|
|
self.prepare_logits_to_keep(batch)
|
|
if self.aux_loss_enabled:
|
|
batch['output_router_logits'] = True
|
|
labels = batch.pop('labels', None)
|
|
if self.is_encoder_decoder:
|
|
batch['labels'] = labels
|
|
text_position_ids = batch.pop('text_position_ids', None)
|
|
if text_position_ids is None:
|
|
text_position_ids = batch.get('position_ids')
|
|
outputs = model(**batch, use_cache=False)
|
|
all_logits = outputs.logits
|
|
|
|
if all_logits.shape[1] != labels.shape[1]:
|
|
# for llava, the model returns logits for the entire sequence, including the image tokens
|
|
# (placed before the text tokens)
|
|
all_logits = all_logits[:, -labels.shape[1]:]
|
|
|
|
if not self.is_encoder_decoder and self.template.sequence_parallel_size == 1:
|
|
# Shift so that tokens < n predict n
|
|
labels = torch.roll(labels, shifts=-1, dims=1)
|
|
per_token_logps, mean_all_logits, loss_mask = self.get_per_token_logps(
|
|
all_logits, labels, label_pad_token_id=self.label_pad_token_id)
|
|
origin_per_token_logps = per_token_logps
|
|
|
|
loss_types = self.loss_type if isinstance(self.loss_type, list) else [self.loss_type]
|
|
if 'ipo' in loss_types:
|
|
size_completion = loss_mask.sum(dim=-1)
|
|
per_token_logps = per_token_logps / size_completion
|
|
|
|
output = {}
|
|
if self.template.padding_free:
|
|
cu_seqlens = self.get_cu_seqlens(text_position_ids, batch.get('logits_to_keep'))
|
|
num_examples = (cu_seqlens.shape[0] - 1) // 2
|
|
all_logps = per_token_logps.new_zeros((num_examples * 2, ))
|
|
completion_lengths = (cu_seqlens[1:] - cu_seqlens[:-1])
|
|
chosen_lengths = completion_lengths[:num_examples]
|
|
rejected_lengths = completion_lengths[num_examples:]
|
|
public_lengths = torch.min(chosen_lengths, rejected_lengths) # l_p in the paper
|
|
|
|
for i in range(cu_seqlens.shape[0] - 1):
|
|
start, end = cu_seqlens[i], cu_seqlens[i + 1]
|
|
length = end - start
|
|
public_length = public_lengths[i % num_examples]
|
|
if self.args.ld_alpha is not None and not is_ref_model and length > public_length:
|
|
front_logps = per_token_logps[:, start:start + public_length].sum()
|
|
rear_logps = per_token_logps[:, start + public_length:end].sum()
|
|
all_logps[i] = front_logps + self.args.ld_alpha * rear_logps
|
|
else:
|
|
all_logps[i] = per_token_logps[:, start:end].sum()
|
|
num_tokens = cu_seqlens[num_examples]
|
|
if not is_ref_model:
|
|
output['nll_loss'] = -origin_per_token_logps[:, :num_tokens][loss_mask[:, :num_tokens]].mean()
|
|
output['chosen_logps'] = all_logps[:num_examples]
|
|
output['rejected_logps'] = all_logps[num_examples:]
|
|
output['mean_chosen_logits'] = mean_all_logits[:, :num_tokens][loss_mask[:, :num_tokens]].mean()
|
|
output['mean_rejected_logits'] = mean_all_logits[:, num_tokens:][loss_mask[:, num_tokens:]].mean()
|
|
else:
|
|
num_examples = labels.shape[0] // 2
|
|
if not is_ref_model:
|
|
output['nll_loss'] = -origin_per_token_logps[:num_examples][loss_mask[:num_examples]].mean()
|
|
if self.args.ld_alpha is not None and not is_ref_model:
|
|
completion_lengths = loss_mask.sum(dim=1)
|
|
|
|
chosen_lengths = completion_lengths[:num_examples]
|
|
rejected_lengths = completion_lengths[num_examples:]
|
|
public_lengths = torch.min(chosen_lengths, rejected_lengths) # l_p in the paper
|
|
public_lengths = torch.cat([public_lengths, public_lengths], dim=0)
|
|
|
|
# Use loss_mask to compute position within completion
|
|
# cumsum gives position within completion (1-indexed), subtract 1 to get 0-indexed
|
|
completion_position_ids = (loss_mask.cumsum(dim=1) - 1) * loss_mask
|
|
|
|
ld_mask = completion_position_ids < public_lengths.unsqueeze(1)
|
|
# front_mask: positions within public_lengths (shared prefix)
|
|
# rear_mask: positions beyond public_lengths (length-dependent suffix)
|
|
front_mask = (ld_mask & loss_mask).float()
|
|
rear_mask = (~ld_mask & loss_mask).float()
|
|
front_logps = (per_token_logps * front_mask).sum(dim=1)
|
|
rear_logps = (per_token_logps * rear_mask).sum(dim=1)
|
|
|
|
all_logps = front_logps + self.args.ld_alpha * rear_logps
|
|
else:
|
|
all_logps = per_token_logps.sum(-1)
|
|
output['chosen_logps'] = all_logps[:num_examples]
|
|
output['rejected_logps'] = all_logps[num_examples:]
|
|
output['mean_chosen_logits'] = mean_all_logits[:num_examples][loss_mask[:num_examples]].mean()
|
|
output['mean_rejected_logits'] = mean_all_logits[num_examples:][loss_mask[num_examples:]].mean()
|
|
if self.aux_loss_enabled:
|
|
output['aux_loss'] = outputs.aux_loss
|
|
return output
|
|
|
|
def compute_ref_log_probs(self, batch):
|
|
compute_ref_context_manager = (
|
|
torch.autocast(self.accelerator.device.type) if self._peft_has_been_casted_to_bf16 else nullcontext())
|
|
with torch.no_grad(), compute_ref_context_manager:
|
|
if self.ref_model is None:
|
|
with self.null_ref_context():
|
|
ref_model_output = self.concatenated_forward(self.model, batch, is_ref_model=True)
|
|
else:
|
|
ref_model_output = self.concatenated_forward(self.ref_model, batch, is_ref_model=True)
|
|
return ref_model_output['chosen_logps'], ref_model_output['rejected_logps']
|
|
|
|
def dpo_loss(
|
|
self,
|
|
chosen_logps: torch.FloatTensor,
|
|
rejected_logps: torch.FloatTensor,
|
|
ref_chosen_logps: torch.FloatTensor,
|
|
ref_rejected_logps: torch.FloatTensor,
|
|
loss_type: str = 'sigmoid',
|
|
model_output: Optional[Dict[str, torch.FloatTensor]] = None,
|
|
) -> Tuple[torch.FloatTensor, torch.FloatTensor, torch.FloatTensor]:
|
|
device = self.accelerator.device
|
|
|
|
chosen_logratios = chosen_logps.to(device) - (not self.reference_free) * ref_chosen_logps.to(device)
|
|
rejected_logratios = rejected_logps.to(device) - (not self.reference_free) * ref_rejected_logps.to(device)
|
|
|
|
if self.f_divergence_type == 'alpha_divergence':
|
|
alpha_coef = _ALPHA_DIVERGENCE_COEF_DEFAULT
|
|
if self.f_divergence_params and _ALPHA_DIVERGENCE_COEF_KEY in self.f_divergence_params:
|
|
alpha_coef = float(self.f_divergence_params[_ALPHA_DIVERGENCE_COEF_KEY])
|
|
logits = (_cap_exp(rejected_logratios * -alpha_coef)
|
|
- _cap_exp(chosen_logratios * -alpha_coef)) / alpha_coef
|
|
else:
|
|
logratios = chosen_logps - rejected_logps
|
|
if self.reference_free:
|
|
ref_logratios = torch.tensor([0], dtype=logratios.dtype, device=logratios.device)
|
|
else:
|
|
ref_logratios = ref_chosen_logps - ref_rejected_logps
|
|
|
|
logratios = logratios.to(device)
|
|
ref_logratios = ref_logratios.to(device)
|
|
logits = logratios - ref_logratios
|
|
|
|
if self.f_divergence_type == 'js_divergence':
|
|
logits -= F.softplus(chosen_logratios) - F.softplus(rejected_logratios)
|
|
|
|
if loss_type == 'sigmoid':
|
|
losses = (-F.logsigmoid(self.beta * logits) *
|
|
(1 - self.label_smoothing) - F.logsigmoid(-self.beta * logits) * self.label_smoothing)
|
|
|
|
elif loss_type == 'robust':
|
|
losses = (-F.logsigmoid(self.beta * logits) * (1 - self.label_smoothing)
|
|
+ F.logsigmoid(-self.beta * logits) * self.label_smoothing) / (1 - 2 * self.label_smoothing)
|
|
|
|
elif loss_type == 'exo_pair':
|
|
import math
|
|
if self.label_smoothing == 0:
|
|
self.label_smoothing = 1e-3
|
|
losses = (self.beta * logits).sigmoid() * (F.logsigmoid(
|
|
self.beta * logits) - math.log(1 - self.label_smoothing)) + (-self.beta * logits).sigmoid() * (
|
|
F.logsigmoid(-self.beta * logits) - math.log(self.label_smoothing))
|
|
|
|
elif loss_type == 'hinge':
|
|
losses = torch.relu(1 - self.beta * logits)
|
|
|
|
elif loss_type == 'ipo':
|
|
losses = (logits - 1 / (2 * self.beta))**2
|
|
|
|
elif loss_type == 'bco_pair':
|
|
chosen_logratios = chosen_logps - ref_chosen_logps
|
|
rejected_logratios = rejected_logps - ref_rejected_logps
|
|
chosen_rewards = self.beta * chosen_logratios
|
|
rejected_rewards = self.beta * rejected_logratios
|
|
rewards = torch.cat((chosen_rewards, rejected_rewards), 0).mean().detach()
|
|
self.running.update(rewards)
|
|
delta = self.running.mean
|
|
losses = -F.logsigmoid(
|
|
(self.beta * chosen_logratios) - delta) - F.logsigmoid(-(self.beta * rejected_logratios - delta))
|
|
|
|
elif loss_type == 'sppo_hard':
|
|
a = chosen_logps - ref_chosen_logps
|
|
b = rejected_logps - ref_rejected_logps
|
|
losses = (a - 0.5 / self.beta)**2 + (b + 0.5 / self.beta)**2
|
|
|
|
elif loss_type == 'nca_pair':
|
|
chosen_rewards = (chosen_logps - ref_chosen_logps) * self.beta
|
|
rejected_rewards = (rejected_logps - ref_rejected_logps) * self.beta
|
|
losses = (-F.logsigmoid(chosen_rewards) - 0.5 * F.logsigmoid(-chosen_rewards)
|
|
- 0.5 * F.logsigmoid(-rejected_rewards))
|
|
|
|
elif loss_type == 'aot_unpaired':
|
|
chosen_logratios = chosen_logps - ref_chosen_logps
|
|
rejected_logratios = rejected_logps - ref_rejected_logps
|
|
chosen_logratios_sorted, _ = torch.sort(chosen_logratios, dim=0)
|
|
rejected_logratios_sorted, _ = torch.sort(rejected_logratios, dim=0)
|
|
delta = chosen_logratios_sorted - rejected_logratios_sorted
|
|
losses = (-F.logsigmoid(self.beta * delta) *
|
|
(1 - self.label_smoothing) - F.logsigmoid(-self.beta * delta) * self.label_smoothing)
|
|
|
|
elif loss_type == 'aot':
|
|
logratios = chosen_logps - rejected_logps
|
|
ref_logratios = ref_chosen_logps - ref_rejected_logps
|
|
logratios_sorted, _ = torch.sort(logratios, dim=0)
|
|
ref_logratios_sorted, _ = torch.sort(ref_logratios, dim=0)
|
|
delta = logratios_sorted - ref_logratios_sorted
|
|
losses = (-F.logsigmoid(self.beta * delta) *
|
|
(1 - self.label_smoothing) - F.logsigmoid(-self.beta * delta) * self.label_smoothing)
|
|
|
|
elif loss_type == 'apo_zero':
|
|
losses_chosen = 1 - F.sigmoid(self.beta * chosen_logratios)
|
|
losses_rejected = F.sigmoid(self.beta * rejected_logratios)
|
|
losses = losses_chosen + losses_rejected
|
|
|
|
elif loss_type == 'apo_down':
|
|
losses_chosen = F.sigmoid(self.beta * chosen_logratios)
|
|
losses_rejected = 1 - F.sigmoid(self.beta * (chosen_logratios - rejected_logratios))
|
|
losses = losses_chosen + losses_rejected
|
|
|
|
elif loss_type == 'discopop':
|
|
logratios = chosen_logps - rejected_logps
|
|
ref_logratios = ref_chosen_logps - ref_rejected_logps
|
|
logits = logratios - ref_logratios
|
|
logits = logits * self.beta
|
|
log_ratio_modulation = torch.sigmoid(logits / self.args.discopop_tau)
|
|
logistic_component = -F.logsigmoid(logits)
|
|
exp_component = torch.exp(-logits)
|
|
losses = logistic_component * (1 - log_ratio_modulation) + exp_component * log_ratio_modulation
|
|
|
|
elif loss_type == 'sft':
|
|
sft_loss = model_output['nll_loss']
|
|
batch_size = chosen_logps.shape[0]
|
|
losses = sft_loss.expand(batch_size)
|
|
chosen_rewards = torch.zeros_like(chosen_logps)
|
|
rejected_rewards = torch.zeros_like(rejected_logps)
|
|
|
|
else:
|
|
raise ValueError(
|
|
f"Unknown loss type: {self.loss_type}. Should be one of ['sigmoid', 'hinge', 'ipo', 'exo_pair', "
|
|
"'nca_pair', 'robust', 'bco_pair', 'sppo_hard', 'aot', 'aot_unpaired', 'discopop', 'apo_zero', "
|
|
"'apo_down', 'sft']")
|
|
|
|
chosen_rewards = self.beta * (chosen_logps.to(device) - ref_chosen_logps.to(device)).detach()
|
|
rejected_rewards = self.beta * (rejected_logps.to(device) - ref_rejected_logps.to(device)).detach()
|
|
|
|
return losses, chosen_rewards, rejected_rewards
|
|
|
|
def get_batch_loss_metrics(
|
|
self,
|
|
model: Union[PreTrainedModel, nn.Module],
|
|
batch: Dict[str, Union[List, torch.LongTensor]],
|
|
train_eval: Literal['train', 'eval'] = 'train',
|
|
) -> Tuple[torch.Tensor, Dict[str, float]]:
|
|
metrics = {}
|
|
|
|
model_output = self.concatenated_forward(model, batch)
|
|
|
|
if 'ref_chosen_logps' in batch and 'ref_rejected_logps' in batch:
|
|
ref_chosen_logps = batch['ref_chosen_logps']
|
|
ref_rejected_logps = batch['ref_rejected_logps']
|
|
else:
|
|
ref_chosen_logps, ref_rejected_logps = self.compute_ref_log_probs(batch)
|
|
|
|
losses = 0
|
|
chosen_rewards = 0
|
|
rejected_rewards = 0
|
|
|
|
loss_types = self.loss_type if isinstance(self.loss_type, list) else [self.loss_type]
|
|
loss_weights = self.loss_weights if hasattr(self, 'loss_weights') and self.loss_weights else None
|
|
for idx, loss_type in enumerate(loss_types):
|
|
_losses, _chosen_rewards, _rejected_rewards = self.dpo_loss(
|
|
model_output['chosen_logps'],
|
|
model_output['rejected_logps'],
|
|
ref_chosen_logps,
|
|
ref_rejected_logps,
|
|
loss_type,
|
|
model_output,
|
|
)
|
|
weight = loss_weights[idx] if loss_weights else 1.0
|
|
losses = losses + _losses * weight
|
|
chosen_rewards = chosen_rewards + _chosen_rewards * weight
|
|
rejected_rewards = rejected_rewards + _rejected_rewards * weight
|
|
|
|
reward_accuracies = (chosen_rewards > rejected_rewards).float()
|
|
|
|
if self.args.rpo_alpha is not None:
|
|
losses = losses + self.args.rpo_alpha * model_output['nll_loss']
|
|
|
|
if self.use_weighting:
|
|
losses = losses * model_output['policy_weights']
|
|
|
|
if self.aux_loss_enabled:
|
|
losses = losses + self.aux_loss_coef * model_output['aux_loss']
|
|
|
|
prefix = 'eval_' if train_eval == 'eval' else ''
|
|
metrics[f'{prefix}rewards/chosen'] = self.accelerator.gather_for_metrics(chosen_rewards).mean().item()
|
|
metrics[f'{prefix}rewards/rejected'] = self.accelerator.gather_for_metrics(rejected_rewards).mean().item()
|
|
metrics[f'{prefix}rewards/accuracies'] = self.accelerator.gather_for_metrics(reward_accuracies).mean().item()
|
|
metrics[f'{prefix}rewards/margins'] = (
|
|
self.accelerator.gather_for_metrics(chosen_rewards - rejected_rewards).mean().item())
|
|
metrics[f'{prefix}logps/chosen'] = (
|
|
self.accelerator.gather_for_metrics(model_output['chosen_logps']).detach().mean().item())
|
|
metrics[f'{prefix}logps/rejected'] = (
|
|
self.accelerator.gather_for_metrics(model_output['rejected_logps']).detach().mean().item())
|
|
metrics[f'{prefix}logits/chosen'] = (
|
|
self.accelerator.gather_for_metrics(model_output['mean_chosen_logits']).detach().mean().item())
|
|
metrics[f'{prefix}logits/rejected'] = (
|
|
self.accelerator.gather_for_metrics(model_output['mean_rejected_logits']).detach().mean().item())
|
|
if self.args.rpo_alpha is not None or 'sft' in loss_types:
|
|
metrics[f'{prefix}nll_loss'] = (
|
|
self.accelerator.gather_for_metrics(model_output['nll_loss']).detach().mean().item())
|
|
if self.aux_loss_enabled:
|
|
metrics[f'{prefix}aux_loss'] = (
|
|
self.accelerator.gather_for_metrics(model_output['aux_loss']).detach().mean().item())
|
|
|
|
return losses.mean(), metrics
|
|
|
|
def store_metrics(self, metrics, train_eval='train'):
|
|
for key, value in metrics.items():
|
|
self._stored_metrics[train_eval][key].append(value)
|
|
|
|
def log(self, logs, start_time=None):
|
|
from transformers import Trainer
|
|
train_eval = 'train' if 'loss' in logs else 'eval'
|
|
for key, metrics in self._stored_metrics[train_eval].items():
|
|
logs[key] = torch.tensor(metrics).mean().item()
|
|
del self._stored_metrics[train_eval]
|
|
mode = 'train' if self.model.training else 'eval'
|
|
custom_metrics = self.custom_metrics[mode]
|
|
prefix = 'eval_' if mode == 'eval' else ''
|
|
logs.update(self.compute_custom_metrics(custom_metrics, prefix))
|
|
return Trainer.log(self, logs, start_time)
|
|
|
|
def compute_loss(self, model, inputs, return_outputs=False, num_items_in_batch=None):
|
|
compute_loss_context_manager = (
|
|
torch.autocast(self.accelerator.device.type) if self._peft_has_been_casted_to_bf16 else nullcontext())
|
|
with compute_loss_context_manager:
|
|
loss, metrics = self.get_batch_loss_metrics(model, inputs, train_eval='train')
|
|
|
|
loss = loss.to(self.args.device)
|
|
self.store_metrics(metrics, train_eval='train')
|
|
|
|
if num_items_in_batch is not None and self.model_accepts_loss_kwargs:
|
|
loss = loss / self.args.gradient_accumulation_steps
|
|
|
|
if return_outputs:
|
|
return loss, metrics
|
|
return loss
|
|
|
|
def training_step(self, model, inputs, *args, **kwargs):
|
|
with self.template.forward_context(self.model, inputs):
|
|
return super().training_step(model, inputs, *args, **kwargs)
|
|
|
|
def prediction_step(self, model, inputs, prediction_loss_only=False, *args, **kwargs):
|
|
with self.template.forward_context(self.model, inputs):
|
|
inputs = self._prepare_inputs(inputs)
|
|
|
|
with torch.no_grad():
|
|
loss, metrics = self.get_batch_loss_metrics(model, inputs, train_eval='eval')
|
|
|
|
self.store_metrics(metrics, train_eval='eval')
|
|
|
|
if prediction_loss_only:
|
|
return loss.detach(), None, None
|
|
|
|
logits_dict = {
|
|
'eval_logits/chosen': metrics['eval_logits/chosen'],
|
|
'eval_logits/rejected': metrics['eval_logits/rejected'],
|
|
}
|
|
logits = torch.tensor(list(logits_dict.values()), device=self.accelerator.device)
|
|
labels = torch.zeros(logits.shape[0], device=self.accelerator.device)
|
|
|
|
return (loss.detach(), logits, labels)
|