{
  "id": 418323,
  "title": "14th Place Solution",
  "url": "/competitions/benetech-making-graphs-accessible/writeups/penguin46-14th-place-solution",
  "author_name": "",
  "post_date": "2023-06-20T02:14:03.283Z",
  "votes": 30,
  "comment_count": 4,
  "views": 0,
  "content": "<p>First, congratulations to the winning teams! This task was very interesting and challenging. I hope to learn a lot from the top solutions.</p>\n<p>My solution consists of chart_type classification, template matching for scatter and pix2struct model for the rest chart_types.</p>\n<h1>Chart_type Classification</h1>\n<p>I finetuned resnet18d with about 70,000 images in the ICDAR dataset, resulting in the accuracy of 0.995 for extracted data.</p>\n<h1>Template matching for scatter</h1>\n<p>Scatter often requires a large number of datapoints, and long token lengths are needed. I addressed this problem by object detection, OCR and template matching. This approach scores 0.51 on extracted data. The algorithm is as follows:</p>\n<ol>\n<li>object detection of data points and axis texts by YOLOX (im_size=480)</li>\n<li>generate a pattern of datapoints using the highest confidence among the detected points</li>\n<li>identify the shape of the pattern based on the distance between the RGB values of the pattern and the background color</li>\n<li>scan the entire image and calculate the similarity score (L2 distance) with the pattern</li>\n<li>select approximately 1000 pixels with the highest similarity score as candidate points</li>\n<li>fill the rectangular area containing the data points with background color and use it as a base for reconstruction</li>\n<li>take out the candidate points in order from the one with the highest similarity score, and place a pattern if the following two conditions are satisfied<ol>\n<li>the L2 error with the original image is smaller when a pattern is placed than when a pattern is not placed</li>\n<li>the overlap with the existing pattern does not exceed 30%.</li></ol></li>\n</ol>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2F7bc7f2767887a28aa23dfff79aa62965%2Fscatter.png?generation=1687226523383966&amp;alt=media\"></p>\n<p>Since simple linear regression is vulnerable to outliers, I tried to use some form of robust regression. Considering that methods such as RANSAC and huber require a parameter on the scale and that the parameters tend to overfit the data set due to small data size, I implemented a simple robust regression without any hyper parameters. All two point pairs are connected by a straight line and the slope and intercept are calculated. The desired regression line is obtained using the median value for all computed slopes and intercepts. </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2Fa42b3944e43c17ada9c800e7242411c4%2Freg.png?generation=1687226587258677&amp;alt=media\"></p>\n<h2>Pix2Struct model for other types</h2>\n<ul>\n<li>labels are in the form xyxy</li>\n<li>decimal part of numerical is rounded to 4 significant digits</li>\n<li>augmentation for translation, rotation, noise, hue, etc.</li>\n<li>pretrained model: MatCha-base</li>\n<li>hyperparameters<ul>\n<li>max_length: 512</li>\n<li>max_patches: 2048</li>\n<li>lr: 1e-5</li>\n<li>scheduler: get_cosine_schedule_with_warmup</li>\n<li>num_warmup_steps: 1000</li>\n<li>weight_decay: 1e-5</li></ul></li>\n<li>Training data<ul>\n<li>extracted (1118)</li>\n<li>generated (999)</li>\n<li>ICDAR (labeled 1286+ pseudo&amp;hand labeled 2988)</li></ul></li>\n</ul>",
  "messages": [
    {
      "id": "2309934",
      "postDate": "06/20/2023 02:08:21",
      "content": "<p>First, congratulations to the winning teams! This task was very interesting and challenging. I hope to learn a lot from the top solutions.</p>\n<p>My solution consists of chart_type classification, template matching for scatter and pix2struct model for the rest chart_types.</p>\n<h1>Chart_type Classification</h1>\n<p>I finetuned resnet18d with about 70,000 images in the ICDAR dataset, resulting in the accuracy of 0.995 for extracted data.</p>\n<h1>Template matching for scatter</h1>\n<p>Scatter often requires a large number of datapoints, and long token lengths are needed. I addressed this problem by object detection, OCR and template matching. This approach scores 0.51 on extracted data. The algorithm is as follows:</p>\n<ol>\n<li>object detection of data points and axis texts by YOLOX (im_size=480)</li>\n<li>generate a pattern of datapoints using the highest confidence among the detected points</li>\n<li>identify the shape of the pattern based on the distance between the RGB values of the pattern and the background color</li>\n<li>scan the entire image and calculate the similarity score (L2 distance) with the pattern</li>\n<li>select approximately 1000 pixels with the highest similarity score as candidate points</li>\n<li>fill the rectangular area containing the data points with background color and use it as a base for reconstruction</li>\n<li>take out the candidate points in order from the one with the highest similarity score, and place a pattern if the following two conditions are satisfied<ol>\n<li>the L2 error with the original image is smaller when a pattern is placed than when a pattern is not placed</li>\n<li>the overlap with the existing pattern does not exceed 30%.</li></ol></li>\n</ol>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2F7bc7f2767887a28aa23dfff79aa62965%2Fscatter.png?generation=1687226523383966&amp;alt=media\"></p>\n<p>Since simple linear regression is vulnerable to outliers, I tried to use some form of robust regression. Considering that methods such as RANSAC and huber require a parameter on the scale and that the parameters tend to overfit the data set due to small data size, I implemented a simple robust regression without any hyper parameters. All two point pairs are connected by a straight line and the slope and intercept are calculated. The desired regression line is obtained using the median value for all computed slopes and intercepts. </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2Fa42b3944e43c17ada9c800e7242411c4%2Freg.png?generation=1687226587258677&amp;alt=media\"></p>\n<h2>Pix2Struct model for other types</h2>\n<ul>\n<li>labels are in the form xyxy</li>\n<li>decimal part of numerical is rounded to 4 significant digits</li>\n<li>augmentation for translation, rotation, noise, hue, etc.</li>\n<li>pretrained model: MatCha-base</li>\n<li>hyperparameters<ul>\n<li>max_length: 512</li>\n<li>max_patches: 2048</li>\n<li>lr: 1e-5</li>\n<li>scheduler: get_cosine_schedule_with_warmup</li>\n<li>num_warmup_steps: 1000</li>\n<li>weight_decay: 1e-5</li></ul></li>\n<li>Training data<ul>\n<li>extracted (1118)</li>\n<li>generated (999)</li>\n<li>ICDAR (labeled 1286+ pseudo&amp;hand labeled 2988)</li></ul></li>\n</ul>",
      "rawMarkdown": "First, congratulations to the winning teams! This task was very interesting and challenging. I hope to learn a lot from the top solutions.\n\nMy solution consists of chart_type classification, template matching for scatter and pix2struct model for the rest chart_types.\n\n# Chart_type Classification\nI finetuned resnet18d with about 70,000 images in the ICDAR dataset, resulting in the accuracy of 0.995 for extracted data.\n\n# Template matching for scatter\nScatter often requires a large number of datapoints, and long token lengths are needed. I addressed this problem by object detection, OCR and template matching. This approach scores 0.51 on extracted data. The algorithm is as follows:\n\n1. object detection of data points and axis texts by YOLOX (im_size=480)\n2. generate a pattern of datapoints using the highest confidence among the detected points\n3. identify the shape of the pattern based on the distance between the RGB values of the pattern and the background color\n4. scan the entire image and calculate the similarity score (L2 distance) with the pattern\n5. select approximately 1000 pixels with the highest similarity score as candidate points\n6. fill the rectangular area containing the data points with background color and use it as a base for reconstruction\n7. take out the candidate points in order from the one with the highest similarity score, and place a pattern if the following two conditions are satisfied\n  1. the L2 error with the original image is smaller when a pattern is placed than when a pattern is not placed\n  2. the overlap with the existing pattern does not exceed 30%.\n\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2F7bc7f2767887a28aa23dfff79aa62965%2Fscatter.png?generation=1687226523383966&alt=media\" width=\"600\">\n\nSince simple linear regression is vulnerable to outliers, I tried to use some form of robust regression. Considering that methods such as RANSAC and huber require a parameter on the scale and that the parameters tend to overfit the data set due to small data size, I implemented a simple robust regression without any hyper parameters. All two point pairs are connected by a straight line and the slope and intercept are calculated. The desired regression line is obtained using the median value for all computed slopes and intercepts. \n\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2Fa42b3944e43c17ada9c800e7242411c4%2Freg.png?generation=1687226587258677&alt=media\" width=\"300\">\n\n## Pix2Struct model for other types\n- labels are in the form xyxy\n- decimal part of numerical is rounded to 4 significant digits\n- augmentation for translation, rotation, noise, hue, etc.\n- pretrained model: MatCha-base\n- hyperparameters\n  - max_length: 512\n  - max_patches: 2048\n  - lr: 1e-5\n  - scheduler: get_cosine_schedule_with_warmup\n  - num_warmup_steps: 1000\n  - weight_decay: 1e-5\n- Training data\n  - extracted (1118)\n  - generated (999)\n  - ICDAR (labeled 1286+ pseudo&hand labeled 2988)",
      "votes": null
    },
    {
      "id": "2310054",
      "postDate": "06/20/2023 05:02:35",
      "content": "<p>Congratulations <a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a>. I am mostly intrigued by your object detection part, quite original. Will you be sharing any code of this?</p>",
      "rawMarkdown": "Congratulations @ryotayoshinobu. I am mostly intrigued by your object detection part, quite original. Will you be sharing any code of this?",
      "votes": null
    },
    {
      "id": "2310095",
      "postDate": "06/20/2023 05:30:53",
      "content": "<p><a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a> congrats! Can you share some your code?</p>",
      "rawMarkdown": "ryotayoshinobu congrats! Can you share some your code?",
      "votes": null
    },
    {
      "id": "2310373",
      "postDate": "06/20/2023 10:12:00",
      "content": "<p>That's a pretty smart pipeline for the scatter plots <a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a> . Congrats on your strong finish! </p>",
      "rawMarkdown": "That's a pretty smart pipeline for the scatter plots @ryotayoshinobu . Congrats on your strong finish!",
      "votes": null
    },
    {
      "id": "2310390",
      "postDate": "06/20/2023 10:28:14",
      "content": "<p>Congrats. I used resnet34 and I never use any extra data. I achieved 99.94% accuracy for both training and testing. I rotated the vertical bars to get more horizontal bar charts since they are only 73. I got 70100 dataset and then split it into 80% and 20%. </p>",
      "rawMarkdown": "Congrats. I used resnet34 and I never use any extra data. I achieved 99.94% accuracy for both training and testing. I rotated the vertical bars to get more horizontal bar charts since they are only 73. I got 70100 dataset and then split it into 80% and 20%.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 2310054,
      "author_name": "alejopaullier",
      "author_url": "",
      "post_date": "06/20/2023 05:02:35",
      "content": "<p>Congratulations <a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a>. I am mostly intrigued by your object detection part, quite original. Will you be sharing any code of this?</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2310095,
      "author_name": "serangu",
      "author_url": "",
      "post_date": "06/20/2023 05:30:53",
      "content": "<p><a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a> congrats! Can you share some your code?</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2310373,
      "author_name": "snnclsr",
      "author_url": "",
      "post_date": "06/20/2023 10:12:00",
      "content": "<p>That's a pretty smart pipeline for the scatter plots <a href=\"https://www.kaggle.com/ryotayoshinobu\" target=\"_blank\">@ryotayoshinobu</a> . Congrats on your strong finish! </p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2310390,
      "author_name": "hamzahabduljalil",
      "author_url": "",
      "post_date": "06/20/2023 10:28:14",
      "content": "<p>Congrats. I used resnet34 and I never use any extra data. I achieved 99.94% accuracy for both training and testing. I rotated the vertical bars to get more horizontal bar charts since they are only 73. I got 70100 dataset and then split it into 80% and 20%. </p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "2309934": "First, congratulations to the winning teams! This task was very interesting and challenging. I hope to learn a lot from the top solutions.\n\nMy solution consists of chart_type classification, template matching for scatter and pix2struct model for the rest chart_types.\n\n# Chart_type Classification\nI finetuned resnet18d with about 70,000 images in the ICDAR dataset, resulting in the accuracy of 0.995 for extracted data.\n\n# Template matching for scatter\nScatter often requires a large number of datapoints, and long token lengths are needed. I addressed this problem by object detection, OCR and template matching. This approach scores 0.51 on extracted data. The algorithm is as follows:\n\n1. object detection of data points and axis texts by YOLOX (im_size=480)\n2. generate a pattern of datapoints using the highest confidence among the detected points\n3. identify the shape of the pattern based on the distance between the RGB values of the pattern and the background color\n4. scan the entire image and calculate the similarity score (L2 distance) with the pattern\n5. select approximately 1000 pixels with the highest similarity score as candidate points\n6. fill the rectangular area containing the data points with background color and use it as a base for reconstruction\n7. take out the candidate points in order from the one with the highest similarity score, and place a pattern if the following two conditions are satisfied\n  1. the L2 error with the original image is smaller when a pattern is placed than when a pattern is not placed\n  2. the overlap with the existing pattern does not exceed 30%.\n\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2F7bc7f2767887a28aa23dfff79aa62965%2Fscatter.png?generation=1687226523383966&alt=media\" width=\"600\">\n\nSince simple linear regression is vulnerable to outliers, I tried to use some form of robust regression. Considering that methods such as RANSAC and huber require a parameter on the scale and that the parameters tend to overfit the data set due to small data size, I implemented a simple robust regression without any hyper parameters. All two point pairs are connected by a straight line and the slope and intercept are calculated. The desired regression line is obtained using the median value for all computed slopes and intercepts. \n\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3962786%2Fa42b3944e43c17ada9c800e7242411c4%2Freg.png?generation=1687226587258677&alt=media\" width=\"300\">\n\n## Pix2Struct model for other types\n- labels are in the form xyxy\n- decimal part of numerical is rounded to 4 significant digits\n- augmentation for translation, rotation, noise, hue, etc.\n- pretrained model: MatCha-base\n- hyperparameters\n  - max_length: 512\n  - max_patches: 2048\n  - lr: 1e-5\n  - scheduler: get_cosine_schedule_with_warmup\n  - num_warmup_steps: 1000\n  - weight_decay: 1e-5\n- Training data\n  - extracted (1118)\n  - generated (999)\n  - ICDAR (labeled 1286+ pseudo&hand labeled 2988)",
    "2310054": "Congratulations @ryotayoshinobu. I am mostly intrigued by your object detection part, quite original. Will you be sharing any code of this?",
    "2310095": "ryotayoshinobu congrats! Can you share some your code?",
    "2310373": "That's a pretty smart pipeline for the scatter plots @ryotayoshinobu . Congrats on your strong finish!",
    "2310390": "Congrats. I used resnet34 and I never use any extra data. I achieved 99.94% accuracy for both training and testing. I rotated the vertical bars to get more horizontal bar charts since they are only 73. I got 70100 dataset and then split it into 80% and 20%."
  },
  "source": "meta"
}