{
  "id": 213779,
  "title": "Recall loss and CCE loss",
  "url": "/competitions/cassava-leaf-disease-classification/discussion/213779",
  "author_name": "DarknessZX",
  "post_date": "2021-01-24T08:51:22.609000",
  "votes": 3,
  "comment_count": 0,
  "views": 0,
  "content": "<p>Any one try these methods？<br>\nI find two interesting work，the code ：<br>\n<a href=\"https://github.com/unique-chan/Complement-Cross-Entropy\" target=\"_blank\">https://github.com/unique-chan/Complement-Cross-Entropy</a><br>\n<a href=\"https://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py\" target=\"_blank\">https://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py</a><br>\nbut i have not try to use them，if these methods works in your code,please contact me,thank you!!</p>\n<p>class RecallLoss(nn.Module):<br>\n    \"\"\" An unofficial implementation of<br>\n        <br>\n        Created by: Zhang Shuai<br>\n        Email: <a>shuaizzz666@gmail.com</a><br>\n        recall = TP / (TP + FN)<br>\n    Args:<br>\n        weight: An array of shape [C,]<br>\n        predict: A float32 tensor of shape [N, C, *], for Semantic segmentation task is [N, C, H, W]<br>\n        target: A int64 tensor of shape [N, *], for Semantic segmentation task is [N, H, W]<br>\n    Return:<br>\n        diceloss<br>\n    \"\"\"<br>\n    def <strong>init</strong>(self, weight=None):<br>\n        super(RecallLoss, self).<strong>init</strong>()<br>\n        if weight is not None:<br>\n            weight = torch.Tensor(weight)<br>\n            self.weight = weight / torch.sum(weight) # Normalized weight<br>\n        self.smooth = 1e-5</p>\n<pre><code>def forward(self, input, target):\n    N, C = input.size()[:2]\n    _, predict = torch.max(input, 1)# # (N, C, *) ==&gt; (N, 1, *)\n\n    predict = predict.view(N, 1, -1) # (N, 1, *)\n    target = target.view(N, 1, -1) # (N, 1, *)\n    last_size = target.size(-1)\n\n    ## convert predict &amp; target (N, 1, *) into one hot vector (N, C, *)\n    predict_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==&gt; (N, C, *)\n    predict_onehot.scatter_(1, predict, 1) # (N, C, *)\n    target_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==&gt; (N, C, *)\n    target_onehot.scatter_(1, target, 1) # (N, C, *)\n\n    true_positive = torch.sum(predict_onehot * target_onehot, dim=2)  # (N, C)\n    total_target = torch.sum(target_onehot, dim=2)  # (N, C)\n    ## Recall = TP / (TP + FN)\n    recall = (true_positive + self.smooth) / (total_target + self.smooth)  # (N, C)\n\n    if hasattr(self, 'weight'):\n        if self.weight.type() != input.type():\n            self.weight = self.weight.type_as(input)\n            recall = recall * self.weight * C  # (N, C)\n    recall_loss = 1 - torch.mean(recall)  # 1\n\n    return recall_loss\n</code></pre>\n<p>class ComplementEntropy(nn.Module):<br>\n    '''Compute the complement entropy of complement classes.'''<br>\n    def <strong>init</strong>(self, num_classes=100):<br>\n        super(ComplementEntropy, self).<strong>init</strong>()<br>\n        self.classes = num_classes<br>\n        self.batch_size = None</p>\n<pre><code>def forward(self, y_hat, y):\n    self.batch_size = len(y)\n    y_hat = F.softmax(y_hat, dim=1)\n    Yg = torch.gather(y_hat, 1, torch.unsqueeze(y, 1))\n    Yg_ = (1 - Yg) + 1e-7\n    Px = y_hat / Yg_.view(len(y_hat), 1)\n    Px_log = torch.log(Px + 1e-10)\n    y_zerohot = torch.ones(self.batch_size, self.classes).scatter_\\\n        (1, y.view(self.batch_size, 1).data.cpu(), 0)\n    output = Px * Px_log * y_zerohot.cuda()\n    entropy = torch.sum(output)\n    entropy /= float(self.batch_size)\n    entropy /= float(self.classes)\n    return entropy\n</code></pre>\n<p>class ComplementCrossEntropy(nn.Module):<br>\n    def <strong>init</strong>(self, num_classes=100, gamma=5):<br>\n        super(ComplementCrossEntropy, self).<strong>init</strong>()<br>\n        self.gamma = gamma<br>\n        self.cross_entropy = nn.CrossEntropyLoss()<br>\n        self.complement_entropy = ComplementEntropy(num_classes)</p>\n<pre><code>def forward(self, y_hat, y):\n    l1 = self.cross_entropy(y_hat, y)\n    l2 = self.complement_entropy(y_hat, y)\n    return l1 + self.gamma * l2\n</code></pre>\n<p>thank you very much!👍</p>",
  "messages": [
    {
      "id": 1167432,
      "postDate": "2021-01-24T08:51:22.610Z",
      "content": "<p>Any one try these methods？<br>\nI find two interesting work，the code ：<br>\n<a href=\"https://github.com/unique-chan/Complement-Cross-Entropy\" target=\"_blank\">https://github.com/unique-chan/Complement-Cross-Entropy</a><br>\n<a href=\"https://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py\" target=\"_blank\">https://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py</a><br>\nbut i have not try to use them，if these methods works in your code,please contact me,thank you!!</p>\n<p>class RecallLoss(nn.Module):<br>\n    \"\"\" An unofficial implementation of<br>\n        <br>\n        Created by: Zhang Shuai<br>\n        Email: <a>shuaizzz666@gmail.com</a><br>\n        recall = TP / (TP + FN)<br>\n    Args:<br>\n        weight: An array of shape [C,]<br>\n        predict: A float32 tensor of shape [N, C, *], for Semantic segmentation task is [N, C, H, W]<br>\n        target: A int64 tensor of shape [N, *], for Semantic segmentation task is [N, H, W]<br>\n    Return:<br>\n        diceloss<br>\n    \"\"\"<br>\n    def <strong>init</strong>(self, weight=None):<br>\n        super(RecallLoss, self).<strong>init</strong>()<br>\n        if weight is not None:<br>\n            weight = torch.Tensor(weight)<br>\n            self.weight = weight / torch.sum(weight) # Normalized weight<br>\n        self.smooth = 1e-5</p>\n<pre><code>def forward(self, input, target):\n    N, C = input.size()[:2]\n    _, predict = torch.max(input, 1)# # (N, C, *) ==&gt; (N, 1, *)\n\n    predict = predict.view(N, 1, -1) # (N, 1, *)\n    target = target.view(N, 1, -1) # (N, 1, *)\n    last_size = target.size(-1)\n\n    ## convert predict &amp; target (N, 1, *) into one hot vector (N, C, *)\n    predict_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==&gt; (N, C, *)\n    predict_onehot.scatter_(1, predict, 1) # (N, C, *)\n    target_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==&gt; (N, C, *)\n    target_onehot.scatter_(1, target, 1) # (N, C, *)\n\n    true_positive = torch.sum(predict_onehot * target_onehot, dim=2)  # (N, C)\n    total_target = torch.sum(target_onehot, dim=2)  # (N, C)\n    ## Recall = TP / (TP + FN)\n    recall = (true_positive + self.smooth) / (total_target + self.smooth)  # (N, C)\n\n    if hasattr(self, 'weight'):\n        if self.weight.type() != input.type():\n            self.weight = self.weight.type_as(input)\n            recall = recall * self.weight * C  # (N, C)\n    recall_loss = 1 - torch.mean(recall)  # 1\n\n    return recall_loss\n</code></pre>\n<p>class ComplementEntropy(nn.Module):<br>\n    '''Compute the complement entropy of complement classes.'''<br>\n    def <strong>init</strong>(self, num_classes=100):<br>\n        super(ComplementEntropy, self).<strong>init</strong>()<br>\n        self.classes = num_classes<br>\n        self.batch_size = None</p>\n<pre><code>def forward(self, y_hat, y):\n    self.batch_size = len(y)\n    y_hat = F.softmax(y_hat, dim=1)\n    Yg = torch.gather(y_hat, 1, torch.unsqueeze(y, 1))\n    Yg_ = (1 - Yg) + 1e-7\n    Px = y_hat / Yg_.view(len(y_hat), 1)\n    Px_log = torch.log(Px + 1e-10)\n    y_zerohot = torch.ones(self.batch_size, self.classes).scatter_\\\n        (1, y.view(self.batch_size, 1).data.cpu(), 0)\n    output = Px * Px_log * y_zerohot.cuda()\n    entropy = torch.sum(output)\n    entropy /= float(self.batch_size)\n    entropy /= float(self.classes)\n    return entropy\n</code></pre>\n<p>class ComplementCrossEntropy(nn.Module):<br>\n    def <strong>init</strong>(self, num_classes=100, gamma=5):<br>\n        super(ComplementCrossEntropy, self).<strong>init</strong>()<br>\n        self.gamma = gamma<br>\n        self.cross_entropy = nn.CrossEntropyLoss()<br>\n        self.complement_entropy = ComplementEntropy(num_classes)</p>\n<pre><code>def forward(self, y_hat, y):\n    l1 = self.cross_entropy(y_hat, y)\n    l2 = self.complement_entropy(y_hat, y)\n    return l1 + self.gamma * l2\n</code></pre>\n<p>thank you very much!👍</p>",
      "rawMarkdown": "Any one try these methods？\nI find two interesting work，the code ：\nhttps://github.com/unique-chan/Complement-Cross-Entropy\nhttps://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py\nbut i have not try to use them，if these methods works in your code,please contact me,thank you!!\n\nclass RecallLoss(nn.Module):\n    \"\"\" An unofficial implementation of\n        <Recall Loss for Imbalanced Image Classification and Semantic Segmentation>\n        Created by: Zhang Shuai\n        Email: shuaizzz666@gmail.com\n        recall = TP / (TP + FN)\n    Args:\n        weight: An array of shape [C,]\n        predict: A float32 tensor of shape [N, C, *], for Semantic segmentation task is [N, C, H, W]\n        target: A int64 tensor of shape [N, *], for Semantic segmentation task is [N, H, W]\n    Return:\n        diceloss\n    \"\"\"\n    def __init__(self, weight=None):\n        super(RecallLoss, self).__init__()\n        if weight is not None:\n            weight = torch.Tensor(weight)\n            self.weight = weight / torch.sum(weight) # Normalized weight\n        self.smooth = 1e-5\n\n    def forward(self, input, target):\n        N, C = input.size()[:2]\n        _, predict = torch.max(input, 1)# # (N, C, *) ==> (N, 1, *)\n\n        predict = predict.view(N, 1, -1) # (N, 1, *)\n        target = target.view(N, 1, -1) # (N, 1, *)\n        last_size = target.size(-1)\n\n        ## convert predict & target (N, 1, *) into one hot vector (N, C, *)\n        predict_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==> (N, C, *)\n        predict_onehot.scatter_(1, predict, 1) # (N, C, *)\n        target_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==> (N, C, *)\n        target_onehot.scatter_(1, target, 1) # (N, C, *)\n\n        true_positive = torch.sum(predict_onehot * target_onehot, dim=2)  # (N, C)\n        total_target = torch.sum(target_onehot, dim=2)  # (N, C)\n        ## Recall = TP / (TP + FN)\n        recall = (true_positive + self.smooth) / (total_target + self.smooth)  # (N, C)\n\n        if hasattr(self, 'weight'):\n            if self.weight.type() != input.type():\n                self.weight = self.weight.type_as(input)\n                recall = recall * self.weight * C  # (N, C)\n        recall_loss = 1 - torch.mean(recall)  # 1\n\n        return recall_loss\n\n\nclass ComplementEntropy(nn.Module):\n    '''Compute the complement entropy of complement classes.'''\n    def __init__(self, num_classes=100):\n        super(ComplementEntropy, self).__init__()\n        self.classes = num_classes\n        self.batch_size = None\n\n    def forward(self, y_hat, y):\n        self.batch_size = len(y)\n        y_hat = F.softmax(y_hat, dim=1)\n        Yg = torch.gather(y_hat, 1, torch.unsqueeze(y, 1))\n        Yg_ = (1 - Yg) + 1e-7\n        Px = y_hat / Yg_.view(len(y_hat), 1)\n        Px_log = torch.log(Px + 1e-10)\n        y_zerohot = torch.ones(self.batch_size, self.classes).scatter_\\\n            (1, y.view(self.batch_size, 1).data.cpu(), 0)\n        output = Px * Px_log * y_zerohot.cuda()\n        entropy = torch.sum(output)\n        entropy /= float(self.batch_size)\n        entropy /= float(self.classes)\n        return entropy\n\n\nclass ComplementCrossEntropy(nn.Module):\n    def __init__(self, num_classes=100, gamma=5):\n        super(ComplementCrossEntropy, self).__init__()\n        self.gamma = gamma\n        self.cross_entropy = nn.CrossEntropyLoss()\n        self.complement_entropy = ComplementEntropy(num_classes)\n\n    def forward(self, y_hat, y):\n        l1 = self.cross_entropy(y_hat, y)\n        l2 = self.complement_entropy(y_hat, y)\n        return l1 + self.gamma * l2\n\nthank you very much!👍",
      "votes": 3
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "1167432": "Any one try these methods？\nI find two interesting work，the code ：\nhttps://github.com/unique-chan/Complement-Cross-Entropy\nhttps://github.com/shuaizzZ/Recall-Loss-PyTorch/blob/master/recall_loss.py\nbut i have not try to use them，if these methods works in your code,please contact me,thank you!!\n\nclass RecallLoss(nn.Module):\n    \"\"\" An unofficial implementation of\n        <Recall Loss for Imbalanced Image Classification and Semantic Segmentation>\n        Created by: Zhang Shuai\n        Email: shuaizzz666@gmail.com\n        recall = TP / (TP + FN)\n    Args:\n        weight: An array of shape [C,]\n        predict: A float32 tensor of shape [N, C, *], for Semantic segmentation task is [N, C, H, W]\n        target: A int64 tensor of shape [N, *], for Semantic segmentation task is [N, H, W]\n    Return:\n        diceloss\n    \"\"\"\n    def __init__(self, weight=None):\n        super(RecallLoss, self).__init__()\n        if weight is not None:\n            weight = torch.Tensor(weight)\n            self.weight = weight / torch.sum(weight) # Normalized weight\n        self.smooth = 1e-5\n\n    def forward(self, input, target):\n        N, C = input.size()[:2]\n        _, predict = torch.max(input, 1)# # (N, C, *) ==> (N, 1, *)\n\n        predict = predict.view(N, 1, -1) # (N, 1, *)\n        target = target.view(N, 1, -1) # (N, 1, *)\n        last_size = target.size(-1)\n\n        ## convert predict & target (N, 1, *) into one hot vector (N, C, *)\n        predict_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==> (N, C, *)\n        predict_onehot.scatter_(1, predict, 1) # (N, C, *)\n        target_onehot = torch.zeros((N, C, last_size)).cuda() # (N, 1, *) ==> (N, C, *)\n        target_onehot.scatter_(1, target, 1) # (N, C, *)\n\n        true_positive = torch.sum(predict_onehot * target_onehot, dim=2)  # (N, C)\n        total_target = torch.sum(target_onehot, dim=2)  # (N, C)\n        ## Recall = TP / (TP + FN)\n        recall = (true_positive + self.smooth) / (total_target + self.smooth)  # (N, C)\n\n        if hasattr(self, 'weight'):\n            if self.weight.type() != input.type():\n                self.weight = self.weight.type_as(input)\n                recall = recall * self.weight * C  # (N, C)\n        recall_loss = 1 - torch.mean(recall)  # 1\n\n        return recall_loss\n\n\nclass ComplementEntropy(nn.Module):\n    '''Compute the complement entropy of complement classes.'''\n    def __init__(self, num_classes=100):\n        super(ComplementEntropy, self).__init__()\n        self.classes = num_classes\n        self.batch_size = None\n\n    def forward(self, y_hat, y):\n        self.batch_size = len(y)\n        y_hat = F.softmax(y_hat, dim=1)\n        Yg = torch.gather(y_hat, 1, torch.unsqueeze(y, 1))\n        Yg_ = (1 - Yg) + 1e-7\n        Px = y_hat / Yg_.view(len(y_hat), 1)\n        Px_log = torch.log(Px + 1e-10)\n        y_zerohot = torch.ones(self.batch_size, self.classes).scatter_\\\n            (1, y.view(self.batch_size, 1).data.cpu(), 0)\n        output = Px * Px_log * y_zerohot.cuda()\n        entropy = torch.sum(output)\n        entropy /= float(self.batch_size)\n        entropy /= float(self.classes)\n        return entropy\n\n\nclass ComplementCrossEntropy(nn.Module):\n    def __init__(self, num_classes=100, gamma=5):\n        super(ComplementCrossEntropy, self).__init__()\n        self.gamma = gamma\n        self.cross_entropy = nn.CrossEntropyLoss()\n        self.complement_entropy = ComplementEntropy(num_classes)\n\n    def forward(self, y_hat, y):\n        l1 = self.cross_entropy(y_hat, y)\n        l2 = self.complement_entropy(y_hat, y)\n        return l1 + self.gamma * l2\n\nthank you very much!👍"
  }
}