{
  "id": 343714,
  "title": "15th Segment Ranking",
  "url": "/competitions/AI4Code/discussion/343714",
  "author_name": "Chenglu",
  "post_date": "2022-08-12T08:17:30.635000",
  "votes": 52,
  "comment_count": 23,
  "views": 0,
  "content": "<h1>Segment Ranking(9th on LB)</h1>\n<p>Thank Kaggle for hosting this game, and the community for all the sharing. It's my first NLP competition so there are not much NLP-related sharing in my solution, just task-related tricks.</p>\n<p>Source code: <a href=\"https://github.com/louis-she/ai4code\" target=\"_blank\">https://github.com/louis-she/ai4code</a></p>\n<p>Inference Notebook: <a href=\"https://www.kaggle.com/code/snaker/new-rank/notebook\" target=\"_blank\">https://www.kaggle.com/code/snaker/new-rank/notebook</a></p>\n<h2>TL;DR</h2>\n<p>One deberta-v3-small model is enough, ranking method, subsequences(segment).</p>\n<p>My solution only uses the ranking method. Given a markdown cell and a bunch of sorted code cells, predict the position of the markdown cell. The main difference here is that I do not use a whole notebook to rank a markdown cell, but just a part of it, which can be called a <code>segment</code>.</p>\n<p>For instance, given a notebook of 40 code cells, we can divide it into 4 sub segments, each segment containing 10 code cells. Then we rank each markdown of the whole notebook in the 10 code cells.</p>\n<p>Interesting thoughts about this method, if we divided the 40 code cells into 40 segments, each segment contains only 1 code cell, then this method is the same as Pairwise, if do not divide the notebook(or divide it into 1 segment), then it's same as full ranking.</p>\n<h2>Segment Ranking</h2>\n<p>The full ranking method, which is also open sourced <a href=\"https://www.kaggle.com/competitions/AI4Code/discussion/326970\" target=\"_blank\">here</a>, is to predict a markdown cell's position in the whole code cells. The sequence feed to the model is usually like this: markdown_cell + code_cell + code_cell … code_cell, but many of the sequence is way too long for transformer models(even for longformer), one simple method to handle the long sequence issue is to cut off the length of makdown_cell and code_cell to make the ensembled sequence length is acceptable. But the more cut-off, the more information we lose, so how can we keep the information as much as we can and also get a reasonable output sequence length?</p>\n<p>To address the global information and sequence length balance issue, I came up with the Segment Ranking method.</p>\n<p>A segment is part of a notebook's sorted code cells. If using M for the number of code cells in a notebook, and N for the number of code cells in a segment, then a notebook can be divided into C segments, in which C equals <code>math.ceil(M / N)</code>.</p>\n<p>Now since we have multiple segments of a notebook, and markdown cells in that notebook can only belong to one of the segments, we have to first decide if a markdown belongs to a segment, and then do the ranking in that segment. So there are two heads of the model, one for classification and one for ranking. The following figure demonstrates the details.</p>\n<p><img src=\"https://raw.githubusercontent.com/louis-she/ai4code/master/assets/segment-ranking.png\" alt=\"segment-ranking\"></p>\n<p>The number of cell in segments(N) here is a super important hyperparameter. A large N will speed up training and inference, small N can bring more context information. I ended up choosing N = 16 and sequence max length = 384.</p>\n<h2>Other important Task-related tricks</h2>\n<p><strong>Training with language modeling</strong></p>\n<p>There is actually the third head of my model, which is used as language modeling. The input for that head is &lt;previous_cell_encode + &lt;anchor_cell_encode + &lt;next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).</p>\n<p><strong>pad is a wast</strong></p>\n<p>I try to keep as much information as possible and reduce  tokens. Given the following 5 cells, how can we cut off to keep a length of 200? Instead cut every cell at a fixed length, I used the following method showed by the figure. Or have a look at the <a href=\"https://github.com/louis-she/ai4code/blob/master/tests/test_utils.py#L6\" target=\"_blank\">test case</a>.</p>\n<p><img src=\"https://raw.githubusercontent.com/louis-she/ai4code/master/assets/sequence-ensembling.png\" alt=\"sequence-ensembling\"></p>\n<p>Thanks for reading.</p>",
  "messages": [
    {
      "id": 1895564,
      "postDate": "2022-08-12T08:17:30.637Z",
      "content": "<h1>Segment Ranking(9th on LB)</h1>\n<p>Thank Kaggle for hosting this game, and the community for all the sharing. It's my first NLP competition so there are not much NLP-related sharing in my solution, just task-related tricks.</p>\n<p>Source code: <a href=\"https://github.com/louis-she/ai4code\" target=\"_blank\">https://github.com/louis-she/ai4code</a></p>\n<p>Inference Notebook: <a href=\"https://www.kaggle.com/code/snaker/new-rank/notebook\" target=\"_blank\">https://www.kaggle.com/code/snaker/new-rank/notebook</a></p>\n<h2>TL;DR</h2>\n<p>One deberta-v3-small model is enough, ranking method, subsequences(segment).</p>\n<p>My solution only uses the ranking method. Given a markdown cell and a bunch of sorted code cells, predict the position of the markdown cell. The main difference here is that I do not use a whole notebook to rank a markdown cell, but just a part of it, which can be called a <code>segment</code>.</p>\n<p>For instance, given a notebook of 40 code cells, we can divide it into 4 sub segments, each segment containing 10 code cells. Then we rank each markdown of the whole notebook in the 10 code cells.</p>\n<p>Interesting thoughts about this method, if we divided the 40 code cells into 40 segments, each segment contains only 1 code cell, then this method is the same as Pairwise, if do not divide the notebook(or divide it into 1 segment), then it's same as full ranking.</p>\n<h2>Segment Ranking</h2>\n<p>The full ranking method, which is also open sourced <a href=\"https://www.kaggle.com/competitions/AI4Code/discussion/326970\" target=\"_blank\">here</a>, is to predict a markdown cell's position in the whole code cells. The sequence feed to the model is usually like this: markdown_cell + code_cell + code_cell … code_cell, but many of the sequence is way too long for transformer models(even for longformer), one simple method to handle the long sequence issue is to cut off the length of makdown_cell and code_cell to make the ensembled sequence length is acceptable. But the more cut-off, the more information we lose, so how can we keep the information as much as we can and also get a reasonable output sequence length?</p>\n<p>To address the global information and sequence length balance issue, I came up with the Segment Ranking method.</p>\n<p>A segment is part of a notebook's sorted code cells. If using M for the number of code cells in a notebook, and N for the number of code cells in a segment, then a notebook can be divided into C segments, in which C equals <code>math.ceil(M / N)</code>.</p>\n<p>Now since we have multiple segments of a notebook, and markdown cells in that notebook can only belong to one of the segments, we have to first decide if a markdown belongs to a segment, and then do the ranking in that segment. So there are two heads of the model, one for classification and one for ranking. The following figure demonstrates the details.</p>\n<p><img src=\"https://raw.githubusercontent.com/louis-she/ai4code/master/assets/segment-ranking.png\" alt=\"segment-ranking\"></p>\n<p>The number of cell in segments(N) here is a super important hyperparameter. A large N will speed up training and inference, small N can bring more context information. I ended up choosing N = 16 and sequence max length = 384.</p>\n<h2>Other important Task-related tricks</h2>\n<p><strong>Training with language modeling</strong></p>\n<p>There is actually the third head of my model, which is used as language modeling. The input for that head is &lt;previous_cell_encode + &lt;anchor_cell_encode + &lt;next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).</p>\n<p><strong>pad is a wast</strong></p>\n<p>I try to keep as much information as possible and reduce  tokens. Given the following 5 cells, how can we cut off to keep a length of 200? Instead cut every cell at a fixed length, I used the following method showed by the figure. Or have a look at the <a href=\"https://github.com/louis-she/ai4code/blob/master/tests/test_utils.py#L6\" target=\"_blank\">test case</a>.</p>\n<p><img src=\"https://raw.githubusercontent.com/louis-she/ai4code/master/assets/sequence-ensembling.png\" alt=\"sequence-ensembling\"></p>\n<p>Thanks for reading.</p>",
      "rawMarkdown": "# Segment Ranking(9th on LB)\n\nThank Kaggle for hosting this game, and the community for all the sharing. It's my first NLP competition so there are not much NLP-related sharing in my solution, just task-related tricks.\n\nSource code: https://github.com/louis-she/ai4code\n\nInference Notebook: https://www.kaggle.com/code/snaker/new-rank/notebook\n\n## TL;DR\n\nOne deberta-v3-small model is enough, ranking method, subsequences(segment).\n\nMy solution only uses the ranking method. Given a markdown cell and a bunch of sorted code cells, predict the position of the markdown cell. The main difference here is that I do not use a whole notebook to rank a markdown cell, but just a part of it, which can be called a `segment`.\n\nFor instance, given a notebook of 40 code cells, we can divide it into 4 sub segments, each segment containing 10 code cells. Then we rank each markdown of the whole notebook in the 10 code cells.\n\nInteresting thoughts about this method, if we divided the 40 code cells into 40 segments, each segment contains only 1 code cell, then this method is the same as Pairwise, if do not divide the notebook(or divide it into 1 segment), then it's same as full ranking.\n\n## Segment Ranking\n\nThe full ranking method, which is also open sourced [here](https://www.kaggle.com/competitions/AI4Code/discussion/326970), is to predict a markdown cell's position in the whole code cells. The sequence feed to the model is usually like this: markdown_cell + code_cell + code_cell ... code_cell, but many of the sequence is way too long for transformer models(even for longformer), one simple method to handle the long sequence issue is to cut off the length of makdown_cell and code_cell to make the ensembled sequence length is acceptable. But the more cut-off, the more information we lose, so how can we keep the information as much as we can and also get a reasonable output sequence length?\n\nTo address the global information and sequence length balance issue, I came up with the Segment Ranking method.\n\nA segment is part of a notebook's sorted code cells. If using M for the number of code cells in a notebook, and N for the number of code cells in a segment, then a notebook can be divided into C segments, in which C equals `math.ceil(M / N)`.\n\nNow since we have multiple segments of a notebook, and markdown cells in that notebook can only belong to one of the segments, we have to first decide if a markdown belongs to a segment, and then do the ranking in that segment. So there are two heads of the model, one for classification and one for ranking. The following figure demonstrates the details.\n\n![segment-ranking](https://raw.githubusercontent.com/louis-she/ai4code/master/assets/segment-ranking.png)\n\nThe number of cell in segments(N) here is a super important hyperparameter. A large N will speed up training and inference, small N can bring more context information. I ended up choosing N = 16 and sequence max length = 384.\n\n## Other important Task-related tricks\n\n**Training with language modeling**\n\nThere is actually the third head of my model, which is used as language modeling. The input for that head is <previous_cell_encode + <anchor_cell_encode + <next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).\n\n**pad is a wast**\n\nI try to keep as much information as possible and reduce <pad> tokens. Given the following 5 cells, how can we cut off to keep a length of 200? Instead cut every cell at a fixed length, I used the following method showed by the figure. Or have a look at the [test case](https://github.com/louis-she/ai4code/blob/master/tests/test_utils.py#L6).\n\n![sequence-ensembling](https://raw.githubusercontent.com/louis-she/ai4code/master/assets/sequence-ensembling.png)\n\nThanks for reading.",
      "votes": 50
    },
    {
      "id": 1945913,
      "postDate": "2022-09-19T13:37:07.753Z",
      "content": "<p><a href=\"https://www.kaggle.com/snaker\" target=\"_blank\">@snaker</a> you are back? Do you know what happened?</p>\n<p>Good luck with getting a gold medal! Happy to see you back on LB.</p>",
      "rawMarkdown": "@snaker you are back? Do you know what happened?\n\nGood luck with getting a gold medal! Happy to see you back on LB.",
      "votes": 1,
      "replies": [
        {
          "id": 1947613,
          "postDate": "2022-09-20T15:01:54.877Z",
          "content": "<p>Maybe there are some mistakes(data related probably) the official has made during the 1st rerun.</p>",
          "rawMarkdown": "Maybe there are some mistakes(data related probably) the official has made during the 1st rerun.",
          "votes": 1
        },
        {
          "id": 1947694,
          "postDate": "2022-09-20T15:36:56.577Z",
          "content": "<p>I'm changing the title back… I got alive in the 2nd rerun..</p>",
          "rawMarkdown": "I'm changing the title back... I got alive in the 2nd rerun..",
          "votes": 2
        }
      ]
    },
    {
      "id": 1895695,
      "postDate": "2022-08-12T10:25:21.497Z",
      "content": "<p>Thank you. This is really interesting. Do you mind telling more about your inspiration for the solution? How have you come to it? Would love to hear the details :)</p>",
      "rawMarkdown": "Thank you. This is really interesting. Do you mind telling more about your inspiration for the solution? How have you come to it? Would love to hear the details :)",
      "votes": 1,
      "replies": [
        {
          "id": 1895978,
          "postDate": "2022-08-12T13:37:08.173Z",
          "content": "<p>I keep thinking about how to bring more global context information. The model can only handle 512 or 1024 length of sequence, but the number of tokens of one notebook is way larger than that. So splitting a notebook into smaller segments is the first and most straightforward way to handle this issue.</p>",
          "rawMarkdown": "I keep thinking about how to bring more global context information. The model can only handle 512 or 1024 length of sequence, but the number of tokens of one notebook is way larger than that. So splitting a notebook into smaller segments is the first and most straightforward way to handle this issue.",
          "votes": 1
        }
      ]
    },
    {
      "id": 1895575,
      "postDate": "2022-08-12T08:38:50.647Z",
      "content": "<p>Thanks for sharing! A clean and interesting solution indeed.</p>\n<p>How much improvement did your LM head and your padding strategy bring in terms of CV and/or public LB score? In our earlier experiments, our team briefly tried a padding strategy similar to yours, but it did not seem to improve on the more \"naive\" padding approach (Method 1 as you described).</p>",
      "rawMarkdown": "Thanks for sharing! A clean and interesting solution indeed.\n\nHow much improvement did your LM head and your padding strategy bring in terms of CV and/or public LB score? In our earlier experiments, our team briefly tried a padding strategy similar to yours, but it did not seem to improve on the more \"naive\" padding approach (Method 1 as you described).",
      "votes": 1,
      "replies": [
        {
          "id": 1895588,
          "postDate": "2022-08-12T08:54:00.803Z",
          "content": "<p>The ML head boosts CV is ~ 0.015 and the padding method boost CV is ~ 0.005.</p>",
          "rawMarkdown": "The ML head boosts CV is ~ 0.015 and the padding method boost CV is ~ 0.005.",
          "votes": 2
        }
      ]
    },
    {
      "id": 1906436,
      "postDate": "2022-08-19T22:01:41.083Z",
      "content": "<p>Thanks for sharing your solution, You clearly worked hard on it.<br>\nCongrats! </p>\n<p>The Devastator.</p>",
      "rawMarkdown": "Thanks for sharing your solution, You clearly worked hard on it.\nCongrats! \n\nThe Devastator.\n"
    },
    {
      "id": 1901854,
      "postDate": "2022-08-17T00:50:19.563Z",
      "content": "<p>Thanks for your sharing! Very clean solution.</p>\n<p>How do you make improvement on performance? Since in your github project says train.py get us a model with 0.87, but how do you improve the score from 0.87 to 0.91. </p>",
      "rawMarkdown": "Thanks for your sharing! Very clean solution.\n \nHow do you make improvement on performance? Since in your github project says train.py get us a model with 0.87, but how do you improve the score from 0.87 to 0.91. ",
      "replies": [
        {
          "id": 1902942,
          "postDate": "2022-08-17T02:33:09.693Z",
          "content": "<p>Train one epoch the score will be above 0.87, train more epochs(like 10) the score will be ~ 0.89 to 0.9 on both CV and LB.</p>\n<p>Add fold0 and external dataset to the training set and train 10 epochs, will achieve ~0.91 on LB</p>",
          "rawMarkdown": "Train one epoch the score will be above 0.87, train more epochs(like 10) the score will be ~ 0.89 to 0.9 on both CV and LB.\n\nAdd fold0 and external dataset to the training set and train 10 epochs, will achieve ~0.91 on LB",
          "votes": 2
        }
      ]
    },
    {
      "id": 1898832,
      "postDate": "2022-08-14T21:33:11.250Z",
      "content": "<p>This is quite innovative, nice!</p>",
      "rawMarkdown": "This is quite innovative, nice!\n"
    },
    {
      "id": 1897840,
      "postDate": "2022-08-14T05:47:46.370Z",
      "content": "<p>great work.</p>",
      "rawMarkdown": "great work."
    },
    {
      "id": 1897704,
      "postDate": "2022-08-14T02:57:40.730Z",
      "content": "<p>Thanks for sharing the source code and it's well explained.</p>",
      "rawMarkdown": "Thanks for sharing the source code and it's well explained."
    },
    {
      "id": 1896898,
      "postDate": "2022-08-13T08:54:48.150Z",
      "content": "<p>great work </p>",
      "rawMarkdown": "great work \n"
    },
    {
      "id": 1895767,
      "postDate": "2022-08-12T11:27:02.477Z",
      "content": "<p>Nice!  </p>\n<p>I did a \"but we have [popular new item] at home\" version of this in the last week, where I had one classification-based output using a codebert base model.  I also didn't try out the last solution for handling tokens, alas.</p>",
      "rawMarkdown": "Nice!  \n\nI did a \"but we have [popular new item] at home\" version of this in the last week, where I had one classification-based output using a codebert base model.  I also didn't try out the last solution for handling tokens, alas."
    },
    {
      "id": 1895641,
      "postDate": "2022-08-12T09:28:43.550Z",
      "content": "<p>Segment ranking - V. Original way to handle long sequences instead of using Longformer BigBird etc. Hope you get a well deserved gold.</p>\n<p>Below is it something like an auxiliary task you trained on but didnt actually use in inference. Is my understanding right?<br>\n<code>There is actually the third head of my model, which is used as language modeling. The input for that head is &lt;previous_cell_encode + &lt;anchor_cell_encode + &lt;next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).</code></p>",
      "rawMarkdown": "Segment ranking - V. Original way to handle long sequences instead of using Longformer BigBird etc. Hope you get a well deserved gold.\n\nBelow is it something like an auxiliary task you trained on but didnt actually use in inference. Is my understanding right?\n`There is actually the third head of my model, which is used as language modeling. The input for that head is <previous_cell_encode + <anchor_cell_encode + <next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).`",
      "replies": [
        {
          "id": 1895671,
          "postDate": "2022-08-12T10:02:40.757Z",
          "content": "<p>Yes it's not used at inference time.</p>\n<p>Instead of pretrain with language modeling, I train the language modeling along with the task.</p>",
          "rawMarkdown": "Yes it's not used at inference time.\n\nInstead of pretrain with language modeling, I train the language modeling along with the task.",
          "votes": 1
        }
      ]
    },
    {
      "id": 1898682,
      "postDate": "2022-08-14T18:19:28.340Z",
      "content": "<p>I'm wondering what are the training samples format, since we only know \"[code1] [code2] [code3] …\" and \"[markdown1] [markdown2] …\" in the training dataset, instead of \"[markdown1] [code1] [code2], [markdown2] [code3] [code4]\". So it seems we don't know if a markdown belong to a code cell(or segment). How to do the classification?</p>",
      "rawMarkdown": "I'm wondering what are the training samples format, since we only know \"[code1] [code2] [code3] ...\" and \"[markdown1] [markdown2] ...\" in the training dataset, instead of \"[markdown1] [code1] [code2], [markdown2] [code3] [code4]\". So it seems we don't know if a markdown belong to a code cell(or segment). How to do the classification?",
      "votes": 1,
      "isDeleted": true,
      "replies": [
        {
          "id": 1898964,
          "postDate": "2022-08-15T00:56:12.910Z",
          "content": "<p>if the real order of a notebook is like this: <code>c1 c2 c3 c4 c5 m1 c6 c7 c8 c9</code>, and divide into 3 segments:</p>\n<p>segment1: m1 c1 c2 c3   cls label 0(m1 not in the segment), ranking label: skipped<br>\nsegment2: m1 c4 c5 c6  cls label 1 (m1 is in the segment), ranking label: 2.5<br>\nsegments: m1 c7 c8 c9 cls label 0, ranking label: skipped</p>",
          "rawMarkdown": "if the real order of a notebook is like this: `c1 c2 c3 c4 c5 m1 c6 c7 c8 c9`, and divide into 3 segments:\n\nsegment1: m1 c1 c2 c3   cls label 0(m1 not in the segment), ranking label: skipped\nsegment2: m1 c4 c5 c6  cls label 1 (m1 is in the segment), ranking label: 2.5\nsegments: m1 c7 c8 c9 cls label 0, ranking label: skipped",
          "votes": 4
        },
        {
          "id": 1904066,
          "postDate": "2022-08-17T23:38:40.810Z",
          "content": "<p>How to konw the ranking label? It seems all the code cells appear before markdown cells in the train dataset</p>",
          "rawMarkdown": "How to konw the ranking label? It seems all the code cells appear before markdown cells in the train dataset",
          "isDeleted": true
        },
        {
          "id": 1904127,
          "postDate": "2022-08-18T01:36:19.670Z",
          "content": "<p><code>train_orders.csv</code> has the right order.</p>",
          "rawMarkdown": "`train_orders.csv` has the right order."
        }
      ]
    },
    {
      "id": 1896893,
      "postDate": "2022-08-13T08:52:09.173Z",
      "content": "<p>The padding method is cool, thanks!</p>",
      "rawMarkdown": "The padding method is cool, thanks!",
      "votes": 1
    },
    {
      "id": 1901859,
      "postDate": "2022-08-17T00:58:32.197Z",
      "content": "<p>Thanks, for sharing! well explained.</p>",
      "rawMarkdown": "Thanks, for sharing! well explained."
    }
  ],
  "comments": [
    {
      "id": 1945913,
      "author_name": "CroDoc",
      "author_url": "",
      "post_date": "2022-09-19T13:37:07.753000",
      "content": "<p><a href=\"https://www.kaggle.com/snaker\" target=\"_blank\">@snaker</a> you are back? Do you know what happened?</p>\n<p>Good luck with getting a gold medal! Happy to see you back on LB.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1947613,
          "author_name": "gezi",
          "author_url": "",
          "post_date": "2022-09-20T15:01:54.877000",
          "content": "<p>Maybe there are some mistakes(data related probably) the official has made during the 1st rerun.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 1947694,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-09-20T15:36:56.577000",
          "content": "<p>I'm changing the title back… I got alive in the 2nd rerun..</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 1895695,
      "author_name": "RoBi",
      "author_url": "",
      "post_date": "2022-08-12T10:25:21.497000",
      "content": "<p>Thank you. This is really interesting. Do you mind telling more about your inspiration for the solution? How have you come to it? Would love to hear the details :)</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1895978,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-12T13:37:08.173000",
          "content": "<p>I keep thinking about how to bring more global context information. The model can only handle 512 or 1024 length of sequence, but the number of tokens of one notebook is way larger than that. So splitting a notebook into smaller segments is the first and most straightforward way to handle this issue.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1895575,
      "author_name": "Ern",
      "author_url": "",
      "post_date": "2022-08-12T08:38:50.647000",
      "content": "<p>Thanks for sharing! A clean and interesting solution indeed.</p>\n<p>How much improvement did your LM head and your padding strategy bring in terms of CV and/or public LB score? In our earlier experiments, our team briefly tried a padding strategy similar to yours, but it did not seem to improve on the more \"naive\" padding approach (Method 1 as you described).</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1895588,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-12T08:54:00.803000",
          "content": "<p>The ML head boosts CV is ~ 0.015 and the padding method boost CV is ~ 0.005.</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 1906436,
      "author_name": "The Devastator",
      "author_url": "",
      "post_date": "2022-08-19T22:01:41.083000",
      "content": "<p>Thanks for sharing your solution, You clearly worked hard on it.<br>\nCongrats! </p>\n<p>The Devastator.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1901854,
      "author_name": "Teemo",
      "author_url": "",
      "post_date": "2022-08-17T00:50:19.563000",
      "content": "<p>Thanks for your sharing! Very clean solution.</p>\n<p>How do you make improvement on performance? Since in your github project says train.py get us a model with 0.87, but how do you improve the score from 0.87 to 0.91. </p>",
      "votes": 0,
      "replies": [
        {
          "id": 1902942,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-17T02:33:09.693000",
          "content": "<p>Train one epoch the score will be above 0.87, train more epochs(like 10) the score will be ~ 0.89 to 0.9 on both CV and LB.</p>\n<p>Add fold0 and external dataset to the training set and train 10 epochs, will achieve ~0.91 on LB</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 1898832,
      "author_name": "Tatiana Zinkina",
      "author_url": "",
      "post_date": "2022-08-14T21:33:11.250000",
      "content": "<p>This is quite innovative, nice!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1897840,
      "author_name": "Salitha Abeysinghe",
      "author_url": "",
      "post_date": "2022-08-14T05:47:46.370000",
      "content": "<p>great work.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1897704,
      "author_name": "samu2505",
      "author_url": "",
      "post_date": "2022-08-14T02:57:40.730000",
      "content": "<p>Thanks for sharing the source code and it's well explained.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1896898,
      "author_name": "Bilal Suppal",
      "author_url": "",
      "post_date": "2022-08-13T08:54:48.150000",
      "content": "<p>great work </p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1895767,
      "author_name": "happycube",
      "author_url": "",
      "post_date": "2022-08-12T11:27:02.477000",
      "content": "<p>Nice!  </p>\n<p>I did a \"but we have [popular new item] at home\" version of this in the last week, where I had one classification-based output using a codebert base model.  I also didn't try out the last solution for handling tokens, alas.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1895641,
      "author_name": "Allohvk",
      "author_url": "",
      "post_date": "2022-08-12T09:28:43.550000",
      "content": "<p>Segment ranking - V. Original way to handle long sequences instead of using Longformer BigBird etc. Hope you get a well deserved gold.</p>\n<p>Below is it something like an auxiliary task you trained on but didnt actually use in inference. Is my understanding right?<br>\n<code>There is actually the third head of my model, which is used as language modeling. The input for that head is &lt;previous_cell_encode + &lt;anchor_cell_encode + &lt;next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).</code></p>",
      "votes": 0,
      "replies": [
        {
          "id": 1895671,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-12T10:02:40.757000",
          "content": "<p>Yes it's not used at inference time.</p>\n<p>Instead of pretrain with language modeling, I train the language modeling along with the task.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1898682,
      "author_name": "",
      "author_url": "",
      "post_date": "2022-08-14T18:19:28.340000",
      "content": "<p>I'm wondering what are the training samples format, since we only know \"[code1] [code2] [code3] …\" and \"[markdown1] [markdown2] …\" in the training dataset, instead of \"[markdown1] [code1] [code2], [markdown2] [code3] [code4]\". So it seems we don't know if a markdown belong to a code cell(or segment). How to do the classification?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1898964,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-15T00:56:12.910000",
          "content": "<p>if the real order of a notebook is like this: <code>c1 c2 c3 c4 c5 m1 c6 c7 c8 c9</code>, and divide into 3 segments:</p>\n<p>segment1: m1 c1 c2 c3   cls label 0(m1 not in the segment), ranking label: skipped<br>\nsegment2: m1 c4 c5 c6  cls label 1 (m1 is in the segment), ranking label: 2.5<br>\nsegments: m1 c7 c8 c9 cls label 0, ranking label: skipped</p>",
          "votes": 4,
          "replies": []
        },
        {
          "id": 1904066,
          "author_name": "",
          "author_url": "",
          "post_date": "2022-08-17T23:38:40.810000",
          "content": "<p>How to konw the ranking label? It seems all the code cells appear before markdown cells in the train dataset</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 1904127,
          "author_name": "Chenglu",
          "author_url": "",
          "post_date": "2022-08-18T01:36:19.670000",
          "content": "<p><code>train_orders.csv</code> has the right order.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 1896893,
      "author_name": "gezi",
      "author_url": "",
      "post_date": "2022-08-13T08:52:09.173000",
      "content": "<p>The padding method is cool, thanks!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1901859,
      "author_name": "Hyunkook Noh",
      "author_url": "",
      "post_date": "2022-08-17T00:58:32.197000",
      "content": "<p>Thanks, for sharing! well explained.</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1895564": "# Segment Ranking(9th on LB)\n\nThank Kaggle for hosting this game, and the community for all the sharing. It's my first NLP competition so there are not much NLP-related sharing in my solution, just task-related tricks.\n\nSource code: https://github.com/louis-she/ai4code\n\nInference Notebook: https://www.kaggle.com/code/snaker/new-rank/notebook\n\n## TL;DR\n\nOne deberta-v3-small model is enough, ranking method, subsequences(segment).\n\nMy solution only uses the ranking method. Given a markdown cell and a bunch of sorted code cells, predict the position of the markdown cell. The main difference here is that I do not use a whole notebook to rank a markdown cell, but just a part of it, which can be called a `segment`.\n\nFor instance, given a notebook of 40 code cells, we can divide it into 4 sub segments, each segment containing 10 code cells. Then we rank each markdown of the whole notebook in the 10 code cells.\n\nInteresting thoughts about this method, if we divided the 40 code cells into 40 segments, each segment contains only 1 code cell, then this method is the same as Pairwise, if do not divide the notebook(or divide it into 1 segment), then it's same as full ranking.\n\n## Segment Ranking\n\nThe full ranking method, which is also open sourced [here](https://www.kaggle.com/competitions/AI4Code/discussion/326970), is to predict a markdown cell's position in the whole code cells. The sequence feed to the model is usually like this: markdown_cell + code_cell + code_cell ... code_cell, but many of the sequence is way too long for transformer models(even for longformer), one simple method to handle the long sequence issue is to cut off the length of makdown_cell and code_cell to make the ensembled sequence length is acceptable. But the more cut-off, the more information we lose, so how can we keep the information as much as we can and also get a reasonable output sequence length?\n\nTo address the global information and sequence length balance issue, I came up with the Segment Ranking method.\n\nA segment is part of a notebook's sorted code cells. If using M for the number of code cells in a notebook, and N for the number of code cells in a segment, then a notebook can be divided into C segments, in which C equals `math.ceil(M / N)`.\n\nNow since we have multiple segments of a notebook, and markdown cells in that notebook can only belong to one of the segments, we have to first decide if a markdown belongs to a segment, and then do the ranking in that segment. So there are two heads of the model, one for classification and one for ranking. The following figure demonstrates the details.\n\n![segment-ranking](https://raw.githubusercontent.com/louis-she/ai4code/master/assets/segment-ranking.png)\n\nThe number of cell in segments(N) here is a super important hyperparameter. A large N will speed up training and inference, small N can bring more context information. I ended up choosing N = 16 and sequence max length = 384.\n\n## Other important Task-related tricks\n\n**Training with language modeling**\n\nThere is actually the third head of my model, which is used as language modeling. The input for that head is <previous_cell_encode + <anchor_cell_encode + <next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).\n\n**pad is a wast**\n\nI try to keep as much information as possible and reduce <pad> tokens. Given the following 5 cells, how can we cut off to keep a length of 200? Instead cut every cell at a fixed length, I used the following method showed by the figure. Or have a look at the [test case](https://github.com/louis-she/ai4code/blob/master/tests/test_utils.py#L6).\n\n![sequence-ensembling](https://raw.githubusercontent.com/louis-she/ai4code/master/assets/sequence-ensembling.png)\n\nThanks for reading.",
    "1945913": "@snaker you are back? Do you know what happened?\n\nGood luck with getting a gold medal! Happy to see you back on LB.",
    "1895695": "Thank you. This is really interesting. Do you mind telling more about your inspiration for the solution? How have you come to it? Would love to hear the details :)",
    "1895575": "Thanks for sharing! A clean and interesting solution indeed.\n\nHow much improvement did your LM head and your padding strategy bring in terms of CV and/or public LB score? In our earlier experiments, our team briefly tried a padding strategy similar to yours, but it did not seem to improve on the more \"naive\" padding approach (Method 1 as you described).",
    "1906436": "Thanks for sharing your solution, You clearly worked hard on it.\nCongrats! \n\nThe Devastator.\n",
    "1901854": "Thanks for your sharing! Very clean solution.\n \nHow do you make improvement on performance? Since in your github project says train.py get us a model with 0.87, but how do you improve the score from 0.87 to 0.91. ",
    "1898832": "This is quite innovative, nice!\n",
    "1897840": "great work.",
    "1897704": "Thanks for sharing the source code and it's well explained.",
    "1896898": "great work \n",
    "1895767": "Nice!  \n\nI did a \"but we have [popular new item] at home\" version of this in the last week, where I had one classification-based output using a codebert base model.  I also didn't try out the last solution for handling tokens, alas.",
    "1895641": "Segment ranking - V. Original way to handle long sequences instead of using Longformer BigBird etc. Hope you get a well deserved gold.\n\nBelow is it something like an auxiliary task you trained on but didnt actually use in inference. Is my understanding right?\n`There is actually the third head of my model, which is used as language modeling. The input for that head is <previous_cell_encode + <anchor_cell_encode + <next_cell_encode, positive means that the three is continuous, negative means not continuous, they are just randomly pick from the notebook(but not the previous and next ones).`",
    "1898682": "I'm wondering what are the training samples format, since we only know \"[code1] [code2] [code3] ...\" and \"[markdown1] [markdown2] ...\" in the training dataset, instead of \"[markdown1] [code1] [code2], [markdown2] [code3] [code4]\". So it seems we don't know if a markdown belong to a code cell(or segment). How to do the classification?",
    "1896893": "The padding method is cool, thanks!",
    "1901859": "Thanks, for sharing! well explained."
  }
}