{
  "id": 335886,
  "title": "58th Solution",
  "content": "<h4>CV</h4>\n<ul>\n<li>Group shuffle split on POIs gave me very good correlation across folds and lb (almost identical at my score range)</li>\n<li>i used 60/40 split on POIs. But i limited the number of negative samples for training (2.8M neg + 500k positive).</li>\n<li>For memory efficiency, i did <code>tuple(sorted([id_1,id_2]))</code> so i only worked with unique pairs</li>\n</ul>\n<h4>Preprocessing</h4>\n<ul>\n<li>str.lower()</li>\n<li>map US states to abbreviations (california -&gt; ca)</li>\n<li>replace all city and states for SG to 'singapore'</li>\n</ul>\n<h4>Finding Pairs</h4>\n<p>used different geohash partitions to split data, then:</p>\n<ul>\n<li>tfidf (various combination of text cols) + agglomerative clustering to form clusters, then generate pairs from clusters</li>\n</ul>\n<p>knn using euclidean + haversine</p>\n<p>uuids pairs: find rows with exactly same values of combinations of text columns (e.g. same name and address)</p>\n<h4>Features</h4>\n<ul>\n<li>using neighbours' features gave me good increase in lb (e.g. include neighbour's distance of id_1 and id_2)</li>\n<li>expanded the idea to take distance features between neighbours of id_1 and neighbours of id_2 </li>\n<li>language detection using fasttext on names</li>\n<li>sbert embeddings and universal sentence encoder -&gt; dot product</li>\n<li>tfidf, lsa and hashing vectoriser -&gt; dot product</li>\n</ul>\n<h4>Model</h4>\n<ul>\n<li>Lgb, catboost, xgboost and 7 layered feed forward nn using category embeddings</li>\n</ul>\n<p>some parameters i found important:</p>\n<ul>\n<li><code>max_delta_step</code> for xgb and lgb when dealing with imbalance data helps make results more stable across experiments</li>\n<li><code>cat_features</code> are very good with catboost, but it makes the model size very large. tune <code>max_ctr_complexity</code> and <code>model_size_reg</code> to make inference less memory intensive.</li>\n</ul>\n<h4>Post-Processing</h4>\n<ol>\n<li>For id without matches, increase threshold slightly using <code>np.round(x,2)</code></li>\n<li>For given id, i took union of all matches that included the given id (e.g. made an inverted list of id-to-matches then take union)</li>\n<li>I check neighbour's matches then merge if IOU exceeded threshold (depending on length of original match)</li>\n<li>Lastly, i pruned pairs which has low predictions (&lt;=0.2)</li>\n</ol>\n<p>Edit: i did not use the leakage explicitly. Applied pairs matching on train/test separately </p>",
  "comments": [
    {
      "id": 1848078,
      "author_name": "",
      "author_url": "",
      "post_date": "2022-07-08T10:25:28.617000",
      "content": "",
      "votes": 0,
      "replies": []
    }
  ],
  "comment_count": 1,
  "messages": [
    {
      "id": 1848016,
      "postDate": "2022-07-08T09:57:09.290Z",
      "content": "<h4>CV</h4>\n<ul>\n<li>Group shuffle split on POIs gave me very good correlation across folds and lb (almost identical at my score range)</li>\n<li>i used 60/40 split on POIs. But i limited the number of negative samples for training (2.8M neg + 500k positive).</li>\n<li>For memory efficiency, i did <code>tuple(sorted([id_1,id_2]))</code> so i only worked with unique pairs</li>\n</ul>\n<h4>Preprocessing</h4>\n<ul>\n<li>str.lower()</li>\n<li>map US states to abbreviations (california -&gt; ca)</li>\n<li>replace all city and states for SG to 'singapore'</li>\n</ul>\n<h4>Finding Pairs</h4>\n<p>used different geohash partitions to split data, then:</p>\n<ul>\n<li>tfidf (various combination of text cols) + agglomerative clustering to form clusters, then generate pairs from clusters</li>\n</ul>\n<p>knn using euclidean + haversine</p>\n<p>uuids pairs: find rows with exactly same values of combinations of text columns (e.g. same name and address)</p>\n<h4>Features</h4>\n<ul>\n<li>using neighbours' features gave me good increase in lb (e.g. include neighbour's distance of id_1 and id_2)</li>\n<li>expanded the idea to take distance features between neighbours of id_1 and neighbours of id_2 </li>\n<li>language detection using fasttext on names</li>\n<li>sbert embeddings and universal sentence encoder -&gt; dot product</li>\n<li>tfidf, lsa and hashing vectoriser -&gt; dot product</li>\n</ul>\n<h4>Model</h4>\n<ul>\n<li>Lgb, catboost, xgboost and 7 layered feed forward nn using category embeddings</li>\n</ul>\n<p>some parameters i found important:</p>\n<ul>\n<li><code>max_delta_step</code> for xgb and lgb when dealing with imbalance data helps make results more stable across experiments</li>\n<li><code>cat_features</code> are very good with catboost, but it makes the model size very large. tune <code>max_ctr_complexity</code> and <code>model_size_reg</code> to make inference less memory intensive.</li>\n</ul>\n<h4>Post-Processing</h4>\n<ol>\n<li>For id without matches, increase threshold slightly using <code>np.round(x,2)</code></li>\n<li>For given id, i took union of all matches that included the given id (e.g. made an inverted list of id-to-matches then take union)</li>\n<li>I check neighbour's matches then merge if IOU exceeded threshold (depending on length of original match)</li>\n<li>Lastly, i pruned pairs which has low predictions (&lt;=0.2)</li>\n</ol>\n<p>Edit: i did not use the leakage explicitly. Applied pairs matching on train/test separately </p>",
      "rawMarkdown": "#### CV\n\n- Group shuffle split on POIs gave me very good correlation across folds and lb (almost identical at my score range)\n- i used 60/40 split on POIs. But i limited the number of negative samples for training (2.8M neg + 500k positive).\n- For memory efficiency, i did `tuple(sorted([id_1,id_2]))` so i only worked with unique pairs\n\n#### Preprocessing\n- str.lower()\n- map US states to abbreviations (california -> ca)\n- replace all city and states for SG to 'singapore'\n\n#### Finding Pairs\nused different geohash partitions to split data, then:\n- tfidf (various combination of text cols) + agglomerative clustering to form clusters, then generate pairs from clusters\n\nknn using euclidean + haversine\n\nuuids pairs: find rows with exactly same values of combinations of text columns (e.g. same name and address)\n\n#### Features\n- using neighbours' features gave me good increase in lb (e.g. include neighbour's distance of id_1 and id_2)\n- expanded the idea to take distance features between neighbours of id_1 and neighbours of id_2 \n- language detection using fasttext on names\n- sbert embeddings and universal sentence encoder -> dot product\n- tfidf, lsa and hashing vectoriser -> dot product\n\n#### Model\n- Lgb, catboost, xgboost and 7 layered feed forward nn using category embeddings\n\nsome parameters i found important:\n- `max_delta_step` for xgb and lgb when dealing with imbalance data helps make results more stable across experiments\n- `cat_features` are very good with catboost, but it makes the model size very large. tune `max_ctr_complexity` and `model_size_reg` to make inference less memory intensive.\n\n#### Post-Processing\n1. For id without matches, increase threshold slightly using `np.round(x,2)`\n2. For given id, i took union of all matches that included the given id (e.g. made an inverted list of id-to-matches then take union)\n3. I check neighbour's matches then merge if IOU exceeded threshold (depending on length of original match)\n4. Lastly, i pruned pairs which has low predictions (<=0.2)\n\n\nEdit: i did not use the leakage explicitly. Applied pairs matching on train/test separately ",
      "votes": 5
    },
    {
      "id": 1848078,
      "postDate": "2022-07-08T10:25:28.617Z",
      "rawMarkdown": "",
      "isDeleted": true
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-23T05:23:39Z",
  "competition_id": 35476,
  "competition_slug": "foursquare-location-matching",
  "team_id": 8574202,
  "solution_url": "/competitions/foursquare-location-matching/writeups/gerwyn-ng-58th-solution"
}