{
  "id": 187864,
  "title": "[21st place] - My solution to 2 silver medals in GL 2020",
  "url": "/competitions/landmark-recognition-2020/writeups/khoa-ngo-21st-place-my-solution-to-2-silver-medals",
  "author_name": "",
  "post_date": "2020-10-09T08:47:25.643Z",
  "votes": 10,
  "comment_count": 14,
  "views": 0,
  "content": "<p>First of all, congratulations to everyone for having interesting journeys across such a challenging competition, especially to the top teams and all who gained a lot from the competition. Also, thanks to google for organizing the 3rd Landmark competitions.</p>\n<p>For me, throughout two competitions of Google Landmark 2020, I really learnt such an amount of knowledge, and also came up with many ideas to compete in those harsh competitions. Here are things I have done.</p>\n<h1><strong>Retrieval competition</strong></h1>\n<p>Actually, I didn’t think this competition was for me at first, because I’m kind of a newbie in tensorflow :)). However, after a bad performance in Global Wheat Detection challenge, I decided to join seriously in the competition within 13 days left.</p>\n<h2>Architecture</h2>\n<p>First, I tried to train delf model from <a href=\"https://github.com/tensorflow/models/tree/master/research/delf\" target=\"_blank\">tf delf</a>, the result is no where near the host baseline kernel (only 0.12-0.13 compared to 0.271 of host baseline) so I quickly quitted this way.</p>\n<p>Luckily, <a href=\"https://www.kaggle.com/chandanverma/convert-pytorch-model-to-tf-2-2-submission-format\" target=\"_blank\">onnx</a> kernel was published and it was a big chance for a pytorch user like me that I could develop my own model. From top-down view, my final model is ensemble of 4 models, which can be represented as followed:</p>\n<pre><code>net_1 -&gt; feature_1 |\n...                |--[concat]--&gt; [fc 4096]--&gt; final_feature\nnet_4 -&gt; feature_4 |\n</code></pre>\n<p>With net_i:</p>\n<pre><code>CNN backbone --&gt; GeM pooling --&gt; fc --&gt; batchnorm --&gt; arcface/cosface\n</code></pre>\n<p>More detailed:</p>\n<pre><code>net_1: efficientnet-b2, fc 1024\nnet_2: efficientnet-b3, fc 512\nnet_3: efficientnet-b3, fc 1024\nnet_4: efficientnet-b4, fc 512\n</code></pre>\n<p>From my results, training one more fc layer on top of ensemble net gave a 0.02 boost on final score compared to simple concatenating.<br>\nI used input images of size 256x256, which might really affect my score (compared to top solutions that use images of large size), and training only with GLDv2 clean. Also while I always use RAdam optimizer, I realize that almost all top teams use SGD, maybe I should switch to SGD in the future?</p>\n<h2>Result</h2>\n<pre><code>Best single-model score: 0.270 - 0.233 (efficientnet-b3, fc 512)\nBest ensemble-model score: 0.293 - 0.260\n</code></pre>\n<p>I had learnt a lot from public solution of top teams after the end of the competition, and figured out somethings I could improve in the retrieval task:</p>\n<ul>\n<li>larger image size</li>\n<li>dealing with imbalanced dataset using class weights</li>\n<li>training on extended dataset: GLDv1, GLDv2 full.</li>\n</ul>\n<p>Although I struggled with tf model submission type at first, it was at last very lucky for me because I didn't have to care about the post-processing phase such as local features, rescoring and reranking, ransac, etc. </p>\n<h1><strong>Recognition competition</strong></h1>\n<p>Maybe I was lucky in the retrieval competition, finally I had to deal with everything when coming to the recognition challenge :).</p>\n<h2>Global feature extraction</h2>\n<p>I used entirely different set of backbones in comparison with those in retrieval task:</p>\n<pre><code>net_1: resnest200, fc 512\nnet_2: resnest200, fc 1024\nnet_3: resnest269, fc 512\nnet_4: resnest269, fc 1024\nnet_5: resnet152, fc 512\n</code></pre>\n<p>From my results, resnest and resnet152 gave much better performances than efficientnet (even b7). I trained with 224x224 images of GLDv1 + GLDv2 clean and fine-tuned with 448x448 of GLDv2 clean, using arcface.</p>\n<h2>Local feature extraction</h2>\n<p>I trained delg, delf with <a href=\"https://github.com/tensorflow/models/tree/master/research/delf\" target=\"_blank\">tf delf</a> again, and further trained a PCA to diminish dimension of descriptors from 1024 -&gt; 128. However, I couldn’t beat the delg model in the host baseline kernel. My best self-trained delg is worse 0.01 than baseline delg.<br>\nSo for my final score, I chose the delg baseline model to extract local features.</p>\n<h2>Rescoring and reranking</h2>\n<p>I defined score of reranking process as followed:</p>\n<pre><code>score = global_score + local_score + recognition_score\n</code></pre>\n<p>Definition of my own recognition score:</p>\n<pre><code>recognition_score = max_value * (1-k/topk) ** alpha\n- recognition score is based on the arcface head of my model\n- max_value: max value of recognition score\n- k (&lt; topk): rank of predicted label in sorted arcface head\n- topk: topk prediction of arcface, recognition_score &gt; 0 if predicted label is in topk else 0\n- alpha &lt; 1: giving a boost to small k (top1, top2 &gt;&gt; top 99, top 100)\n- My final submission: (max_value, topk, alpha) = (2, 200, 0.35)\n</code></pre>\n<p>I didn’t try many values of hyperparameters of my recognition_score, but it gave a 0.006 boost compared to the scoring scheme from the baseline kernel.</p>\n<h2>Result</h2>\n<pre><code>Best single-model score: 0.5424 - 0.5233 (resnest200, fc 512)\nBest ensemble-model score: 0.5640 - 0.5354\n</code></pre>\n<h2>Not worked things</h2>\n<p>Here are some ideas which did not work well:</p>\n<ul>\n<li>Filter distractors by arcface head (if label not in top 200 -&gt; non-landmark) it downgraded my score around 0.01</li>\n<li>Online fine-tuning with private training set, downgraded my score around 0.02</li>\n</ul>\n<p>That might be a little long for now :)). I will update this post if I remember something interesting. Thank you for reading my sharing!</p>",
  "messages": [
    {
      "id": "1033012",
      "postDate": "09/30/2020 15:40:35",
      "content": "<p>First of all, congratulations to everyone for having interesting journeys across such a challenging competition, especially to the top teams and all who gained a lot from the competition. Also, thanks to google for organizing the 3rd Landmark competitions.</p>\n<p>For me, throughout two competitions of Google Landmark 2020, I really learnt such an amount of knowledge, and also came up with many ideas to compete in those harsh competitions. Here are things I have done.</p>\n<h1><strong>Retrieval competition</strong></h1>\n<p>Actually, I didn’t think this competition was for me at first, because I’m kind of a newbie in tensorflow :)). However, after a bad performance in Global Wheat Detection challenge, I decided to join seriously in the competition within 13 days left.</p>\n<h2>Architecture</h2>\n<p>First, I tried to train delf model from <a href=\"https://github.com/tensorflow/models/tree/master/research/delf\" target=\"_blank\">tf delf</a>, the result is no where near the host baseline kernel (only 0.12-0.13 compared to 0.271 of host baseline) so I quickly quitted this way.</p>\n<p>Luckily, <a href=\"https://www.kaggle.com/chandanverma/convert-pytorch-model-to-tf-2-2-submission-format\" target=\"_blank\">onnx</a> kernel was published and it was a big chance for a pytorch user like me that I could develop my own model. From top-down view, my final model is ensemble of 4 models, which can be represented as followed:</p>\n<pre><code>net_1 -&gt; feature_1 |\n...                |--[concat]--&gt; [fc 4096]--&gt; final_feature\nnet_4 -&gt; feature_4 |\n</code></pre>\n<p>With net_i:</p>\n<pre><code>CNN backbone --&gt; GeM pooling --&gt; fc --&gt; batchnorm --&gt; arcface/cosface\n</code></pre>\n<p>More detailed:</p>\n<pre><code>net_1: efficientnet-b2, fc 1024\nnet_2: efficientnet-b3, fc 512\nnet_3: efficientnet-b3, fc 1024\nnet_4: efficientnet-b4, fc 512\n</code></pre>\n<p>From my results, training one more fc layer on top of ensemble net gave a 0.02 boost on final score compared to simple concatenating.<br>\nI used input images of size 256x256, which might really affect my score (compared to top solutions that use images of large size), and training only with GLDv2 clean. Also while I always use RAdam optimizer, I realize that almost all top teams use SGD, maybe I should switch to SGD in the future?</p>\n<h2>Result</h2>\n<pre><code>Best single-model score: 0.270 - 0.233 (efficientnet-b3, fc 512)\nBest ensemble-model score: 0.293 - 0.260\n</code></pre>\n<p>I had learnt a lot from public solution of top teams after the end of the competition, and figured out somethings I could improve in the retrieval task:</p>\n<ul>\n<li>larger image size</li>\n<li>dealing with imbalanced dataset using class weights</li>\n<li>training on extended dataset: GLDv1, GLDv2 full.</li>\n</ul>\n<p>Although I struggled with tf model submission type at first, it was at last very lucky for me because I didn't have to care about the post-processing phase such as local features, rescoring and reranking, ransac, etc. </p>\n<h1><strong>Recognition competition</strong></h1>\n<p>Maybe I was lucky in the retrieval competition, finally I had to deal with everything when coming to the recognition challenge :).</p>\n<h2>Global feature extraction</h2>\n<p>I used entirely different set of backbones in comparison with those in retrieval task:</p>\n<pre><code>net_1: resnest200, fc 512\nnet_2: resnest200, fc 1024\nnet_3: resnest269, fc 512\nnet_4: resnest269, fc 1024\nnet_5: resnet152, fc 512\n</code></pre>\n<p>From my results, resnest and resnet152 gave much better performances than efficientnet (even b7). I trained with 224x224 images of GLDv1 + GLDv2 clean and fine-tuned with 448x448 of GLDv2 clean, using arcface.</p>\n<h2>Local feature extraction</h2>\n<p>I trained delg, delf with <a href=\"https://github.com/tensorflow/models/tree/master/research/delf\" target=\"_blank\">tf delf</a> again, and further trained a PCA to diminish dimension of descriptors from 1024 -&gt; 128. However, I couldn’t beat the delg model in the host baseline kernel. My best self-trained delg is worse 0.01 than baseline delg.<br>\nSo for my final score, I chose the delg baseline model to extract local features.</p>\n<h2>Rescoring and reranking</h2>\n<p>I defined score of reranking process as followed:</p>\n<pre><code>score = global_score + local_score + recognition_score\n</code></pre>\n<p>Definition of my own recognition score:</p>\n<pre><code>recognition_score = max_value * (1-k/topk) ** alpha\n- recognition score is based on the arcface head of my model\n- max_value: max value of recognition score\n- k (&lt; topk): rank of predicted label in sorted arcface head\n- topk: topk prediction of arcface, recognition_score &gt; 0 if predicted label is in topk else 0\n- alpha &lt; 1: giving a boost to small k (top1, top2 &gt;&gt; top 99, top 100)\n- My final submission: (max_value, topk, alpha) = (2, 200, 0.35)\n</code></pre>\n<p>I didn’t try many values of hyperparameters of my recognition_score, but it gave a 0.006 boost compared to the scoring scheme from the baseline kernel.</p>\n<h2>Result</h2>\n<pre><code>Best single-model score: 0.5424 - 0.5233 (resnest200, fc 512)\nBest ensemble-model score: 0.5640 - 0.5354\n</code></pre>\n<h2>Not worked things</h2>\n<p>Here are some ideas which did not work well:</p>\n<ul>\n<li>Filter distractors by arcface head (if label not in top 200 -&gt; non-landmark) it downgraded my score around 0.01</li>\n<li>Online fine-tuning with private training set, downgraded my score around 0.02</li>\n</ul>\n<p>That might be a little long for now :)). I will update this post if I remember something interesting. Thank you for reading my sharing!</p>",
      "rawMarkdown": "First of all, congratulations to everyone for having interesting journeys across such a challenging competition, especially to the top teams and all who gained a lot from the competition. Also, thanks to google for organizing the 3rd Landmark competitions.\n\nFor me, throughout two competitions of Google Landmark 2020, I really learnt such an amount of knowledge, and also came up with many ideas to compete in those harsh competitions. Here are things I have done.\n\n# **Retrieval competition**\nActually, I didn’t think this competition was for me at first, because I’m kind of a newbie in tensorflow :)). However, after a bad performance in Global Wheat Detection challenge, I decided to join seriously in the competition within 13 days left.\n\n## Architecture\nFirst, I tried to train delf model from [tf delf](https://github.com/tensorflow/models/tree/master/research/delf), the result is no where near the host baseline kernel (only 0.12-0.13 compared to 0.271 of host baseline) so I quickly quitted this way.\n\nLuckily, [onnx](https://www.kaggle.com/chandanverma/convert-pytorch-model-to-tf-2-2-submission-format) kernel was published and it was a big chance for a pytorch user like me that I could develop my own model. From top-down view, my final model is ensemble of 4 models, which can be represented as followed:\n```\nnet_1 -> feature_1 |\n...                |--[concat]--> [fc 4096]--> final_feature\nnet_4 -> feature_4 |\n```\nWith net_i:\n```\nCNN backbone --> GeM pooling --> fc --> batchnorm --> arcface/cosface\n```\nMore detailed:\n```\nnet_1: efficientnet-b2, fc 1024\nnet_2: efficientnet-b3, fc 512\nnet_3: efficientnet-b3, fc 1024\nnet_4: efficientnet-b4, fc 512\n```\nFrom my results, training one more fc layer on top of ensemble net gave a 0.02 boost on final score compared to simple concatenating.\nI used input images of size 256x256, which might really affect my score (compared to top solutions that use images of large size), and training only with GLDv2 clean. Also while I always use RAdam optimizer, I realize that almost all top teams use SGD, maybe I should switch to SGD in the future?\n##Result\n```\nBest single-model score: 0.270 - 0.233 (efficientnet-b3, fc 512)\nBest ensemble-model score: 0.293 - 0.260\n```\nI had learnt a lot from public solution of top teams after the end of the competition, and figured out somethings I could improve in the retrieval task:\n- larger image size\n- dealing with imbalanced dataset using class weights\n- training on extended dataset: GLDv1, GLDv2 full.\n\nAlthough I struggled with tf model submission type at first, it was at last very lucky for me because I didn't have to care about the post-processing phase such as local features, rescoring and reranking, ransac, etc. \n#**Recognition competition**\nMaybe I was lucky in the retrieval competition, finally I had to deal with everything when coming to the recognition challenge :).\n## Global feature extraction\nI used entirely different set of backbones in comparison with those in retrieval task:\n```\nnet_1: resnest200, fc 512\nnet_2: resnest200, fc 1024\nnet_3: resnest269, fc 512\nnet_4: resnest269, fc 1024\nnet_5: resnet152, fc 512\n```\nFrom my results, resnest and resnet152 gave much better performances than efficientnet (even b7). I trained with 224x224 images of GLDv1 + GLDv2 clean and fine-tuned with 448x448 of GLDv2 clean, using arcface.\n## Local feature extraction\nI trained delg, delf with [tf delf](https://github.com/tensorflow/models/tree/master/research/delf) again, and further trained a PCA to diminish dimension of descriptors from 1024 -> 128. However, I couldn’t beat the delg model in the host baseline kernel. My best self-trained delg is worse 0.01 than baseline delg.\nSo for my final score, I chose the delg baseline model to extract local features.\n## Rescoring and reranking\nI defined score of reranking process as followed:\n```\nscore = global_score + local_score + recognition_score\n```\nDefinition of my own recognition score:\n```\nrecognition_score = max_value * (1-k/topk) ** alpha\n- recognition score is based on the arcface head of my model\n- max_value: max value of recognition score\n- k (< topk): rank of predicted label in sorted arcface head\n- topk: topk prediction of arcface, recognition_score > 0 if predicted label is in topk else 0\n- alpha < 1: giving a boost to small k (top1, top2 >> top 99, top 100)\n- My final submission: (max_value, topk, alpha) = (2, 200, 0.35)\n```\nI didn’t try many values of hyperparameters of my recognition_score, but it gave a 0.006 boost compared to the scoring scheme from the baseline kernel.\n## Result\n```\nBest single-model score: 0.5424 - 0.5233 (resnest200, fc 512)\nBest ensemble-model score: 0.5640 - 0.5354\n```\n## Not worked things\nHere are some ideas which did not work well:\n- Filter distractors by arcface head (if label not in top 200 -> non-landmark) it downgraded my score around 0.01\n- Online fine-tuning with private training set, downgraded my score around 0.02\n\nThat might be a little long for now :)). I will update this post if I remember something interesting. Thank you for reading my sharing!",
      "votes": null
    },
    {
      "id": "1033015",
      "postDate": "09/30/2020 15:41:47",
      "content": "<p>Congrats on silver. Thanks for sharing <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> </p>",
      "rawMarkdown": "Congrats on silver. Thanks for sharing @nejicool96",
      "votes": null
    },
    {
      "id": "1033018",
      "postDate": "09/30/2020 15:43:33",
      "content": "<p>Thank you <a href=\"https://www.kaggle.com/vineeth1999\" target=\"_blank\">@vineeth1999</a>  :))</p>",
      "rawMarkdown": "Thank you @vineeth1999  :))",
      "votes": null
    },
    {
      "id": "1033035",
      "postDate": "09/30/2020 15:57:39",
      "content": "<p>Good job! Congrats on silver from HUST bro Khoa <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> :D</p>",
      "rawMarkdown": "Good job! Congrats on silver from HUST bro Khoa @nejicool96 :D",
      "votes": null
    },
    {
      "id": "1033038",
      "postDate": "09/30/2020 16:01:54",
      "content": "<p>Wow :)), thank you <a href=\"https://www.kaggle.com/duykhanh99\" target=\"_blank\">@duykhanh99</a> </p>",
      "rawMarkdown": "Wow :)), thank you @duykhanh99",
      "votes": null
    },
    {
      "id": "1033055",
      "postDate": "09/30/2020 16:19:53",
      "content": "<p>Congrajulations!!! Thanks for sharing😊</p>",
      "rawMarkdown": "Congrajulations!!! Thanks for sharing😊",
      "votes": null
    },
    {
      "id": "1033062",
      "postDate": "09/30/2020 16:23:43",
      "content": "<p>Thank you :D</p>",
      "rawMarkdown": "Thank you :D",
      "votes": null
    },
    {
      "id": "1033157",
      "postDate": "09/30/2020 17:54:00",
      "content": "<p>That's interesting 😍<br>\nCongratulations <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> on your third silver medal 👍</p>",
      "rawMarkdown": "That's interesting 😍\nCongratulations @nejicool96 on your third silver medal 👍",
      "votes": null
    },
    {
      "id": "1033162",
      "postDate": "09/30/2020 17:58:35",
      "content": "<p>Thank you, congrats your silver too :D </p>",
      "rawMarkdown": "Thank you, congrats your silver too :D",
      "votes": null
    },
    {
      "id": "1033528",
      "postDate": "10/01/2020 04:29:51",
      "content": "<p>Nice approach! Congratulations to you and thanks for sharing this.</p>",
      "rawMarkdown": "Nice approach! Congratulations to you and thanks for sharing this.",
      "votes": null
    },
    {
      "id": "1033544",
      "postDate": "10/01/2020 04:48:19",
      "content": "<p>Thank you :)</p>",
      "rawMarkdown": "Thank you :)",
      "votes": null
    },
    {
      "id": "1037639",
      "postDate": "10/05/2020 07:36:04",
      "content": "<p>Hi <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> . Can I call you : A landmark recognition expert :))</p>",
      "rawMarkdown": "Hi @nejicool96 . Can I call you : A landmark recognition expert :))",
      "votes": null
    },
    {
      "id": "1037645",
      "postDate": "10/05/2020 07:40:30",
      "content": "<p>Thank you, but no, call me Khoa plz :))).</p>",
      "rawMarkdown": "Thank you, but no, call me Khoa plz :))).",
      "votes": null
    },
    {
      "id": "1043763",
      "postDate": "10/09/2020 08:20:43",
      "content": "<p>Congrats! Thanks for your sharing! Do you use any non-landmark filtering tricks for your final results?</p>",
      "rawMarkdown": "Congrats! Thanks for your sharing! Do you use any non-landmark filtering tricks for your final results?",
      "votes": null
    },
    {
      "id": "1043789",
      "postDate": "10/09/2020 08:45:30",
      "content": "<p>Thank you. I tried to filter non-landmark by using the probabilities of arcface head (updated in my post), but it downgraded my score so I didn't use any filtering in my final results.</p>",
      "rawMarkdown": "Thank you. I tried to filter non-landmark by using the probabilities of arcface head (updated in my post), but it downgraded my score so I didn't use any filtering in my final results.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1033015,
      "author_name": "vineeth1999",
      "author_url": "",
      "post_date": "09/30/2020 15:41:47",
      "content": "<p>Congrats on silver. Thanks for sharing <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> </p>",
      "votes": null,
      "replies": [
        {
          "id": 1033018,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "09/30/2020 15:43:33",
          "content": "<p>Thank you <a href=\"https://www.kaggle.com/vineeth1999\" target=\"_blank\">@vineeth1999</a>  :))</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1033035,
      "author_name": "duykhanh99",
      "author_url": "",
      "post_date": "09/30/2020 15:57:39",
      "content": "<p>Good job! Congrats on silver from HUST bro Khoa <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> :D</p>",
      "votes": null,
      "replies": [
        {
          "id": 1033038,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "09/30/2020 16:01:54",
          "content": "<p>Wow :)), thank you <a href=\"https://www.kaggle.com/duykhanh99\" target=\"_blank\">@duykhanh99</a> </p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1033055,
      "author_name": "amrut11",
      "author_url": "",
      "post_date": "09/30/2020 16:19:53",
      "content": "<p>Congrajulations!!! Thanks for sharing😊</p>",
      "votes": null,
      "replies": [
        {
          "id": 1033062,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "09/30/2020 16:23:43",
          "content": "<p>Thank you :D</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1033157,
      "author_name": "rahim3",
      "author_url": "",
      "post_date": "09/30/2020 17:54:00",
      "content": "<p>That's interesting 😍<br>\nCongratulations <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> on your third silver medal 👍</p>",
      "votes": null,
      "replies": [
        {
          "id": 1033162,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "09/30/2020 17:58:35",
          "content": "<p>Thank you, congrats your silver too :D </p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1033528,
      "author_name": "ee1150641",
      "author_url": "",
      "post_date": "10/01/2020 04:29:51",
      "content": "<p>Nice approach! Congratulations to you and thanks for sharing this.</p>",
      "votes": null,
      "replies": [
        {
          "id": 1033544,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "10/01/2020 04:48:19",
          "content": "<p>Thank you :)</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1037639,
      "author_name": "daonguyenduong",
      "author_url": "",
      "post_date": "10/05/2020 07:36:04",
      "content": "<p>Hi <a href=\"https://www.kaggle.com/nejicool96\" target=\"_blank\">@nejicool96</a> . Can I call you : A landmark recognition expert :))</p>",
      "votes": null,
      "replies": [
        {
          "id": 1037645,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "10/05/2020 07:40:30",
          "content": "<p>Thank you, but no, call me Khoa plz :))).</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1043763,
      "author_name": "sjtuwh",
      "author_url": "",
      "post_date": "10/09/2020 08:20:43",
      "content": "<p>Congrats! Thanks for your sharing! Do you use any non-landmark filtering tricks for your final results?</p>",
      "votes": null,
      "replies": [
        {
          "id": 1043789,
          "author_name": "nejicool96",
          "author_url": "",
          "post_date": "10/09/2020 08:45:30",
          "content": "<p>Thank you. I tried to filter non-landmark by using the probabilities of arcface head (updated in my post), but it downgraded my score so I didn't use any filtering in my final results.</p>",
          "votes": null,
          "replies": []
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "1033012": "First of all, congratulations to everyone for having interesting journeys across such a challenging competition, especially to the top teams and all who gained a lot from the competition. Also, thanks to google for organizing the 3rd Landmark competitions.\n\nFor me, throughout two competitions of Google Landmark 2020, I really learnt such an amount of knowledge, and also came up with many ideas to compete in those harsh competitions. Here are things I have done.\n\n# **Retrieval competition**\nActually, I didn’t think this competition was for me at first, because I’m kind of a newbie in tensorflow :)). However, after a bad performance in Global Wheat Detection challenge, I decided to join seriously in the competition within 13 days left.\n\n## Architecture\nFirst, I tried to train delf model from [tf delf](https://github.com/tensorflow/models/tree/master/research/delf), the result is no where near the host baseline kernel (only 0.12-0.13 compared to 0.271 of host baseline) so I quickly quitted this way.\n\nLuckily, [onnx](https://www.kaggle.com/chandanverma/convert-pytorch-model-to-tf-2-2-submission-format) kernel was published and it was a big chance for a pytorch user like me that I could develop my own model. From top-down view, my final model is ensemble of 4 models, which can be represented as followed:\n```\nnet_1 -> feature_1 |\n...                |--[concat]--> [fc 4096]--> final_feature\nnet_4 -> feature_4 |\n```\nWith net_i:\n```\nCNN backbone --> GeM pooling --> fc --> batchnorm --> arcface/cosface\n```\nMore detailed:\n```\nnet_1: efficientnet-b2, fc 1024\nnet_2: efficientnet-b3, fc 512\nnet_3: efficientnet-b3, fc 1024\nnet_4: efficientnet-b4, fc 512\n```\nFrom my results, training one more fc layer on top of ensemble net gave a 0.02 boost on final score compared to simple concatenating.\nI used input images of size 256x256, which might really affect my score (compared to top solutions that use images of large size), and training only with GLDv2 clean. Also while I always use RAdam optimizer, I realize that almost all top teams use SGD, maybe I should switch to SGD in the future?\n##Result\n```\nBest single-model score: 0.270 - 0.233 (efficientnet-b3, fc 512)\nBest ensemble-model score: 0.293 - 0.260\n```\nI had learnt a lot from public solution of top teams after the end of the competition, and figured out somethings I could improve in the retrieval task:\n- larger image size\n- dealing with imbalanced dataset using class weights\n- training on extended dataset: GLDv1, GLDv2 full.\n\nAlthough I struggled with tf model submission type at first, it was at last very lucky for me because I didn't have to care about the post-processing phase such as local features, rescoring and reranking, ransac, etc. \n#**Recognition competition**\nMaybe I was lucky in the retrieval competition, finally I had to deal with everything when coming to the recognition challenge :).\n## Global feature extraction\nI used entirely different set of backbones in comparison with those in retrieval task:\n```\nnet_1: resnest200, fc 512\nnet_2: resnest200, fc 1024\nnet_3: resnest269, fc 512\nnet_4: resnest269, fc 1024\nnet_5: resnet152, fc 512\n```\nFrom my results, resnest and resnet152 gave much better performances than efficientnet (even b7). I trained with 224x224 images of GLDv1 + GLDv2 clean and fine-tuned with 448x448 of GLDv2 clean, using arcface.\n## Local feature extraction\nI trained delg, delf with [tf delf](https://github.com/tensorflow/models/tree/master/research/delf) again, and further trained a PCA to diminish dimension of descriptors from 1024 -> 128. However, I couldn’t beat the delg model in the host baseline kernel. My best self-trained delg is worse 0.01 than baseline delg.\nSo for my final score, I chose the delg baseline model to extract local features.\n## Rescoring and reranking\nI defined score of reranking process as followed:\n```\nscore = global_score + local_score + recognition_score\n```\nDefinition of my own recognition score:\n```\nrecognition_score = max_value * (1-k/topk) ** alpha\n- recognition score is based on the arcface head of my model\n- max_value: max value of recognition score\n- k (< topk): rank of predicted label in sorted arcface head\n- topk: topk prediction of arcface, recognition_score > 0 if predicted label is in topk else 0\n- alpha < 1: giving a boost to small k (top1, top2 >> top 99, top 100)\n- My final submission: (max_value, topk, alpha) = (2, 200, 0.35)\n```\nI didn’t try many values of hyperparameters of my recognition_score, but it gave a 0.006 boost compared to the scoring scheme from the baseline kernel.\n## Result\n```\nBest single-model score: 0.5424 - 0.5233 (resnest200, fc 512)\nBest ensemble-model score: 0.5640 - 0.5354\n```\n## Not worked things\nHere are some ideas which did not work well:\n- Filter distractors by arcface head (if label not in top 200 -> non-landmark) it downgraded my score around 0.01\n- Online fine-tuning with private training set, downgraded my score around 0.02\n\nThat might be a little long for now :)). I will update this post if I remember something interesting. Thank you for reading my sharing!",
    "1033015": "Congrats on silver. Thanks for sharing @nejicool96",
    "1033018": "Thank you @vineeth1999  :))",
    "1033035": "Good job! Congrats on silver from HUST bro Khoa @nejicool96 :D",
    "1033038": "Wow :)), thank you @duykhanh99",
    "1033055": "Congrajulations!!! Thanks for sharing😊",
    "1033062": "Thank you :D",
    "1033157": "That's interesting 😍\nCongratulations @nejicool96 on your third silver medal 👍",
    "1033162": "Thank you, congrats your silver too :D",
    "1033528": "Nice approach! Congratulations to you and thanks for sharing this.",
    "1033544": "Thank you :)",
    "1037639": "Hi @nejicool96 . Can I call you : A landmark recognition expert :))",
    "1037645": "Thank you, but no, call me Khoa plz :))).",
    "1043763": "Congrats! Thanks for your sharing! Do you use any non-landmark filtering tricks for your final results?",
    "1043789": "Thank you. I tried to filter non-landmark by using the probabilities of arcface head (updated in my post), but it downgraded my score so I didn't use any filtering in my final results."
  },
  "source": "meta"
}