{
  "topic": {
    "id": 199657,
    "title": "4th place solution: Ensemble with GMM",
    "authorName": "corochann",
    "commentCount": 26,
    "votes": 58,
    "postDate": "2020-11-26T16:55:14.362000"
  },
  "comments": [
    {
      "id": 1106968,
      "authorName": "corochann",
      "votes": 5,
      "postDate": "2020-12-09T09:04:51.770000",
      "content": "<p>We have published our code:<br>\n<a href=\"https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution\" target=\"_blank\">https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution</a></p>"
    },
    {
      "id": 1107307,
      "authorName": "Heroseo",
      "votes": 1,
      "postDate": "2020-12-09T15:24:16.500000",
      "content": "<p>Great job.<br>\nThanks for sharing!</p>\n<p><a href=\"https://www.kaggle.com/corochann\" target=\"_blank\">@corochann</a> </p>"
    },
    {
      "id": 1107782,
      "authorName": "corochann",
      "votes": 1,
      "postDate": "2020-12-10T00:32:09.503000",
      "content": "<p>Thanks, please check/try our ensemble code :)</p>\n<ul>\n<li><a href=\"https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution/tree/master/src/ensemble\" target=\"_blank\">https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution/tree/master/src/ensemble</a></li>\n</ul>"
    },
    {
      "id": 1107795,
      "authorName": "Dean Kang",
      "votes": 1,
      "postDate": "2020-12-10T01:03:26.083000",
      "content": "<p>Awesome! thank you! 👍</p>"
    },
    {
      "id": 1107809,
      "authorName": "corochann",
      "votes": 2,
      "postDate": "2020-12-10T01:26:49.637000",
      "content": "<p>😃</p>\n<p>You can find various trial implementations of our rasterizer too: (numba jit tuned version of rasterizer etc)</p>\n<ul>\n<li><a href=\"https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution/tree/master/src/lib/rasterization\" target=\"_blank\">https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution/tree/master/src/lib/rasterization</a></li>\n</ul>"
    },
    {
      "id": 1096004,
      "authorName": "corochann",
      "votes": 6,
      "postDate": "2020-11-30T06:27:25.403000",
      "content": "<h1>What we tried and not worked</h1>\n<p>Sorry for the late post, these are some of the items that we tried but not worked.</p>\n<h2>Change hyper parameters</h2>\n<p>We tried several hyper parameters, especially for rasterizers. But none of them contributed to improve the model's accuracy.</p>\n<ul>\n<li><p>image size</p>\n<ul>\n<li>We tried 224x224 &amp; 128x128. The image size=128 training is faster especially because Rasterization becomes faster, and its training accuracy is almost the same until the middle of the training. However, its validation loss is a bit (only about 0.5~1.0) worse than image size = 224.</li></ul></li>\n<li><p>pixel_size</p>\n<ul>\n<li>There are many frames that the car is almost stopping now but starts in the near future. We thought that when the car starts moving, its change in the pixel is very small and CNN cannot detect it when the pixel_size is bit (resolution is rough). We tried to change <code>pixel_size</code> from default 0.5 into 0.25 or 0.15 but the accuracy becomes worse.</li></ul></li>\n<li><p>num_history</p>\n<ul>\n<li>1. Only short history predictor: Several agents have very few past history. So I thought when we train the model with only 0 past frames (i.e., input only current frame), this specific purpose model performs better for predicting the future with only 0 past frames. In the training phase, <strong>we can train this model using the agents with many past frames, by just input only a current frame.</strong> However, this model’s accuracy is worse than the default 10 history input model.</li>\n<li>2. Long history predictor: Oppositely, having more past information helps to improve the score? To check that hypothesis, we tried to input longer past history frames by setting <code>history_num_frames=7, 10</code> with <code>history_step_size=2</code> instead of default <code>history_num_frames=10</code> with <code>history_step_size=1</code>. This model’s accuracy was lower than the original model even if we only chose the validation input to have more than 20 history frames.</li></ul></li>\n</ul>\n<h2>Big, deep models</h2>\n<p>We tried <code>resnet101</code> &amp; <code>res152</code> too, but they did not work well.</p>\n<h2>Custom Rasterizer</h2>\n<p>We tried implementing our own rasterizer to add more rich information to CNN input, but all of them did not work well to improve the accuracy somehow…</p>\n<ul>\n<li><code>ChannelSemanticRasterizer</code><ul>\n<li><code>SemanticRasterizer</code> draws the semantic in RGB space, using 3 channels. We thought this is not always optimal for CNN input and tried to input 6 channels with 1. road, 2. default lane, 3. green signal lane, 4. yellow signal lane, 5. red signal lane, 6. crosswalk.</li></ul></li>\n<li><code>TLSemanticRasterizer</code>:<ul>\n<li>When we executed EDA, we thought knowing <strong>the red signal length is important</strong>. Because some frames start with the red signal as current, and start in the future when the signal changed to green.<br>\nWe input a signal length by changing the color value so that CNN can understand how long this signal color already continued (since Host car detected the signal).</li></ul></li>\n<li><code>AgentTypeBoxRasterizer</code>:<ul>\n<li>There are 4 agent types: CAR, CYCLIST, PEDESTRIAN and UNKNOWN in the original dataset. But UNKNOWN is not drawn in the original <code>BoxRasterizer</code>. Also agent type information is also dropped when drawing boxes.<br>\nWe tried to draw each agent type in different channels including UNKNOWN, to input more precise information. </li></ul></li>\n</ul>\n<p><strong>Speed up rasterizer</strong><br>\nUse numpy batch operation as much as possible, and replacing implementations  with numba jit computations. Even though it becomes faster in single process, its computation speed-up does not contribute so much for multi-process data preparation during training.</p>\n<h2>Train with Agent type</h2>\n<p>Other than trying the <code>AgentTypeBoxRasterizer</code>, we tried inputting agent type one-hot vector explicitly, but it did not contribute to improve accuracy too.</p>\n<h2>Multi-agent prediction model</h2>\n<p>The baseline kernel predicts future movement of only target agent. Instead I considered to build a model which predicts all the agent's future movement within the input image.<br>\nThe first I thought this idea speed-ups the training since it can predict multiple agent at once. However sometimes the host car detects agent with very far place, like 400 pixels far away. So we noticed it is difficult to align the image size to fixed size. And we suspended its further trial.</p>\n<h2>Yaw correction</h2>\n<p>The below figure shows the biggest error in the validation dataset. The error is extremely high when the <code>yaw</code> in the dataset was actually opposite and the model predicted the opposite way to go.<br>\nWe worked hard to check if the test dataset contains this kind of case. Indeed there seems to be some frames whose <code>yaw</code> might be opposite, however most of the time the agent is stopping in this case in the test dataset. Even though we fixed the yaw, the LB score was almost unchanged.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F518134%2Fe51c936752b5cd7bd0689f6ef9faebe9%2Fvalidation_worst_error.png?generation=1606717208803896&amp;alt=media\" alt=\"\"><br>\nThe biggest error in the validation dataset with error=43988.1 !!</p>\n<h2>Leak check</h2>\n<p>When we checked the dataset carefully, we noticed that the timestamp &amp; the map position actually overlaps within the train/validation/test dataset.<br>\nWe checked if the test dataset information was leaked from another dataset. But it seems that the timestamp is not aligned in scenes (maybe physically other host car is used to collect data, and timestamp record is not calibrated).</p>"
    },
    {
      "id": 1099404,
      "authorName": "Louis Yang",
      "votes": 1,
      "postDate": "2020-12-02T10:42:04.313000",
      "content": "<p>Thanks for sharing! I think this clear list of things that don't work is way more important than those that work! <br>\nFor Lyft, I think they might want to check the \"Yaw correction\" part. Predicting a car to move in a completely opposite direction will probably be a fatal mistake in real life. Even if it only happen once.</p>"
    },
    {
      "id": 1099529,
      "authorName": "corochann",
      "votes": 1,
      "postDate": "2020-12-02T12:30:39.103000",
      "content": "<p>Thanks for reply <a href=\"https://www.kaggle.com/louis925\" target=\"_blank\">@louis925</a>, yeah I think so too. For considering application, this \"what did not work\" is more important to consider further why.</p>\n<p>Actually \"Yaw correction\" happened many times, and I guess to correct it we need better accuracy for the previous object detection NN part where I guess this module will decide the yaw direction.<br>\nWhile the pedestrian &amp; cyclist they are more easier to decide direction from real image and indeed there is less mistake for yaw, but car is just \"box\" shape, determining its direction from image sometimes has mistake.</p>"
    },
    {
      "id": 1092920,
      "authorName": "Dean Kang",
      "votes": 3,
      "postDate": "2020-11-27T09:40:26.947000",
      "content": "<p>Thank you so much for sharing. Just curious, did you use GCP or a local machine for training? Using v100 in GCP seems quite expansive.</p>"
    },
    {
      "id": 1092923,
      "authorName": "corochann",
      "votes": 3,
      "postDate": "2020-11-27T09:44:30.027000",
      "content": "<p>We used local machine :)</p>"
    },
    {
      "id": 1092700,
      "authorName": "Dieter",
      "votes": 3,
      "postDate": "2020-11-27T05:12:27.447000",
      "content": "<p>Great write-up, thanks for sharing. I like your GMM ensembling.</p>"
    },
    {
      "id": 1092755,
      "authorName": "corochann",
      "votes": 0,
      "postDate": "2020-11-27T06:22:29.687000",
      "content": "<p>Thank you <a href=\"https://www.kaggle.com/christofhenkel\" target=\"_blank\">@christofhenkel</a> for comment. I'm looking forward to see your team's solution.</p>\n<p>I saw that your team used stacking. I also wonder if your team applied GMM ensembling, the score has increased further or not!</p>"
    },
    {
      "id": 1092894,
      "authorName": "Dieter",
      "votes": 1,
      "postDate": "2020-11-27T08:52:44.610000",
      "content": "<p>thats what I am also wondering. Might give it a try today. Thanks for posting the code </p>"
    },
    {
      "id": 1092309,
      "authorName": "Heroseo",
      "votes": 3,
      "postDate": "2020-11-26T17:28:17.537000",
      "content": "<p>Thanks for sharing and well explanation.<br>\nI totally agree with you!<br>\n<a href=\"https://www.kaggle.com/corochann/lyft-training-with-multi-mode-confidence\" target=\"_blank\">Lyft: Training with multi-mode confidence</a> is really strong baseline.</p>\n<p>And Congrats 4th <a href=\"https://www.kaggle.com/corochann\" target=\"_blank\">@corochann</a> and <a href=\"https://www.kaggle.com/zaburo\" target=\"_blank\">@zaburo</a>, <a href=\"https://www.kaggle.com/qhapaq49\" target=\"_blank\">@qhapaq49</a>, <a href=\"https://www.kaggle.com/charmq\" target=\"_blank\">@charmq</a>.</p>"
    },
    {
      "id": 1092326,
      "authorName": "corochann",
      "votes": 0,
      "postDate": "2020-11-26T17:42:01.813000",
      "content": "<p>Thank you! Glad to know that :) <a href=\"https://www.kaggle.com/piantic\" target=\"_blank\">@piantic</a> </p>"
    },
    {
      "id": 1098852,
      "authorName": "YaGana Sheriff-Hussaini",
      "votes": 1,
      "postDate": "2020-12-01T22:38:03.257000",
      "content": "<p>Congrats <a href=\"https://www.kaggle.com/corochann\" target=\"_blank\">@corochann</a> and team. Thanks for sharing your solution.</p>"
    },
    {
      "id": 1098932,
      "authorName": "corochann",
      "votes": 1,
      "postDate": "2020-12-02T00:33:12.727000",
      "content": "<p>Thanks, congrats <a href=\"https://www.kaggle.com/sheriytm\" target=\"_blank\">@sheriytm</a> too!</p>"
    },
    {
      "id": 1092767,
      "authorName": "hengck23",
      "votes": 1,
      "postDate": "2020-11-27T06:37:08.903000",
      "content": "<p>good work and thanks for the writeup!</p>\n<p>\"so we also tried implementing own GMM model with fixing covariance to be 1.\"<br>\ndo you have some code or pseudo-code for that? i would like to implement and try.<br>\nthanks</p>"
    },
    {
      "id": 1092801,
      "authorName": "corochann",
      "votes": 6,
      "postDate": "2020-11-27T07:17:34.680000",
      "content": "<p><a href=\"https://www.kaggle.com/hengck23\" target=\"_blank\">@hengck23</a> <br>\nThanks for your comment.<br>\nWe used this code, usage is same with sklearn's GMM.</p>\n<pre><code>import numba as nb\nimport numpy as np\nfrom sklearn.mixture import GaussianMixture\n# from sklearn.mixture._gaussian_mixture import _estimate_gaussian_parameters\n\n\n@nb.jit(nb.types.Tuple(\n    (nb.float64[:], nb.float64[:, :])\n)(nb.float64[:, :], nb.float64[:, :]), nopython=True, nogil=True)\ndef _estimate_gaussian_parameters(X, resp):\n    nk = resp.sum(axis=0) + 10 * np.finfo(resp.dtype).eps\n    means = np.dot(np.ascontiguousarray(resp.T), X) / np.ascontiguousarray(np.expand_dims(nk, 1))\n    return nk, means\n\n\nclass GaussianMixtureIdentity(GaussianMixture):\n    def _initialize(self, X, resp):\n        n_samples, _ = X.shape\n        self.covariances_ = np.zeros(self.n_components)+1.0\n        self.precisions_cholesky_ = np.zeros(self.n_components)+1.0\n        weights, means = _estimate_gaussian_parameters(X, resp)\n        weights /= n_samples\n\n        self.weights_ = (weights if self.weights_init is None\n                         else self.weights_init)\n        self.means_ = means if self.means_init is None else self.means_init\n\n    def _m_step(self, X, log_resp):\n        n_samples, _ = X.shape\n        self.covariances_ = np.zeros(self.n_components)+1.0\n        self.precisions_cholesky_ = np.zeros(self.n_components)+1.0\n        self.weights_, self.means_ = _estimate_gaussian_parameters(X, np.exp(log_resp))\n        self.weights_ /= n_samples\n</code></pre>"
    },
    {
      "id": 1092471,
      "authorName": "Louis Yang",
      "votes": 1,
      "postDate": "2020-11-26T21:02:18.263000",
      "content": "<p>Congrats! Wow! You set <code>min_history=0</code>! Very interesting idea! Does that increase the amount samples in AgentDataset by a lot?</p>"
    },
    {
      "id": 1092600,
      "authorName": "corochann",
      "votes": 1,
      "postDate": "2020-11-27T02:50:32.563000",
      "content": "<p>Yes, the dataset becomes <code>191,177,863</code> -&gt; <code>198,474,478</code>.</p>\n<p>I guess <code>min_frame_history=0</code> increases the number, while <code>min_frame_history=10</code> reduces the number.</p>"
    },
    {
      "id": 1092322,
      "authorName": "nosound",
      "votes": 1,
      "postDate": "2020-11-26T17:34:31.200000",
      "content": "<p>Congrats! What hardware have you used to run such a massive experiment? I have trained my models for days and only covered 34M samples, and you did 191M. How many cores have you used, what was the bottleneck? Quite impressive!</p>"
    },
    {
      "id": 1092328,
      "authorName": "corochann",
      "votes": 3,
      "postDate": "2020-11-26T17:45:17.960000",
      "content": "<p>Thank you and congrats to you too! <a href=\"https://www.kaggle.com/zaharch\" target=\"_blank\">@zaharch</a> </p>\n<p>We used 8 V100 GPUs for single model training with about 32 cpu cores.<br>\nI think disk IO and rasterization process was the bottleneck compared to the normal image training.</p>"
    },
    {
      "id": 1094891,
      "authorName": "corochann",
      "votes": 0,
      "postDate": "2020-11-29T04:11:44.587000",
      "content": "<p>Thanks! <a href=\"https://www.kaggle.com/prokaggler\" target=\"_blank\">@prokaggler</a> </p>"
    },
    {
      "id": 1102591,
      "authorName": "",
      "votes": 1,
      "postDate": "2020-12-05T05:04:27.047000",
      "content": "<p>I love this post!</p>"
    },
    {
      "id": 1103475,
      "authorName": "corochann",
      "votes": 0,
      "postDate": "2020-12-05T23:56:34.103000",
      "content": "<p>Thanks <a href=\"https://www.kaggle.com/YoungseokJoung\" target=\"_blank\">@YoungseokJoung</a> !</p>"
    }
  ],
  "index": {
    "id": "199657",
    "title": "4th place solution: Ensemble with GMM",
    "authorName": "corochann",
    "commentCount": "26",
    "votes": "58",
    "postDate": "2020-12-09 09:06:03.400000"
  }
}