{
  "id": 258363,
  "title": "40th Place solution: How we improved our rank from 1100th three days ago",
  "content": "<p>First of all <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a> and I would like to start by heartily thanking the following people: <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a>, <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a>, <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>, <a href=\"https://www.kaggle.com/andretugan\" target=\"_blank\">@andretugan</a>, <a href=\"https://www.kaggle.com/jacob34\" target=\"_blank\">@jacob34</a>, <a href=\"https://www.kaggle.com/kurupical\" target=\"_blank\">@kurupical</a>, <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> and <a href=\"https://www.kaggle.com/markwijkhuizen\" target=\"_blank\">@markwijkhuizen</a>. Without their great work and discussion it would not have been possible for us to have made it here. Additionally I would like to  personally thank <a href=\"https://www.kaggle.com/radek1\" target=\"_blank\">@radek1</a> for his wonderful book <strong>Meta learning</strong>. This book inspired me with a lot of ideas in general as well as I used them in this competition. I highly recommend this book to all fellow data scientists. This is my first serious Kaggle competition. I did one for a couple of days five years ago but didn't pursue it. But this time I survived :)  Once again a very big hearty thank you to all of you. I personally had never worked with transformers two months ago. Thanks to this competition I am happy I discovered it. We were at 1100th place three days ago, so we are really happy that we made it to 40th.</p>\n<p>Getting inspired from <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a> and <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a> I decided to develop everything publicly for the first two months of the competition. Later on <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a> and I met exactly one month ago and we formed a team.  </p>\n<p>We understood that the key to succeed in this competition were the following:</p>\n<ol>\n<li>Stabilizing the training of the transformer</li>\n<li>Leveraging massive external data</li>\n<li>A good ensemble of good models</li>\n<li>Definitely not to overfit</li>\n</ol>\n<h3>Stabilizing the training of the transformer</h3>\n<p>Of all these things the most difficult part was stabilizing the training. Our validation graphs looked like seismographs. Here is a snippet of the graph before and after stabilizing.<br>\n<img src=\"https://i.ibb.co/x8q5NGy/image-3.png\" alt=\"\"></p>\n<p>At least with the base model it was ok but with the large model it was just impossible. We also felt very uncomfortable with evaluating every n iterations. Therefore we spent about twenty days focusing  on running experiments to stabilize the training. That's when we came across <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>'s models trained using <strong>differential learning rate</strong>. The first time when we implemented it felt magical. The training was extremely stable, no more seismographs ;) This helped us in avoiding frequent evaluation and also let us comfortably train our models on the full dataset without validation. Yes the idea of training on full data instead of Kfold CV came from <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a>. You can watch the wonderful video posted by <a href=\"https://www.kaggle.com/abhishek\" target=\"_blank\">@abhishek</a> in his youtube channel where 4 grandmasters share their secrets of success</p>\n<h3>Design of work</h3>\n<p>We also realized a good ensemble was key to success and independence is the key to successful ensemble. Therefore we always designed and ran experiments independently and discussed results later on so we don't bias each other as well.  In order to facilitate identical experimental conditions and also not to do double work we created a central repository of all our pipeline components adhering to good coding principles.  </p>\n<h3>Choosing the models and not overfitting</h3>\n<p>As the CV and LB correlation was not great, we had two choices: we could either probe LB and understand more about the test data but we had almost no time/submissions left for that. Our other choice was choosing models not based on their CV scores but by looking at the validation graphs, evaluating them visually if the training and validation loss look stable, and then if the final model was close to the best model (with frequent evaluation) and so on. So this was more of the data scientist instinct that helped us. We never chose a model because the CV score was high.  </p>\n<h3>Model definition</h3>\n<p>The attention head that were used in almost all the public notebook we came across took the pad tokens into account. Therefore we modified it to exclude the pad tokens in the attention calculation. </p>\n<pre><code>class MaskAddedAttentionHead(nn.Module):\n    def __init__(self, input_dim, head_hidden_dim):\n        super(MaskAddedAttentionHead, self).__init__()\n        self.W = nn.Linear(input_dim, head_hidden_dim)\n        self.V = nn.Linear(head_hidden_dim, 1)\n\n    def forward(self, x, attention_mask):\n        attention_scores = self.V(torch.tanh(self.W(x)))\n        attention_scores = attention_scores + attention_mask\n        attention_scores = torch.softmax(attention_scores, dim=1)\n        attentive_x = attention_scores * x\n        attentive_x = attentive_x.sum(axis=1)\n        return attentive_x\n</code></pre>\n<p>Once we stabilized the training, replacing RMSE loss with MSE loss gave us a good boost. We didn't dig deeper into the reason but I guess it had something to do with gradient flow. </p>\n<h3>Leveraging massive external data</h3>\n<p>One of our star differences was the pretraining of our models with the external data. Thanks to <a href=\"https://www.kaggle.com/markwijkhuizen\" target=\"_blank\">@markwijkhuizen</a> we did not have to scrape Wikipedia. We converted the problem into a text ranking problem and trained the model with the ranking loss as the objective. We understood that Bradley Terry scores were essentially computed by comparing pairs of text excerpts therefore we have to do something similar. As many of the text excerpts come from Wikipedia and Simple Wikipedia we trained a ranker as follows: <img src=\"https://i.ibb.co/HNPN1vG/text-comparator.png\" alt=\"\"><br>\nOur initial experiments with pretraining did not give us good results so we dropped it. Only on the last day after running out of ideas we remembered abandoning this and thought why not try it again.  The reason why transfer learning did not work well in the past for us but worked well now was because our transformer became a stable bed now. </p>\n<p>Now when we look back the key to rapid progress in three days comes from the fact that we invested all our effort in preparing a very stable experimental set-up. </p>\n<p>Thank you all for all your valuable discussion in the forums and notebooks. Without great work being made public, we couldn't have done this. I really cannot thank <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a> and <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a> enough. This continues to inspire us to develop more and more publicly. Thank you.</p>\n<p>Here is our code: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit</a></p>",
  "comments": [
    {
      "id": 1441121,
      "author_name": "Chris Deotte",
      "author_url": "",
      "post_date": "2021-08-03T19:40:12.413000",
      "content": "<p>Great solution and great climb to 40th place. Stablizing training was indeed key! </p>\n<p>We also focused on this and plotted val loss curves. Differential learning rates and schedules, freezing backbones, heads with different losses, and adjusting dropout all helped. <a href=\"https://www.kaggle.com/c/commonlitreadabilityprize/discussion/260729\" target=\"_blank\">Here</a> is a plot showing training with and without dropout.</p>",
      "votes": 3,
      "replies": [
        {
          "id": 1445047,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-04T07:41:37.987000",
          "content": "<p>Thank you Chris. We also experimented with dropout and observed similar effect so we also set all the dropouts to 0. We set both the hidden and the attention dropouts to 0.  We didn't find this inmtuitive but nevertheless we couldn't investigate the reason. </p>\n<pre><code>'roberta_hidden_dropout_prob': 0.0,\n'roberta_attention_probs_dropout_prob': 0.0,\n</code></pre>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 1472444,
          "author_name": "Gary Lai",
          "author_url": "",
          "post_date": "2021-08-14T21:40:14.980000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> , what does heads with different losses and freezing backbones mean? Can you link me to resources / explanations please? Thank you so much!</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 1429578,
      "author_name": "Shahules",
      "author_url": "",
      "post_date": "2021-08-03T10:47:39.217000",
      "content": "<p>Great, It was a pleasure working with you <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> . A lot happened during these last 30 days, learned a lot, and got one more good friend through kaggle 💯🎉</p>",
      "votes": 3,
      "replies": [
        {
          "id": 1431532,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-03T12:35:25.593000",
          "content": "<p>It was the same working with you <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a>! I am extremely happy that I got a great friend through Kaggle! I learnt so much from you. Thank you Shahul! </p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1456312,
      "author_name": "Nabeel AlMusawy",
      "author_url": "",
      "post_date": "2021-08-06T21:23:39.357000",
      "content": "<p>Great work!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1455592,
      "author_name": "Gary Lai",
      "author_url": "",
      "post_date": "2021-08-06T16:06:00.787000",
      "content": "<p>Hi Vignesh, thanks so much for this very thoughtful and inspiring post. I have a question about the ranking loss? How exactly does it work? What is the \"comparator\", \"difficulty ranking\" and \"readability ground truth\" (I couldn't seem to find it in your code)?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1464225,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-10T13:50:30.433000",
          "content": "<p>Hi Gary,<br>\nI am very sorry for the late response. I have released a small prototype of the comparator here: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-text-comparator-rmse-vs-ranking-loss\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-text-comparator-rmse-vs-ranking-loss</a></p>\n<p>Essentially <strong>comparator</strong> is a model that takes in a pair of inputs and identifies which one is more difficult to read in comparison to the other. <strong>Readability ground truth</strong> is the target of the text available from the training data. Please go through the notebook and please don't hesitate to write to me if you have follow up questions. Thank you</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1450331,
      "author_name": "Shivu11",
      "author_url": "",
      "post_date": "2021-08-05T04:53:33.743000",
      "content": "<p>If you could only tell about how to survive till the end of the competition ? This is my first competition ,I really want to make it till the end.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1454970,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-06T12:01:48.550000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/shivu11\" target=\"_blank\">@shivu11</a> <br>\nIt was the most difficult part of this competition. I made it very clear to myself it is ok if I don't make progress but its not ok to drop out. Here is a blog that inspired me to keep going: <a href=\"https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/\" target=\"_blank\">https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/</a> . Hope this helps you as well! Good luck with future competitions</p>",
          "votes": 5,
          "replies": []
        }
      ]
    },
    {
      "id": 1448654,
      "author_name": "Amol Ambkar",
      "author_url": "",
      "post_date": "2021-08-04T18:15:27.107000",
      "content": "<p>Great one…</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1441480,
      "author_name": "Shubham Singh",
      "author_url": "",
      "post_date": "2021-08-03T20:26:41.513000",
      "content": "<p>It is a great detailed explanation and thanks for the resources you mentioned . </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1432616,
      "author_name": "over watch",
      "author_url": "",
      "post_date": "2021-08-03T13:26:33.930000",
      "content": "<p>Nice Work, and congrats on your big improvement in the last few days of the competition!</p>\n<p>Quick question about differential learning rate- is it the same as layer-wise learning decay? I also read that you were training on the entire dataset. Can you elaborate on the advantages of doing this compared to k-fold? Thanks a lot!</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1445123,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-04T07:53:33.383000",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/overwatcher\" target=\"_blank\">@overwatcher</a>. Yes its the same. I just noticed that my private score has improved by +0.003 just by training on full dataset. We know this is a great boost in this competition. So all credits goes to <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> </p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1432018,
      "author_name": "Dave E",
      "author_url": "",
      "post_date": "2021-08-03T12:58:18.543000",
      "content": "<p>Thanks for sharing, great stuff, all really clear and logical and sensible. Read your discussion posts <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> and happy to see you were able to achieve a great progression.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1445125,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-04T07:54:01.397000",
          "content": "<p>Thank you <a href=\"https://www.kaggle.com/davidedwards1\" target=\"_blank\">@davidedwards1</a> </p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 1445206,
      "author_name": "jcesquivel",
      "author_url": "",
      "post_date": "2021-08-04T08:07:12.563000",
      "content": "<p>Congratulations <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> for your awesome work. I'm glad to have been helpful.</p>",
      "votes": 2,
      "replies": [
        {
          "id": 1449049,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-04T19:44:12.833000",
          "content": "<p>Thank you very much <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a> </p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 1443151,
      "author_name": "Anshu Kumar Singh",
      "author_url": "",
      "post_date": "2021-08-04T01:55:46.403000",
      "content": "<p>Thank you for this nice explanation. Very much informative</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 1464738,
      "author_name": "DIVYA MAHESHWARI1101",
      "author_url": "",
      "post_date": "2021-08-10T17:25:41.277000",
      "content": "<p>Really Nice work!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1443522,
      "author_name": "spy1234567",
      "author_url": "",
      "post_date": "2021-08-04T03:16:05.290000",
      "content": "<p>Hi, Baskaran, Congrats!<br>\nCould you share from with notebook you have learned the differential learning rate? Thank you!</p>",
      "votes": 0,
      "replies": [
        {
          "id": 1443790,
          "author_name": "Saiyan Warrior",
          "author_url": "",
          "post_date": "2021-08-04T04:10:15.867000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/spy1234567\" target=\"_blank\">@spy1234567</a> this is how I used differential learning rate<br>\n<a href=\"https://www.kaggle.com/andretugan/pre-trained-roberta-solution-in-pytorch?scriptVersionId=67087445&amp;cellId=14\" target=\"_blank\">https://www.kaggle.com/andretugan/pre-trained-roberta-solution-in-pytorch?scriptVersionId=67087445&amp;cellId=14</a><br>\nHope this help😊</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 1445105,
          "author_name": "Vignesh Baskaran",
          "author_url": "",
          "post_date": "2021-08-04T07:51:08.760000",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/spy1234567\" target=\"_blank\">@spy1234567</a><br>\nWe learnt about this technique from <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>'s discussion post and we implemented it ourselves. You may find our code here: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit</a></p>\n<p>Under the function <code>get_optimizer_parameters</code> with <code>group_mode</code>=<code>be_wd</code> you may find our implementation.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 1446457,
          "author_name": "spy1234567",
          "author_url": "",
          "post_date": "2021-08-04T12:19:04.113000",
          "content": "<p>Hi, <a href=\"https://www.kaggle.com/saiyanwarrior\" target=\"_blank\">@saiyanwarrior</a> and <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> , thanks a lot for your kind help!</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1440356,
      "author_name": "HRUSHIKESH SHELAR",
      "author_url": "",
      "post_date": "2021-08-03T18:11:29.363000",
      "content": "<p>Nice work!!!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1447289,
      "author_name": "ABDELAZIZ Korba",
      "author_url": "",
      "post_date": "2021-08-04T14:36:01.587000",
      "content": "<p>Thank you for this nice explanation.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1455418,
      "author_name": "Shivu11",
      "author_url": "",
      "post_date": "2021-08-06T15:02:20.167000",
      "content": "<p>Thank you so much <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> </p>",
      "votes": 0,
      "replies": []
    }
  ],
  "comment_count": 27,
  "messages": [
    {
      "id": 1428215,
      "postDate": "2021-08-03T09:13:57.417Z",
      "content": "<p>First of all <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a> and I would like to start by heartily thanking the following people: <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a>, <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a>, <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>, <a href=\"https://www.kaggle.com/andretugan\" target=\"_blank\">@andretugan</a>, <a href=\"https://www.kaggle.com/jacob34\" target=\"_blank\">@jacob34</a>, <a href=\"https://www.kaggle.com/kurupical\" target=\"_blank\">@kurupical</a>, <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> and <a href=\"https://www.kaggle.com/markwijkhuizen\" target=\"_blank\">@markwijkhuizen</a>. Without their great work and discussion it would not have been possible for us to have made it here. Additionally I would like to  personally thank <a href=\"https://www.kaggle.com/radek1\" target=\"_blank\">@radek1</a> for his wonderful book <strong>Meta learning</strong>. This book inspired me with a lot of ideas in general as well as I used them in this competition. I highly recommend this book to all fellow data scientists. This is my first serious Kaggle competition. I did one for a couple of days five years ago but didn't pursue it. But this time I survived :)  Once again a very big hearty thank you to all of you. I personally had never worked with transformers two months ago. Thanks to this competition I am happy I discovered it. We were at 1100th place three days ago, so we are really happy that we made it to 40th.</p>\n<p>Getting inspired from <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a> and <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a> I decided to develop everything publicly for the first two months of the competition. Later on <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a> and I met exactly one month ago and we formed a team.  </p>\n<p>We understood that the key to succeed in this competition were the following:</p>\n<ol>\n<li>Stabilizing the training of the transformer</li>\n<li>Leveraging massive external data</li>\n<li>A good ensemble of good models</li>\n<li>Definitely not to overfit</li>\n</ol>\n<h3>Stabilizing the training of the transformer</h3>\n<p>Of all these things the most difficult part was stabilizing the training. Our validation graphs looked like seismographs. Here is a snippet of the graph before and after stabilizing.<br>\n<img src=\"https://i.ibb.co/x8q5NGy/image-3.png\" alt=\"\"></p>\n<p>At least with the base model it was ok but with the large model it was just impossible. We also felt very uncomfortable with evaluating every n iterations. Therefore we spent about twenty days focusing  on running experiments to stabilize the training. That's when we came across <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>'s models trained using <strong>differential learning rate</strong>. The first time when we implemented it felt magical. The training was extremely stable, no more seismographs ;) This helped us in avoiding frequent evaluation and also let us comfortably train our models on the full dataset without validation. Yes the idea of training on full data instead of Kfold CV came from <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a>. You can watch the wonderful video posted by <a href=\"https://www.kaggle.com/abhishek\" target=\"_blank\">@abhishek</a> in his youtube channel where 4 grandmasters share their secrets of success</p>\n<h3>Design of work</h3>\n<p>We also realized a good ensemble was key to success and independence is the key to successful ensemble. Therefore we always designed and ran experiments independently and discussed results later on so we don't bias each other as well.  In order to facilitate identical experimental conditions and also not to do double work we created a central repository of all our pipeline components adhering to good coding principles.  </p>\n<h3>Choosing the models and not overfitting</h3>\n<p>As the CV and LB correlation was not great, we had two choices: we could either probe LB and understand more about the test data but we had almost no time/submissions left for that. Our other choice was choosing models not based on their CV scores but by looking at the validation graphs, evaluating them visually if the training and validation loss look stable, and then if the final model was close to the best model (with frequent evaluation) and so on. So this was more of the data scientist instinct that helped us. We never chose a model because the CV score was high.  </p>\n<h3>Model definition</h3>\n<p>The attention head that were used in almost all the public notebook we came across took the pad tokens into account. Therefore we modified it to exclude the pad tokens in the attention calculation. </p>\n<pre><code>class MaskAddedAttentionHead(nn.Module):\n    def __init__(self, input_dim, head_hidden_dim):\n        super(MaskAddedAttentionHead, self).__init__()\n        self.W = nn.Linear(input_dim, head_hidden_dim)\n        self.V = nn.Linear(head_hidden_dim, 1)\n\n    def forward(self, x, attention_mask):\n        attention_scores = self.V(torch.tanh(self.W(x)))\n        attention_scores = attention_scores + attention_mask\n        attention_scores = torch.softmax(attention_scores, dim=1)\n        attentive_x = attention_scores * x\n        attentive_x = attentive_x.sum(axis=1)\n        return attentive_x\n</code></pre>\n<p>Once we stabilized the training, replacing RMSE loss with MSE loss gave us a good boost. We didn't dig deeper into the reason but I guess it had something to do with gradient flow. </p>\n<h3>Leveraging massive external data</h3>\n<p>One of our star differences was the pretraining of our models with the external data. Thanks to <a href=\"https://www.kaggle.com/markwijkhuizen\" target=\"_blank\">@markwijkhuizen</a> we did not have to scrape Wikipedia. We converted the problem into a text ranking problem and trained the model with the ranking loss as the objective. We understood that Bradley Terry scores were essentially computed by comparing pairs of text excerpts therefore we have to do something similar. As many of the text excerpts come from Wikipedia and Simple Wikipedia we trained a ranker as follows: <img src=\"https://i.ibb.co/HNPN1vG/text-comparator.png\" alt=\"\"><br>\nOur initial experiments with pretraining did not give us good results so we dropped it. Only on the last day after running out of ideas we remembered abandoning this and thought why not try it again.  The reason why transfer learning did not work well in the past for us but worked well now was because our transformer became a stable bed now. </p>\n<p>Now when we look back the key to rapid progress in three days comes from the fact that we invested all our effort in preparing a very stable experimental set-up. </p>\n<p>Thank you all for all your valuable discussion in the forums and notebooks. Without great work being made public, we couldn't have done this. I really cannot thank <a href=\"https://www.kaggle.com/maunish\" target=\"_blank\">@maunish</a> and <a href=\"https://www.kaggle.com/rhtsingh\" target=\"_blank\">@rhtsingh</a> enough. This continues to inspire us to develop more and more publicly. Thank you.</p>\n<p>Here is our code: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit</a></p>",
      "rawMarkdown": "First of all @shahules and I would like to start by heartily thanking the following people: @rhtsingh, @maunish, @jcesquiveld, @andretugan, @jacob34, @kurupical, @cdeotte and @markwijkhuizen. Without their great work and discussion it would not have been possible for us to have made it here. Additionally I would like to  personally thank @radek1 for his wonderful book **Meta learning**. This book inspired me with a lot of ideas in general as well as I used them in this competition. I highly recommend this book to all fellow data scientists. This is my first serious Kaggle competition. I did one for a couple of days five years ago but didn't pursue it. But this time I survived :)  Once again a very big hearty thank you to all of you. I personally had never worked with transformers two months ago. Thanks to this competition I am happy I discovered it. We were at 1100th place three days ago, so we are really happy that we made it to 40th.\n\nGetting inspired from @rhtsingh and @maunish I decided to develop everything publicly for the first two months of the competition. Later on @shahules and I met exactly one month ago and we formed a team.  \n\nWe understood that the key to succeed in this competition were the following:\n1. Stabilizing the training of the transformer\n2. Leveraging massive external data\n3. A good ensemble of good models\n4. Definitely not to overfit\n\n### Stabilizing the training of the transformer\nOf all these things the most difficult part was stabilizing the training. Our validation graphs looked like seismographs. Here is a snippet of the graph before and after stabilizing.\n![](https://i.ibb.co/x8q5NGy/image-3.png)\n\nAt least with the base model it was ok but with the large model it was just impossible. We also felt very uncomfortable with evaluating every n iterations. Therefore we spent about twenty days focusing  on running experiments to stabilize the training. That's when we came across @jcesquiveld's models trained using **differential learning rate**. The first time when we implemented it felt magical. The training was extremely stable, no more seismographs ;) This helped us in avoiding frequent evaluation and also let us comfortably train our models on the full dataset without validation. Yes the idea of training on full data instead of Kfold CV came from @cdeotte. You can watch the wonderful video posted by @abhishek in his youtube channel where 4 grandmasters share their secrets of success\n\n\n### Design of work\nWe also realized a good ensemble was key to success and independence is the key to successful ensemble. Therefore we always designed and ran experiments independently and discussed results later on so we don't bias each other as well.  In order to facilitate identical experimental conditions and also not to do double work we created a central repository of all our pipeline components adhering to good coding principles.  \n\n### Choosing the models and not overfitting\n As the CV and LB correlation was not great, we had two choices: we could either probe LB and understand more about the test data but we had almost no time/submissions left for that. Our other choice was choosing models not based on their CV scores but by looking at the validation graphs, evaluating them visually if the training and validation loss look stable, and then if the final model was close to the best model (with frequent evaluation) and so on. So this was more of the data scientist instinct that helped us. We never chose a model because the CV score was high.  \n\n### Model definition\nThe attention head that were used in almost all the public notebook we came across took the pad tokens into account. Therefore we modified it to exclude the pad tokens in the attention calculation. \n\n``` python\nclass MaskAddedAttentionHead(nn.Module):\n    def __init__(self, input_dim, head_hidden_dim):\n        super(MaskAddedAttentionHead, self).__init__()\n        self.W = nn.Linear(input_dim, head_hidden_dim)\n        self.V = nn.Linear(head_hidden_dim, 1)\n        \n    def forward(self, x, attention_mask):\n        attention_scores = self.V(torch.tanh(self.W(x)))\n        attention_scores = attention_scores + attention_mask\n        attention_scores = torch.softmax(attention_scores, dim=1)\n        attentive_x = attention_scores * x\n        attentive_x = attentive_x.sum(axis=1)\n        return attentive_x\n```\n\nOnce we stabilized the training, replacing RMSE loss with MSE loss gave us a good boost. We didn't dig deeper into the reason but I guess it had something to do with gradient flow. \n\n### Leveraging massive external data\nOne of our star differences was the pretraining of our models with the external data. Thanks to @markwijkhuizen we did not have to scrape Wikipedia. We converted the problem into a text ranking problem and trained the model with the ranking loss as the objective. We understood that Bradley Terry scores were essentially computed by comparing pairs of text excerpts therefore we have to do something similar. As many of the text excerpts come from Wikipedia and Simple Wikipedia we trained a ranker as follows: ![](https://i.ibb.co/HNPN1vG/text-comparator.png)\nOur initial experiments with pretraining did not give us good results so we dropped it. Only on the last day after running out of ideas we remembered abandoning this and thought why not try it again.  The reason why transfer learning did not work well in the past for us but worked well now was because our transformer became a stable bed now. \n\nNow when we look back the key to rapid progress in three days comes from the fact that we invested all our effort in preparing a very stable experimental set-up. \n\nThank you all for all your valuable discussion in the forums and notebooks. Without great work being made public, we couldn't have done this. I really cannot thank @maunish and @rhtsingh enough. This continues to inspire us to develop more and more publicly. Thank you.\n\nHere is our code: https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit",
      "votes": 113
    },
    {
      "id": 1441121,
      "postDate": "2021-08-03T19:40:12.413Z",
      "content": "<p>Great solution and great climb to 40th place. Stablizing training was indeed key! </p>\n<p>We also focused on this and plotted val loss curves. Differential learning rates and schedules, freezing backbones, heads with different losses, and adjusting dropout all helped. <a href=\"https://www.kaggle.com/c/commonlitreadabilityprize/discussion/260729\" target=\"_blank\">Here</a> is a plot showing training with and without dropout.</p>",
      "rawMarkdown": "Great solution and great climb to 40th place. Stablizing training was indeed key! \n\nWe also focused on this and plotted val loss curves. Differential learning rates and schedules, freezing backbones, heads with different losses, and adjusting dropout all helped. [Here][1] is a plot showing training with and without dropout.\n\n[1]: https://www.kaggle.com/c/commonlitreadabilityprize/discussion/260729",
      "votes": 3,
      "replies": [
        {
          "id": 1445047,
          "postDate": "2021-08-04T07:41:37.987Z",
          "content": "<p>Thank you Chris. We also experimented with dropout and observed similar effect so we also set all the dropouts to 0. We set both the hidden and the attention dropouts to 0.  We didn't find this inmtuitive but nevertheless we couldn't investigate the reason. </p>\n<pre><code>'roberta_hidden_dropout_prob': 0.0,\n'roberta_attention_probs_dropout_prob': 0.0,\n</code></pre>",
          "rawMarkdown": "Thank you Chris. We also experimented with dropout and observed similar effect so we also set all the dropouts to 0. We set both the hidden and the attention dropouts to 0.  We didn't find this inmtuitive but nevertheless we couldn't investigate the reason. \n``` python\n'roberta_hidden_dropout_prob': 0.0,\n'roberta_attention_probs_dropout_prob': 0.0,\n```\n",
          "votes": 2
        },
        {
          "id": 1472444,
          "postDate": "2021-08-14T21:40:14.980Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> , what does heads with different losses and freezing backbones mean? Can you link me to resources / explanations please? Thank you so much!</p>",
          "rawMarkdown": "Hi @cdeotte , what does heads with different losses and freezing backbones mean? Can you link me to resources / explanations please? Thank you so much!"
        }
      ]
    },
    {
      "id": 1429578,
      "postDate": "2021-08-03T10:47:39.217Z",
      "content": "<p>Great, It was a pleasure working with you <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> . A lot happened during these last 30 days, learned a lot, and got one more good friend through kaggle 💯🎉</p>",
      "rawMarkdown": "Great, It was a pleasure working with you @vigneshbaskaran . A lot happened during these last 30 days, learned a lot, and got one more good friend through kaggle 💯🎉",
      "votes": 3,
      "replies": [
        {
          "id": 1431532,
          "postDate": "2021-08-03T12:35:25.593Z",
          "content": "<p>It was the same working with you <a href=\"https://www.kaggle.com/shahules\" target=\"_blank\">@shahules</a>! I am extremely happy that I got a great friend through Kaggle! I learnt so much from you. Thank you Shahul! </p>",
          "rawMarkdown": "It was the same working with you @shahules! I am extremely happy that I got a great friend through Kaggle! I learnt so much from you. Thank you Shahul! ",
          "votes": 1
        }
      ]
    },
    {
      "id": 1456312,
      "postDate": "2021-08-06T21:23:39.357Z",
      "content": "<p>Great work!</p>",
      "rawMarkdown": "Great work!",
      "votes": 1
    },
    {
      "id": 1455592,
      "postDate": "2021-08-06T16:06:00.787Z",
      "content": "<p>Hi Vignesh, thanks so much for this very thoughtful and inspiring post. I have a question about the ranking loss? How exactly does it work? What is the \"comparator\", \"difficulty ranking\" and \"readability ground truth\" (I couldn't seem to find it in your code)?</p>",
      "rawMarkdown": "Hi Vignesh, thanks so much for this very thoughtful and inspiring post. I have a question about the ranking loss? How exactly does it work? What is the \"comparator\", \"difficulty ranking\" and \"readability ground truth\" (I couldn't seem to find it in your code)?",
      "votes": 1,
      "replies": [
        {
          "id": 1464225,
          "postDate": "2021-08-10T13:50:30.433Z",
          "content": "<p>Hi Gary,<br>\nI am very sorry for the late response. I have released a small prototype of the comparator here: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-text-comparator-rmse-vs-ranking-loss\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-text-comparator-rmse-vs-ranking-loss</a></p>\n<p>Essentially <strong>comparator</strong> is a model that takes in a pair of inputs and identifies which one is more difficult to read in comparison to the other. <strong>Readability ground truth</strong> is the target of the text available from the training data. Please go through the notebook and please don't hesitate to write to me if you have follow up questions. Thank you</p>",
          "rawMarkdown": "Hi Gary,\nI am very sorry for the late response. I have released a small prototype of the comparator here: https://www.kaggle.com/vigneshbaskaran/commonlit-text-comparator-rmse-vs-ranking-loss\n\nEssentially **comparator** is a model that takes in a pair of inputs and identifies which one is more difficult to read in comparison to the other. **Readability ground truth** is the target of the text available from the training data. Please go through the notebook and please don't hesitate to write to me if you have follow up questions. Thank you",
          "votes": 1
        }
      ]
    },
    {
      "id": 1450331,
      "postDate": "2021-08-05T04:53:33.743Z",
      "content": "<p>If you could only tell about how to survive till the end of the competition ? This is my first competition ,I really want to make it till the end.</p>",
      "rawMarkdown": "If you could only tell about how to survive till the end of the competition ? This is my first competition ,I really want to make it till the end.",
      "votes": 1,
      "replies": [
        {
          "id": 1454970,
          "postDate": "2021-08-06T12:01:48.550Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/shivu11\" target=\"_blank\">@shivu11</a> <br>\nIt was the most difficult part of this competition. I made it very clear to myself it is ok if I don't make progress but its not ok to drop out. Here is a blog that inspired me to keep going: <a href=\"https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/\" target=\"_blank\">https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/</a> . Hope this helps you as well! Good luck with future competitions</p>",
          "rawMarkdown": "Hi @shivu11 \nIt was the most difficult part of this competition. I made it very clear to myself it is ok if I don't make progress but its not ok to drop out. Here is a blog that inspired me to keep going: https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/ . Hope this helps you as well! Good luck with future competitions",
          "votes": 5
        }
      ]
    },
    {
      "id": 1448654,
      "postDate": "2021-08-04T18:15:27.107Z",
      "content": "<p>Great one…</p>",
      "rawMarkdown": "Great one...",
      "votes": 1
    },
    {
      "id": 1441480,
      "postDate": "2021-08-03T20:26:41.513Z",
      "content": "<p>It is a great detailed explanation and thanks for the resources you mentioned . </p>",
      "rawMarkdown": "It is a great detailed explanation and thanks for the resources you mentioned . ",
      "votes": 1
    },
    {
      "id": 1432616,
      "postDate": "2021-08-03T13:26:33.930Z",
      "content": "<p>Nice Work, and congrats on your big improvement in the last few days of the competition!</p>\n<p>Quick question about differential learning rate- is it the same as layer-wise learning decay? I also read that you were training on the entire dataset. Can you elaborate on the advantages of doing this compared to k-fold? Thanks a lot!</p>",
      "rawMarkdown": "Nice Work, and congrats on your big improvement in the last few days of the competition!\n\nQuick question about differential learning rate- is it the same as layer-wise learning decay? I also read that you were training on the entire dataset. Can you elaborate on the advantages of doing this compared to k-fold? Thanks a lot!",
      "votes": 1,
      "replies": [
        {
          "id": 1445123,
          "postDate": "2021-08-04T07:53:33.383Z",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/overwatcher\" target=\"_blank\">@overwatcher</a>. Yes its the same. I just noticed that my private score has improved by +0.003 just by training on full dataset. We know this is a great boost in this competition. So all credits goes to <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> </p>",
          "rawMarkdown": "Thanks @overwatcher. Yes its the same. I just noticed that my private score has improved by +0.003 just by training on full dataset. We know this is a great boost in this competition. So all credits goes to @cdeotte ",
          "votes": 1
        }
      ]
    },
    {
      "id": 1432018,
      "postDate": "2021-08-03T12:58:18.543Z",
      "content": "<p>Thanks for sharing, great stuff, all really clear and logical and sensible. Read your discussion posts <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> and happy to see you were able to achieve a great progression.</p>",
      "rawMarkdown": "Thanks for sharing, great stuff, all really clear and logical and sensible. Read your discussion posts @vigneshbaskaran and happy to see you were able to achieve a great progression.",
      "votes": 1,
      "replies": [
        {
          "id": 1445125,
          "postDate": "2021-08-04T07:54:01.397Z",
          "content": "<p>Thank you <a href=\"https://www.kaggle.com/davidedwards1\" target=\"_blank\">@davidedwards1</a> </p>",
          "rawMarkdown": "Thank you @davidedwards1 "
        }
      ]
    },
    {
      "id": 1445206,
      "postDate": "2021-08-04T08:07:12.563Z",
      "content": "<p>Congratulations <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> for your awesome work. I'm glad to have been helpful.</p>",
      "rawMarkdown": "Congratulations [@vigneshbaskaran](https://www.kaggle.com/vigneshbaskaran) for your awesome work. I'm glad to have been helpful.",
      "votes": 2,
      "replies": [
        {
          "id": 1449049,
          "postDate": "2021-08-04T19:44:12.833Z",
          "content": "<p>Thank you very much <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a> </p>",
          "rawMarkdown": "Thank you very much @jcesquiveld "
        }
      ]
    },
    {
      "id": 1443151,
      "postDate": "2021-08-04T01:55:46.403Z",
      "content": "<p>Thank you for this nice explanation. Very much informative</p>",
      "rawMarkdown": "Thank you for this nice explanation. Very much informative",
      "votes": 2
    },
    {
      "id": 1464738,
      "postDate": "2021-08-10T17:25:41.277Z",
      "content": "<p>Really Nice work!</p>",
      "rawMarkdown": "Really Nice work!"
    },
    {
      "id": 1443522,
      "postDate": "2021-08-04T03:16:05.290Z",
      "content": "<p>Hi, Baskaran, Congrats!<br>\nCould you share from with notebook you have learned the differential learning rate? Thank you!</p>",
      "rawMarkdown": "Hi, Baskaran, Congrats!\nCould you share from with notebook you have learned the differential learning rate? Thank you!",
      "replies": [
        {
          "id": 1443790,
          "postDate": "2021-08-04T04:10:15.867Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/spy1234567\" target=\"_blank\">@spy1234567</a> this is how I used differential learning rate<br>\n<a href=\"https://www.kaggle.com/andretugan/pre-trained-roberta-solution-in-pytorch?scriptVersionId=67087445&amp;cellId=14\" target=\"_blank\">https://www.kaggle.com/andretugan/pre-trained-roberta-solution-in-pytorch?scriptVersionId=67087445&amp;cellId=14</a><br>\nHope this help😊</p>",
          "rawMarkdown": "Hi @spy1234567 this is how I used differential learning rate\nhttps://www.kaggle.com/andretugan/pre-trained-roberta-solution-in-pytorch?scriptVersionId=67087445&cellId=14\nHope this help😊"
        },
        {
          "id": 1445105,
          "postDate": "2021-08-04T07:51:08.760Z",
          "content": "<p>Hi <a href=\"https://www.kaggle.com/spy1234567\" target=\"_blank\">@spy1234567</a><br>\nWe learnt about this technique from <a href=\"https://www.kaggle.com/jcesquiveld\" target=\"_blank\">@jcesquiveld</a>'s discussion post and we implemented it ourselves. You may find our code here: <a href=\"https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit\" target=\"_blank\">https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit</a></p>\n<p>Under the function <code>get_optimizer_parameters</code> with <code>group_mode</code>=<code>be_wd</code> you may find our implementation.</p>",
          "rawMarkdown": "Hi @spy1234567\nWe learnt about this technique from @jcesquiveld's discussion post and we implemented it ourselves. You may find our code here: https://www.kaggle.com/vigneshbaskaran/commonlit-nn-kit\n\nUnder the function `get_optimizer_parameters` with `group_mode`=`be_wd` you may find our implementation.",
          "votes": 1
        },
        {
          "id": 1446457,
          "postDate": "2021-08-04T12:19:04.113Z",
          "content": "<p>Hi, <a href=\"https://www.kaggle.com/saiyanwarrior\" target=\"_blank\">@saiyanwarrior</a> and <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> , thanks a lot for your kind help!</p>",
          "rawMarkdown": "Hi, @saiyanwarrior and @vigneshbaskaran , thanks a lot for your kind help!",
          "votes": 1
        }
      ]
    },
    {
      "id": 1440356,
      "postDate": "2021-08-03T18:11:29.363Z",
      "content": "<p>Nice work!!!</p>",
      "rawMarkdown": "Nice work!!!"
    },
    {
      "id": 1447289,
      "postDate": "2021-08-04T14:36:01.587Z",
      "content": "<p>Thank you for this nice explanation.</p>",
      "rawMarkdown": "Thank you for this nice explanation.",
      "votes": 1
    },
    {
      "id": 1455418,
      "postDate": "2021-08-06T15:02:20.167Z",
      "content": "<p>Thank you so much <a href=\"https://www.kaggle.com/vigneshbaskaran\" target=\"_blank\">@vigneshbaskaran</a> </p>",
      "rawMarkdown": "Thank you so much @vigneshbaskaran "
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-19T23:47:04Z",
  "competition_id": 25914,
  "competition_slug": "commonlitreadabilityprize",
  "team_id": 6760665,
  "solution_url": "/competitions/commonlitreadabilityprize/writeups/southies-40th-place-solution-how-we-improved-our-r"
}