{
  "id": 508297,
  "title": "2nd Place Solution for the CSC532 Fruits Categorical Classification 2024 Competition",
  "url": "/competitions/csc532-fruits-categorical-classification-2024/discussion/508297",
  "author_name": "KM Kyaw",
  "post_date": "2024-05-29T05:05:56.281000",
  "votes": 2,
  "comment_count": 0,
  "views": 0,
  "content": "<h1>Introduction</h1>\n<p>First of all, I would like to thank the competition-host for hosting this competition along with CSC532 course. It really helped us to apply the concepts that we learned from the class. This competition is to classify \"fresh\" vs \"rotten\" apples, bananas, and oranges. It looks like an elementary competition but the huge variation of data between training set and test set makes the competition challenging.</p>\n<h1>Overview of the Approach</h1>\n<p>I implemented a two-stage ensemble approach. As the name suggests, each image has to go through two stages of classification. Given an image,</p>\n<ol>\n<li>Classify whether it is Apple or Banana or Orange</li>\n<li>Classify whether it is Rotten or Fresh</li>\n</ol>\n<p>I used an ensemble of models for both classification stages. The ensemble includes:</p>\n<ul>\n<li>MobileNetV2</li>\n<li>InceptionV3</li>\n<li>Xception</li>\n<li>InceptionV3</li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Fdfbdefbc6475d677cfab35b44622956e%2FScreenshot%202024-05-28%20at%2010.33.30AM.png?generation=1716953768681219&amp;alt=media\" alt=\"Ensemble Model\"></p>\n<h1>Data Augmentation for Training</h1>\n<p>I applied the following augmentation to all fruits:</p>\n<ul>\n<li>horizontal flip</li>\n<li>vertical flip</li>\n<li>samplewise center</li>\n<li>zoom </li>\n<li>width shift</li>\n<li>height shift</li>\n<li>rotation </li>\n</ul>\n<p>Apples are the most challenging because of the variations in color due the type (Gala, Granny Smith, Delicious Red, etc). Among all apples, most of my models tend to misclassify fresh Gala apples as rotten ones due to its texture. Therefore, I set epochs to 25 for apples (10 for other fruits) and added Gaussian noise to apples using the following function:</p>\n<pre><code> ():\n    row, col, ch = img.shape\n    mean = \n    var = \n    sigma = var ** \n    gauss = np.random.normal(mean, sigma, (row, col, ch))\n    gauss = gauss.reshape(row, col, ch)\n    noisy = img + gauss\n     noisy\n</code></pre>\n<h1>Pre-Processing for Submission</h1>\n<p>All of the images for submission go through background remover as pre-processing step to remove the noisy background. This is because of the difference between training and validation(submission) sets. The training images are sharp and clean, while the validation images are crowd-sourced images as mentioned in the competition data description.</p>\n<blockquote>\n  <p>The validation data was mostly crowdsourced from the participants of the DLAI5 hackathon.</p>\n</blockquote>\n<p>First I used self-defined YOLO-based function to remove the background for submission images (special thanks to Khine Eaindray Htun for the amazing idea <a href=\"https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning)\" target=\"_blank\">https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning)</a>. However, self-defined function tends to remove the whole fruit in some cases as I discussed earlier in <a href=\"https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413\" target=\"_blank\">https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413</a>. Therefore, I used an alternative way to do so by using rembg library. Based on my observations, it is safer to use rembg as it rarely misclassifies and removes the fruit. </p>\n<h1>Final submissions</h1>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Private Score</th>\n<th>Public Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Two-stage model without Gaussian noise in Apples</td>\n<td>0.77402</td>\n<td><strong>0.64384</strong></td>\n</tr>\n<tr>\n<td>Two-stage model with Gaussian noise in Apples</td>\n<td><strong>0.80527</strong></td>\n<td>0.59920</td>\n</tr>\n</tbody>\n</table>\n<p><br><br>\nI believed in leaderboard overfitting (based on my Kaggler's instinct) and therefore, I didn't rely on public score a lot. As expected, a huge shakeup happened once the private score were released. <br>\nOne of my non-final submissions could make me get the 1st place. However, I didn't select it as I lost track of its notebook. </p>\n<blockquote>\n  <p>Lesson learned : Always keep everything documented. </p>\n</blockquote>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Ffd52eb88362a7bc8e057cdfc68d5890a%2FScreenshot%202024-05-29%20at%209.57.11AM.png?generation=1716955205753689&amp;alt=media\"></p>\n<h1>Conclusion</h1>\n<p>The two-stage ensemble model proved to be effective, especially when Gaussian noise was added to the training images of apples to address their variability. The data augmentation techniques and pre-processing steps were crucial in improving the model's performance and generalization.<br>\nOverall, the competition was a great learning experience, enhancing my understanding of ensemble learning, pre-processing and data augmentation. </p>\n<p>I've shared my two-stage model inference here :<br>\n<a href=\"https://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference\" target=\"_blank\">https://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference</a></p>",
  "messages": [
    {
      "id": 2842435,
      "postDate": "2024-05-29T05:05:56.280Z",
      "content": "<h1>Introduction</h1>\n<p>First of all, I would like to thank the competition-host for hosting this competition along with CSC532 course. It really helped us to apply the concepts that we learned from the class. This competition is to classify \"fresh\" vs \"rotten\" apples, bananas, and oranges. It looks like an elementary competition but the huge variation of data between training set and test set makes the competition challenging.</p>\n<h1>Overview of the Approach</h1>\n<p>I implemented a two-stage ensemble approach. As the name suggests, each image has to go through two stages of classification. Given an image,</p>\n<ol>\n<li>Classify whether it is Apple or Banana or Orange</li>\n<li>Classify whether it is Rotten or Fresh</li>\n</ol>\n<p>I used an ensemble of models for both classification stages. The ensemble includes:</p>\n<ul>\n<li>MobileNetV2</li>\n<li>InceptionV3</li>\n<li>Xception</li>\n<li>InceptionV3</li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Fdfbdefbc6475d677cfab35b44622956e%2FScreenshot%202024-05-28%20at%2010.33.30AM.png?generation=1716953768681219&amp;alt=media\" alt=\"Ensemble Model\"></p>\n<h1>Data Augmentation for Training</h1>\n<p>I applied the following augmentation to all fruits:</p>\n<ul>\n<li>horizontal flip</li>\n<li>vertical flip</li>\n<li>samplewise center</li>\n<li>zoom </li>\n<li>width shift</li>\n<li>height shift</li>\n<li>rotation </li>\n</ul>\n<p>Apples are the most challenging because of the variations in color due the type (Gala, Granny Smith, Delicious Red, etc). Among all apples, most of my models tend to misclassify fresh Gala apples as rotten ones due to its texture. Therefore, I set epochs to 25 for apples (10 for other fruits) and added Gaussian noise to apples using the following function:</p>\n<pre><code> ():\n    row, col, ch = img.shape\n    mean = \n    var = \n    sigma = var ** \n    gauss = np.random.normal(mean, sigma, (row, col, ch))\n    gauss = gauss.reshape(row, col, ch)\n    noisy = img + gauss\n     noisy\n</code></pre>\n<h1>Pre-Processing for Submission</h1>\n<p>All of the images for submission go through background remover as pre-processing step to remove the noisy background. This is because of the difference between training and validation(submission) sets. The training images are sharp and clean, while the validation images are crowd-sourced images as mentioned in the competition data description.</p>\n<blockquote>\n  <p>The validation data was mostly crowdsourced from the participants of the DLAI5 hackathon.</p>\n</blockquote>\n<p>First I used self-defined YOLO-based function to remove the background for submission images (special thanks to Khine Eaindray Htun for the amazing idea <a href=\"https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning)\" target=\"_blank\">https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning)</a>. However, self-defined function tends to remove the whole fruit in some cases as I discussed earlier in <a href=\"https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413\" target=\"_blank\">https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413</a>. Therefore, I used an alternative way to do so by using rembg library. Based on my observations, it is safer to use rembg as it rarely misclassifies and removes the fruit. </p>\n<h1>Final submissions</h1>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Private Score</th>\n<th>Public Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Two-stage model without Gaussian noise in Apples</td>\n<td>0.77402</td>\n<td><strong>0.64384</strong></td>\n</tr>\n<tr>\n<td>Two-stage model with Gaussian noise in Apples</td>\n<td><strong>0.80527</strong></td>\n<td>0.59920</td>\n</tr>\n</tbody>\n</table>\n<p><br><br>\nI believed in leaderboard overfitting (based on my Kaggler's instinct) and therefore, I didn't rely on public score a lot. As expected, a huge shakeup happened once the private score were released. <br>\nOne of my non-final submissions could make me get the 1st place. However, I didn't select it as I lost track of its notebook. </p>\n<blockquote>\n  <p>Lesson learned : Always keep everything documented. </p>\n</blockquote>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Ffd52eb88362a7bc8e057cdfc68d5890a%2FScreenshot%202024-05-29%20at%209.57.11AM.png?generation=1716955205753689&amp;alt=media\"></p>\n<h1>Conclusion</h1>\n<p>The two-stage ensemble model proved to be effective, especially when Gaussian noise was added to the training images of apples to address their variability. The data augmentation techniques and pre-processing steps were crucial in improving the model's performance and generalization.<br>\nOverall, the competition was a great learning experience, enhancing my understanding of ensemble learning, pre-processing and data augmentation. </p>\n<p>I've shared my two-stage model inference here :<br>\n<a href=\"https://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference\" target=\"_blank\">https://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference</a></p>",
      "rawMarkdown": "# Introduction\nFirst of all, I would like to thank the competition-host for hosting this competition along with CSC532 course. It really helped us to apply the concepts that we learned from the class. This competition is to classify \"fresh\" vs \"rotten\" apples, bananas, and oranges. It looks like an elementary competition but the huge variation of data between training set and test set makes the competition challenging.\n\n# Overview of the Approach\nI implemented a two-stage ensemble approach. As the name suggests, each image has to go through two stages of classification. Given an image,\n1. Classify whether it is Apple or Banana or Orange\n2. Classify whether it is Rotten or Fresh\n\nI used an ensemble of models for both classification stages. The ensemble includes:\n- MobileNetV2\n- InceptionV3\n- Xception\n- InceptionV3\n\n![Ensemble Model](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Fdfbdefbc6475d677cfab35b44622956e%2FScreenshot%202024-05-28%20at%2010.33.30AM.png?generation=1716953768681219&alt=media)\n\n# Data Augmentation for Training\nI applied the following augmentation to all fruits:\n- horizontal flip\n- vertical flip\n- samplewise center\n- zoom \n- width shift\n- height shift\n- rotation \n\nApples are the most challenging because of the variations in color due the type (Gala, Granny Smith, Delicious Red, etc). Among all apples, most of my models tend to misclassify fresh Gala apples as rotten ones due to its texture. Therefore, I set epochs to 25 for apples (10 for other fruits) and added Gaussian noise to apples using the following function:\n\n```python\ndef add_gaussian_noise(img):\n    row, col, ch = img.shape\n    mean = 0\n    var = 0.1\n    sigma = var ** 0.5\n    gauss = np.random.normal(mean, sigma, (row, col, ch))\n    gauss = gauss.reshape(row, col, ch)\n    noisy = img + gauss\n    return noisy\n```\n# Pre-Processing for Submission\nAll of the images for submission go through background remover as pre-processing step to remove the noisy background. This is because of the difference between training and validation(submission) sets. The training images are sharp and clean, while the validation images are crowd-sourced images as mentioned in the competition data description.\n\n>The validation data was mostly crowdsourced from the participants of the DLAI5 hackathon.\n\nFirst I used self-defined YOLO-based function to remove the background for submission images (special thanks to Khine Eaindray Htun for the amazing idea https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning). However, self-defined function tends to remove the whole fruit in some cases as I discussed earlier in https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413. Therefore, I used an alternative way to do so by using rembg library. Based on my observations, it is safer to use rembg as it rarely misclassifies and removes the fruit. \n\n# Final submissions\n| Model | Private Score | Public Score |\n| --- | --- | --- |\n| Two-stage model without Gaussian noise in Apples | 0.77402 | **0.64384** |\n| Two-stage model with Gaussian noise in Apples | **0.80527** | 0.59920|\n\n</br>\nI believed in leaderboard overfitting (based on my Kaggler's instinct) and therefore, I didn't rely on public score a lot. As expected, a huge shakeup happened once the private score were released. \nOne of my non-final submissions could make me get the 1st place. However, I didn't select it as I lost track of its notebook. \n>Lesson learned : Always keep everything documented. \n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Ffd52eb88362a7bc8e057cdfc68d5890a%2FScreenshot%202024-05-29%20at%209.57.11AM.png?generation=1716955205753689&alt=media)\n\n# Conclusion\nThe two-stage ensemble model proved to be effective, especially when Gaussian noise was added to the training images of apples to address their variability. The data augmentation techniques and pre-processing steps were crucial in improving the model's performance and generalization.\nOverall, the competition was a great learning experience, enhancing my understanding of ensemble learning, pre-processing and data augmentation. \n\nI've shared my two-stage model inference here :\nhttps://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference",
      "votes": 2
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "2842435": "# Introduction\nFirst of all, I would like to thank the competition-host for hosting this competition along with CSC532 course. It really helped us to apply the concepts that we learned from the class. This competition is to classify \"fresh\" vs \"rotten\" apples, bananas, and oranges. It looks like an elementary competition but the huge variation of data between training set and test set makes the competition challenging.\n\n# Overview of the Approach\nI implemented a two-stage ensemble approach. As the name suggests, each image has to go through two stages of classification. Given an image,\n1. Classify whether it is Apple or Banana or Orange\n2. Classify whether it is Rotten or Fresh\n\nI used an ensemble of models for both classification stages. The ensemble includes:\n- MobileNetV2\n- InceptionV3\n- Xception\n- InceptionV3\n\n![Ensemble Model](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Fdfbdefbc6475d677cfab35b44622956e%2FScreenshot%202024-05-28%20at%2010.33.30AM.png?generation=1716953768681219&alt=media)\n\n# Data Augmentation for Training\nI applied the following augmentation to all fruits:\n- horizontal flip\n- vertical flip\n- samplewise center\n- zoom \n- width shift\n- height shift\n- rotation \n\nApples are the most challenging because of the variations in color due the type (Gala, Granny Smith, Delicious Red, etc). Among all apples, most of my models tend to misclassify fresh Gala apples as rotten ones due to its texture. Therefore, I set epochs to 25 for apples (10 for other fruits) and added Gaussian noise to apples using the following function:\n\n```python\ndef add_gaussian_noise(img):\n    row, col, ch = img.shape\n    mean = 0\n    var = 0.1\n    sigma = var ** 0.5\n    gauss = np.random.normal(mean, sigma, (row, col, ch))\n    gauss = gauss.reshape(row, col, ch)\n    noisy = img + gauss\n    return noisy\n```\n# Pre-Processing for Submission\nAll of the images for submission go through background remover as pre-processing step to remove the noisy background. This is because of the difference between training and validation(submission) sets. The training images are sharp and clean, while the validation images are crowd-sourced images as mentioned in the competition data description.\n\n>The validation data was mostly crowdsourced from the participants of the DLAI5 hackathon.\n\nFirst I used self-defined YOLO-based function to remove the background for submission images (special thanks to Khine Eaindray Htun for the amazing idea https://www.kaggle.com/code/khineaindrayhtun/segmentation-assisted-transfer-learning). However, self-defined function tends to remove the whole fruit in some cases as I discussed earlier in https://www.kaggle.com/competitions/csc532-fruits-categorical-classification-2024/discussion/483413. Therefore, I used an alternative way to do so by using rembg library. Based on my observations, it is safer to use rembg as it rarely misclassifies and removes the fruit. \n\n# Final submissions\n| Model | Private Score | Public Score |\n| --- | --- | --- |\n| Two-stage model without Gaussian noise in Apples | 0.77402 | **0.64384** |\n| Two-stage model with Gaussian noise in Apples | **0.80527** | 0.59920|\n\n</br>\nI believed in leaderboard overfitting (based on my Kaggler's instinct) and therefore, I didn't rely on public score a lot. As expected, a huge shakeup happened once the private score were released. \nOne of my non-final submissions could make me get the 1st place. However, I didn't select it as I lost track of its notebook. \n>Lesson learned : Always keep everything documented. \n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F5080265%2Ffd52eb88362a7bc8e057cdfc68d5890a%2FScreenshot%202024-05-29%20at%209.57.11AM.png?generation=1716955205753689&alt=media)\n\n# Conclusion\nThe two-stage ensemble model proved to be effective, especially when Gaussian noise was added to the training images of apples to address their variability. The data augmentation techniques and pre-processing steps were crucial in improving the model's performance and generalization.\nOverall, the competition was a great learning experience, enhancing my understanding of ensemble learning, pre-processing and data augmentation. \n\nI've shared my two-stage model inference here :\nhttps://www.kaggle.com/code/kaungmyatkyaw/2-stage-ensemble-inference"
  }
}