defget_grad_norm_(parameters, norm_type: float = 2.0) -> torch.Tensor: """ Calculate the norm of gradient. :param parameters: model parameters :param norm_type: type of norm, e.g. l2 norm, infinity norm, etc. :return: norm of all gradient, stored in torch.Tensor """ ifisinstance(parameters, torch.Tensor): parameters = [parameters] # 先判断传入的是不是Tensor,如果是,将其装入一个列表中 parameters = [p for p in parameters if p.grad isnotNone] # 对列表中的参数遍历,只取出那些有梯度的参数 norm_type = float(norm_type) # 转换norm_type,作为torch.norm的参数 iflen(parameters) == 0: return torch.tensor(0.) # 如果是个空列表,那么没有需要计算的,返回0 device = parameters[0].grad.device # 获取目前使用的设备 if torch.isinf(torch.Tensor([norm_type])).item(): total_norm = max(p.grad.detach().abs().max().to(device) for p in parameters) # 如果使用无穷范数,那么找其绝对值的最大值,利用目前设备计算 else: total_norm = torch.norm(torch.stack([torch.norm(p.grad.detach(), norm_type).to(device) for p in parameters]), norm_type) # 如果不是,使用troch.norm来得到范数,范数的类型由参数决定 return total_norm # 返回梯度的范数
接下来在训练engine中,代码也有少许改动
1 2 3 4 5 6 7 8 9
if use_amp: # 如果使用了AMP with torch.cuda.amp.autocast(): # 需要添加autocast来进行前向推理 output = model(samples) loss = criterion(output, targets) else: # full precision output = model(samples) loss = criterion(output, targets)