{
  "id": 344565,
  "title": "About the normalization of comp metric",
  "url": "/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/344565",
  "author_name": "",
  "post_date": "2022-08-15T16:43:59.680614200Z",
  "votes": 15,
  "comment_count": 5,
  "views": 0,
  "content": "<p>I think the Competition metric needs to be normalised by weights. Is it correct to first divide each row by each weight and then average the loss?</p>\n<p></p>\n<p>Above is my mistake…. I am really embarassed….<br>\nThank you, <a href=\"https://www.kaggle.com/harshitsheoran\" target=\"_blank\">@harshitsheoran</a>!<br>\nNow I can calculate the right competition loss!</p>\n<pre><code>def competiton_loss_row_norm(y_hat, y):\n    loss = loss_fn(y_hat, y)\n    weights = y * competition_weights['+'] + (1 - y) * competition_weights['-']\n    loss = (loss * weights).sum(axis=1)\n    w_sum = weights.sum(axis=1)\n    loss = torch.div(loss, w_sum)\n    return loss.mean()\n</code></pre>\n<p>notebook here. I updated ver 4.<br>\n<a href=\"https://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data\" target=\"_blank\">https://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data</a></p>",
  "messages": [
    {
      "id": "1900018",
      "postDate": "08/15/2022 16:43:59",
      "content": "<p>I think the Competition metric needs to be normalised by weights. Is it correct to first divide each row by each weight and then average the loss?</p>\n<p></p>\n<p>Above is my mistake…. I am really embarassed….<br>\nThank you, <a href=\"https://www.kaggle.com/harshitsheoran\" target=\"_blank\">@harshitsheoran</a>!<br>\nNow I can calculate the right competition loss!</p>\n<pre><code>def competiton_loss_row_norm(y_hat, y):\n    loss = loss_fn(y_hat, y)\n    weights = y * competition_weights['+'] + (1 - y) * competition_weights['-']\n    loss = (loss * weights).sum(axis=1)\n    w_sum = weights.sum(axis=1)\n    loss = torch.div(loss, w_sum)\n    return loss.mean()\n</code></pre>\n<p>notebook here. I updated ver 4.<br>\n<a href=\"https://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data\" target=\"_blank\">https://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data</a></p>",
      "rawMarkdown": "I think the Competition metric needs to be normalised by weights. Is it correct to first divide each row by each weight and then average the loss?\n\n~~If this is the case, then using mean prediction, the loss in train data would be around 0.7. If only data with a patient_overall of 1 were used, the loss would be approximately 0.57. This is consistent with the public LB score of the mean preds. ~~\n\nAbove is my mistake.... I am really embarassed....\nThank you, @harshitsheoran!\nNow I can calculate the right competition loss!\n\n```\ndef competiton_loss_row_norm(y_hat, y):\n    loss = loss_fn(y_hat, y)\n    weights = y * competition_weights['+'] + (1 - y) * competition_weights['-']\n    loss = (loss * weights).sum(axis=1)\n    w_sum = weights.sum(axis=1)\n    loss = torch.div(loss, w_sum)\n    return loss.mean()\n```\n\nnotebook here. I updated ver 4.\nhttps://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data",
      "votes": null
    },
    {
      "id": "1900026",
      "postDate": "08/15/2022 16:49:41",
      "content": "<p>Just 1 small/tiny/petite problem which is causing all your loss calculations to go haywire is you are using BCEWithLogitsLoss instead of BCELoss, rest you are wise enough.</p>",
      "rawMarkdown": "Just 1 small/tiny/petite problem which is causing all your loss calculations to go haywire is you are using BCEWithLogitsLoss instead of BCELoss, rest you are wise enough.",
      "votes": null
    },
    {
      "id": "1900045",
      "postDate": "08/15/2022 17:03:57",
      "content": "<p>It's true! I'm so embarrassed!</p>\n<p>I thought it was quirky and weird, but now the value fit perfectly, thank you!</p>",
      "rawMarkdown": "It's true! I'm so embarrassed!\n\nI thought it was quirky and weird, but now the value fit perfectly, thank you!",
      "votes": null
    },
    {
      "id": "1900205",
      "postDate": "08/15/2022 19:26:36",
      "content": "<p>Thanks a lot for full code and discussion, I was also struggling to replicate metric😅</p>",
      "rawMarkdown": "Thanks a lot for full code and discussion, I was also struggling to replicate metric😅",
      "votes": null
    },
    {
      "id": "1900241",
      "postDate": "08/15/2022 20:28:00",
      "content": "<p>I see that in the notebook, your version of competition loss from a discussion is too small, I personally wrote that normalization line, and I am using that in my pipeline, the intended way to use that line is 1 patient at a time, so doing something like this<br>\n<code>print(np.mean([competiton_loss(mean_values[i:i+1], labels[i:i+1].double()) for i in range(len(mean_values))]))</code> would give a perfect score.</p>",
      "rawMarkdown": "I see that in the notebook, your version of competition loss from a discussion is too small, I personally wrote that normalization line, and I am using that in my pipeline, the intended way to use that line is 1 patient at a time, so doing something like this\n`print(np.mean([competiton_loss(mean_values[i:i+1], labels[i:i+1].double()) for i in range(len(mean_values))]))` would give a perfect score.",
      "votes": null
    },
    {
      "id": "1900361",
      "postDate": "08/16/2022 00:18:49",
      "content": "<p>You need to be careful to understand the difference between a loss per batch and a loss for an epoch.  Most frameworks assume that the losses for each batch are averaged to get the epoch loss, but that would be incorrect for this competition.  That is because the samples are weighted by positive/negative and there may be different numbers of positive and negative samples in each batch</p>",
      "rawMarkdown": "You need to be careful to understand the difference between a loss per batch and a loss for an epoch.  Most frameworks assume that the losses for each batch are averaged to get the epoch loss, but that would be incorrect for this competition.  That is because the samples are weighted by positive/negative and there may be different numbers of positive and negative samples in each batch",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1900026,
      "author_name": "harshitsheoran",
      "author_url": "",
      "post_date": "08/15/2022 16:49:41",
      "content": "<p>Just 1 small/tiny/petite problem which is causing all your loss calculations to go haywire is you are using BCEWithLogitsLoss instead of BCELoss, rest you are wise enough.</p>",
      "votes": null,
      "replies": [
        {
          "id": 1900045,
          "author_name": "yosukeyama",
          "author_url": "",
          "post_date": "08/15/2022 17:03:57",
          "content": "<p>It's true! I'm so embarrassed!</p>\n<p>I thought it was quirky and weird, but now the value fit perfectly, thank you!</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1900205,
      "author_name": "olegsidorshin",
      "author_url": "",
      "post_date": "08/15/2022 19:26:36",
      "content": "<p>Thanks a lot for full code and discussion, I was also struggling to replicate metric😅</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 1900241,
      "author_name": "harshitsheoran",
      "author_url": "",
      "post_date": "08/15/2022 20:28:00",
      "content": "<p>I see that in the notebook, your version of competition loss from a discussion is too small, I personally wrote that normalization line, and I am using that in my pipeline, the intended way to use that line is 1 patient at a time, so doing something like this<br>\n<code>print(np.mean([competiton_loss(mean_values[i:i+1], labels[i:i+1].double()) for i in range(len(mean_values))]))</code> would give a perfect score.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 1900361,
      "author_name": "solverworld",
      "author_url": "",
      "post_date": "08/16/2022 00:18:49",
      "content": "<p>You need to be careful to understand the difference between a loss per batch and a loss for an epoch.  Most frameworks assume that the losses for each batch are averaged to get the epoch loss, but that would be incorrect for this competition.  That is because the samples are weighted by positive/negative and there may be different numbers of positive and negative samples in each batch</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1900018": "I think the Competition metric needs to be normalised by weights. Is it correct to first divide each row by each weight and then average the loss?\n\n~~If this is the case, then using mean prediction, the loss in train data would be around 0.7. If only data with a patient_overall of 1 were used, the loss would be approximately 0.57. This is consistent with the public LB score of the mean preds. ~~\n\nAbove is my mistake.... I am really embarassed....\nThank you, @harshitsheoran!\nNow I can calculate the right competition loss!\n\n```\ndef competiton_loss_row_norm(y_hat, y):\n    loss = loss_fn(y_hat, y)\n    weights = y * competition_weights['+'] + (1 - y) * competition_weights['-']\n    loss = (loss * weights).sum(axis=1)\n    w_sum = weights.sum(axis=1)\n    loss = torch.div(loss, w_sum)\n    return loss.mean()\n```\n\nnotebook here. I updated ver 4.\nhttps://www.kaggle.com/code/yosukeyama/comp-metric-findings-about-test-data",
    "1900026": "Just 1 small/tiny/petite problem which is causing all your loss calculations to go haywire is you are using BCEWithLogitsLoss instead of BCELoss, rest you are wise enough.",
    "1900045": "It's true! I'm so embarrassed!\n\nI thought it was quirky and weird, but now the value fit perfectly, thank you!",
    "1900205": "Thanks a lot for full code and discussion, I was also struggling to replicate metric😅",
    "1900241": "I see that in the notebook, your version of competition loss from a discussion is too small, I personally wrote that normalization line, and I am using that in my pipeline, the intended way to use that line is 1 patient at a time, so doing something like this\n`print(np.mean([competiton_loss(mean_values[i:i+1], labels[i:i+1].double()) for i in range(len(mean_values))]))` would give a perfect score.",
    "1900361": "You need to be careful to understand the difference between a loss per batch and a loss for an epoch.  Most frameworks assume that the losses for each batch are averaged to get the epoch loss, but that would be incorrect for this competition.  That is because the samples are weighted by positive/negative and there may be different numbers of positive and negative samples in each batch"
  },
  "source": "meta"
}