o  i-@sddlmZddlZddlmZddlmZddlZddlm m Z ddl m Z ddlmZddlmZGdd d e Z ddddZ ddddZdS)) annotationsN)Sequence)Optional)_Loss)one_hot) LossReductioncs>eZdZdZdddddejdfdfdd ZdddZZS) FocalLossa FocalLoss is an extension of BCEWithLogitsLoss that down-weights loss from high confidence correct predictions. Reimplementation of the Focal Loss described in: - ["Focal Loss for Dense Object Detection"](https://arxiv.org/abs/1708.02002), T. Lin et al., ICCV 2017 - "AnatomyNet: Deep learning for fast and fully automated whole-volume segmentation of head and neck anatomy", Zhu et al., Medical Physics 2018 Example: >>> import torch >>> from monai.losses import FocalLoss >>> from torch.nn import BCEWithLogitsLoss >>> shape = B, N, *DIMS = 2, 3, 5, 7, 11 >>> input = torch.rand(*shape) >>> target = torch.rand(*shape) >>> # Demonstrate equivalence to BCE when gamma=0 >>> fl_g0_criterion = FocalLoss(reduction='none', gamma=0) >>> fl_g0_loss = fl_g0_criterion(input, target) >>> bce_criterion = BCEWithLogitsLoss(reduction='none') >>> bce_loss = bce_criterion(input, target) >>> assert torch.allclose(fl_g0_loss, bce_loss) >>> # Demonstrate "focus" by setting gamma > 0. >>> fl_g2_criterion = FocalLoss(reduction='none', gamma=2) >>> fl_g2_loss = fl_g2_criterion(input, target) >>> # Mark easy and hard cases >>> is_easy = (target > 0.7) & (input > 0.7) >>> is_hard = (target > 0.7) & (input < 0.3) >>> easy_loss_g0 = fl_g0_loss[is_easy].mean() >>> hard_loss_g0 = fl_g0_loss[is_hard].mean() >>> easy_loss_g2 = fl_g2_loss[is_easy].mean() >>> hard_loss_g2 = fl_g2_loss[is_hard].mean() >>> # Gamma > 0 causes the loss function to "focus" on the hard >>> # cases. IE, easy cases are downweighted, so hard cases >>> # receive a higher proportion of the loss. >>> hard_to_easy_ratio_g2 = hard_loss_g2 / easy_loss_g2 >>> hard_to_easy_ratio_g0 = hard_loss_g0 / easy_loss_g0 >>> assert hard_to_easy_ratio_g2 > hard_to_easy_ratio_g0 TF@Ninclude_backgroundbool to_onehot_ygammafloatalpha float | Noneweight3Sequence[float] | float | int | torch.Tensor | None reductionLossReduction | str use_softmaxreturnNonecsbtjt|jd||_||_||_||_||_||_ |dur%t |nd}| d||dS)a Args: include_background: if False, channel index 0 (background category) is excluded from the loss calculation. If False, `alpha` is invalid when using softmax. to_onehot_y: whether to convert the label `y` into the one-hot format. Defaults to False. gamma: value of the exponent gamma in the definition of the Focal loss. Defaults to 2. alpha: value of the alpha in the definition of the alpha-balanced Focal loss. The value should be in [0, 1]. Defaults to None. weight: weights to apply to the voxels of each class. If None no weights are applied. The input can be a single value (same weight for all classes), a sequence of values (the length of the sequence should be the same as the number of classes. If not ``include_background``, the number of classes should not include the background category class 0). The value/values should be no less than 0. Defaults to None. reduction: {``"none"``, ``"mean"``, ``"sum"``} Specifies the reduction to apply to the output. Defaults to ``"mean"``. - ``"none"``: no reduction will be applied. - ``"mean"``: the sum of the output will be divided by the number of elements in the output. - ``"sum"``: the output will be summed. use_softmax: whether to use softmax to transform the original logits into probabilities. If True, softmax is used. If False, sigmoid is used. Defaults to False. Example: >>> import torch >>> from monai.losses import FocalLoss >>> pred = torch.tensor([[1, 0], [0, 1], [1, 0]], dtype=torch.float32) >>> grnd = torch.tensor([[0], [1], [0]], dtype=torch.int64) >>> fl = FocalLoss(to_onehot_y=True) >>> fl(pred, grnd) )rN class_weight) super__init__rvaluer r r rrrtorch as_tensorregister_buffer)selfr r r rrrr __class__Y/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/losses/focal_loss.pyrDs) zFocalLoss.__init__input torch.TensortargetcCs*|jd}|jr|dkrtdnt||d}|js9|dkr%tdn|ddddf}|ddddf}|j|jkrLtd|jd|jdd}|}|}|jrs|jsi|j durid|_ td t |||j |j }n t |||j |j }|jd}|j dur|dkr|j jd krt|j g||_ n |j jd |krtd |j d krtd |j ||_ d gdgt|jdd}|j ||_ |j |}|jtjjkrd}|r|jttdt|jd}|}|S|jtjjkr|}|S|jtjjkr |Std|jd)a Args: input: the shape should be BNH[WD], where N is the number of classes. The input should be the original logits since it will be transformed by a sigmoid/softmax in the forward function. target: the shape should be BNH[WD] or B1H[WD], where N is the number of classes. Raises: ValueError: When input and target (after one hot transform if set) have different shapes. ValueError: When ``self.reduction`` is not one of ["mean", "sum", "none"]. ValueError: When ``self.weight`` is a sequence and the length is not equal to the number of classes. ValueError: When ``self.weight`` is/contains a value that is less than 0. z6single channel prediction, `to_onehot_y=True` ignored.) num_classesz>single channel prediction, `include_background=False` ignored.Nz"ground truth has different shape (z) from input ()z?`include_background=False`, `alpha` ignored when using softmax.rzthe length of the `weight` sequence should be the same as the number of classes. If `include_background=False`, the weight should not include the background category class 0.z:the value/values of the `weight` should be no less than 0.T)dimzUnsupported reduction: z0, available options are ["mean", "sum", "none"].)shaper warningswarnrr ValueErrorrrrsoftmax_focal_lossr sigmoid_focal_lossrndimrrmintolenviewrrSUMrmeanlistrangesumMEANNONE)rr$r& n_pred_chlossnum_of_classesbroadcast_dimsZaverage_spatial_dimsr"r"r#forwardxs`         zFocalLoss.forward)r r r r r rrrrrrrrr rr)r$r%r&r%rr%) __name__ __module__ __qualname____doc__rr=rrC __classcell__r"r"r r#rs+4rr r$r%r&r rrOptional[float]rcCs|d}d|| ||}|durDtd|g|g|jdd|}dgdgt|jdd}||}||}|S)z FL(pt) = -alpha * (1 - pt)**gamma * log(pt) where p_i = exp(s_i) / sum_j exp(s_j), t is the target (ground truth) class, and s_j is the unnormalized score for class j. r'Nr*r+) log_softmaxexppowrtensorr-r5r6r7)r$r&r rZinput_lsr@Z alpha_facrBr"r"r#r1s * r1cCsj|||t|}t| |dd}|||}|dur3||d|d|}||}|S)z| FL(pt) = -alpha * (1 - pt)**gamma * log(pt) where p = sigmoid(x), pt = p if label is 1 or 1 - p if label is 0 r+r'N)F logsigmoidrK)r$r&r rr@ZinvprobsZ alpha_factorr"r"r#r2s r2)r N) r$r%r&r%r rrrIrr%) __future__rr.collections.abcrtypingrrtorch.nn.functionalnn functionalrNtorch.nn.modules.lossrmonai.networksr monai.utilsrrr1r2r"r"r"r#s      5