{
  "id": 135984,
  "title": "1st place solution /w code",
  "url": "/competitions/bengaliai-cv19/discussion/135984",
  "author_name": "deoxy",
  "post_date": "2020-03-17T01:39:24.788000",
  "votes": 488,
  "comment_count": 136,
  "views": 0,
  "content": "<h1>1st Place Solution --- Cyclegan Based Zero Shot Learning</h1>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F5231a0ab7a0bf93611fb6fd3d72c6295%2F1.png?generation=1584591840196431&amp;alt=media\" alt=\"\"></p>\n\n<h2>Classes and Labeling</h2>\n\n<p>I did not make inferences about the parts of the character. In other words, all my models classify against the 14784 (168  * 11  * 8) class.\nTherefore, I needed to know what the combination of labels made up of Grapheme.</p>\n\n<p>I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.</p>\n\n<p>```python=</p>\n\n<p>class_map = pd.read_csv('../input/bengaliai-cv19/class_map.csv')\ngrapheme_root = class_map[class_map['component_type'] == 'grapheme_root']\nvowel_diacritic = class_map[class_map['component_type'] == 'vowel_diacritic']\nconsonant_diacritic = class_map[class_map['component_type'] == 'consonant_diacritic']\ngrapheme_root_list = grapheme_root['component'].tolist()\nvowel_diacritic_list = vowel_diacritic['component'].tolist()\nconsonant_diacritic_list = consonant_diacritic['component'].tolist()</p>\n\n<p>def label_to_grapheme(grapheme_root, vowel_diacritic, consonant_diacritic):\n    if consonant_diacritic == 0:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 1:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic] + consonant_diacritic_list[consonant_diacritic]\n    elif consonant_diacritic == 2:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root]\n        else:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 3:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:]\n        else:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 4:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            if grapheme_root == 123 and vowel_diacritic == 1:\n                return grapheme_root_list[grapheme_root] + '\\u200d' + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n            return grapheme_root_list[grapheme_root]  + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 5:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 6:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 7:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1]\n        else:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1] + vowel_diacritic_list[vowel_diacritic]\n```</p>\n\n<p>The generation of synthetic data and the conversion of the prediction results into three components are based on this correspondence.</p>\n\n<h2>Split Data for Unseen Cross Validation</h2>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F2fd56df85b7442295bc605b10053aac9%2F2.png?generation=1584591905364753&amp;alt=media\" alt=\"\"></p>\n\n<p>All are randomly selected and split.Ashamedly, I split the data without thinking, so that a non-existent Grapheme root class was created at the time of evaluation, and proper evaluation could not be performed.\nHowever, since the learning cost was very high, it could not be easily recreated, and all local cv were evaluated as they were.\n😭</p>\n\n<h2>(1) Out of Distribution Detection Model</h2>\n\n<p>It is a model for distinguishing whether the input image is a Seen class or an Unseen class.\nThis model outputs confidence for each of the 1295 classes independently. If all confidences are low, it is judged as Unseen, and if there is at least one confidence, it is judged as Seen class.</p>\n\n<ul>\n<li>No resize and crop</li>\n<li>Preprocess --- AutoAugment Policy for SVHN (<a href=\"https://github.com/DeepVoltaire/AutoAugment\">https://github.com/DeepVoltaire/AutoAugment</a>)</li>\n<li>CNN --- EfficientNet-b7(ImageNet Pretrained)</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- WarmUpAndLinearDecay\n<code>python=\ndef warmup_linear_decay(step):\nif step &amp;lt; WARM_UP_STEP:\n    return step/WARM_UP_STEP\nelse:\n    return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n</code></li>\n<li>Output Lyaer --- LayerNorm-FC(2560 -&gt; 1295)-BCEWithLogitsLoss + OHEM?\n<code>python=\n    out = model(image)\n    sig_out = out.sigmoid()\n    loss = criterion(out, one_hot_label)\n    train_loss_position = (1-one_hot_label)*(sig_out.detach() &amp;gt; 0.1) + one_hot_label\n    loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\n</code></li>\n<li>Epoch --- 200</li>\n<li>Batch size --- 32</li>\n<li>dataset split --- 1:0</li>\n<li>single fold</li>\n<li>Machine Resource --- 1 Tesla V100 6 days</li>\n</ul>\n\n<p>| 1168 class Local CV(auroc) |\n| -------- |\n| 0.9967         |</p>\n\n<h2>(2) Seen Class Model</h2>\n\n<p>This model classifies 1295 classes included in the training data.</p>\n\n<ul>\n<li>No resize and crop</li>\n<li>Preprocess --- AutoAugment Policy for SVHN (<a href=\"https://github.com/DeepVoltaire/AutoAugment\">https://github.com/DeepVoltaire/AutoAugment</a>)</li>\n<li>CNN --- EfficientNet-b7(ImageNet Pretrained)</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- WarmUpAndLinearDecay\n<code>python=\ndef warmup_linear_decay(step):\nif step &amp;lt; WARM_UP_STEP:\n    return step/WARM_UP_STEP\nelse:\n    return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n</code></li>\n<li>Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy</li>\n<li>Epoch --- 200</li>\n<li>Batch size --- 32</li>\n<li>dataset split --- 9:1 random split</li>\n<li>single fold</li>\n<li>Machine Resource --- 1 Tesla V100 6 days</li>\n</ul>\n\n<p>| CV Score | LB Score |\n| -------- | -------- |\n| 0.9985     | 0.9874     |</p>\n\n<p>Large gaps can be predicted due to the presence of Unseen Class.</p>\n\n<h2>(3) Unseen Class Model</h2>\n\n<p>Learning this model is done in two stages. The first step is training a classifier for images synthesized from ttf files. The second step is training the generator that converts handwritten characters into the desired synthesized data-like image. To perform these learnings, first select one ttf and generate a synthetic dataset.\nThe image size of the synthesized data was 236x137, the same as the training data. Using Pillow and raqm, I drew Graphheme in four sizes, <code>[84, 96, 108, 120]</code>. The size of the dataset is 59136.</p>\n\n<h3>Font Classifier Pre-training</h3>\n\n<ul>\n<li>crop and resize to 224x224</li>\n<li>preprocess --- random affine, random rotate, random crop, cutout</li>\n<li>CNN --- EfficientNet-b0</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5</li>\n</ul>\n\n<p>def warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 60\n- Batch size --- 32\n- Machine Resource --- 1 Tesla V100 4 hours</p>\n\n<h3>CycleGan Training</h3>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fac780d7f0e17487c7ac2338346da5e93%2F3.png?generation=1584591955177298&amp;alt=media\" alt=\"\"></p>\n\n<ul>\n<li>crop and resize to 224x224</li>\n<li>preprocess --- random affine, random rotate, random crop (smaller than pre-training one), and no cutout</li>\n<li>Model --- Based on <a href=\"https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix\">https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix</a> + Pre-trained Font Classifier(fixed parameter and eval mode)</li>\n<li>Optimzer --- <code>torch.optim.Adam(params, lr=0.0002, betas=(0.5, 0.999))</code></li>\n<li>LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5</li>\n</ul>\n\n<p>def warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\ngenerator_scheduler = torch.optim.lr_scheduler.LambdaLR(generator_optimizer, warmup_linear_decay)\ndiscriminator_scheduler = torch.optim.lr_scheduler.LambdaLR(discriminator_optimizer, warmup_linear_decay)\n```\n- Epoch --- 40\n- Batch size --- 32\n- Machine Resource --- 4 Tesla V100 2.5 days\n- HyperParameter --- lambda_consistency=10, lambda_cls=1.0~5.0</p>\n\n<p>Please see the paper for CycleGan. The points that are different from normal CycleGan are as follows. The discriminator adds the supervised loss of the pre-trained font classifier when calculating the loss of a handwritten2font generator.</p>\n\n<p>The CV of the one that gave the highest score (lambda_cls = 4.0) is as follows. To avoid the influence of non-existent Graphheme root classes, macro average recall is calculated after excluding non-existent classes. (It does not mean that the recall value of a class that does not exist is calculated as 0.0 or 1.0.)</p>\n\n<p>| Local CV Score for Unseen Class | Local CV Score for Seen Class    |\n| ------------------------- | --- |\n| 0.8804                    |   0.9377  |</p>\n\n<p>After performing hyperparameter tuning, I trained two other types of ttf without evaluating local cv. They gave a higher LB score than the model trained in the first ttf, so the CV score of the parameter used in private may be higher.</p>\n\n<p>I created two models using different ttf for submission. At the time of submission, inferences were made using these ensembles.</p>\n\n<ul>\n<li><a href=\"https://www.omicronlab.com/download/fonts/kalpurush.ttf\">https://www.omicronlab.com/download/fonts/kalpurush.ttf</a></li>\n<li><a href=\"https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf\">https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf</a></li>\n</ul>\n\n<p>CycleGan's training code will be released after being modified so that it can run on 1GPU. Please wait.</p>\n\n<h2>Strange Points</h2>\n\n<p>To be honest, I can't justify why this method would increase the generalization of the Unseen class.\nI expected that the generation of images very similar to the synthetic data would affect Consistency Loss and Discriminator and gain generalization to the Unseen Class. However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.</p>\n\n<p>| lambda_cls | Input Image | Generated Image | True Synthesis Image | Local CV |\n| ---------- | ----------- | --------------- | -------------------- | -------- |\n| 1.0        |       <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F711934da5f230beddb44a8739df91485%2Fa.png?generation=1584592112177362&amp;alt=media\" alt=\"\">      |     <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fe191a2b21f412a494f069c1f20a658bb%2Fc.png?generation=1584592112054776&amp;alt=media\" alt=\"\"> | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Ff8a1a40285305ea497c1602d149c4177%2Fb.png?generation=1584592116047842&amp;alt=media\" alt=\"\">|     0.8618     |\n|    4.0        |   <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb3f573d385e3b9469d0ce6324e51b480%2Fe.png?generation=1584592113807041&amp;alt=media\" alt=\"\">     | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F7a2f830547a3a2b8f5a4daec2e0382f3%2Fg.png?generation=1584592111614129&amp;alt=media\" alt=\"\">        | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb40309c1b75ade826b394b326fba9201%2Ff.png?generation=1584592114057138&amp;alt=media\" alt=\"\">                |     <strong>0.8804</strong>     |</p>\n\n<h2>Code</h2>\n\n<p>The reduced version of CycleGAN code is now available.</p>\n\n<ol>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-classifier\">https://www.kaggle.com/linshokaku/cyclegan-classifier</a>\nFont image classifier training code (7h)</li>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-training\">https://www.kaggle.com/linshokaku/cyclegan-training</a>\nTraining code for a generator that converts a handwritten image to a font image (8h)</li>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-submission\">https://www.kaggle.com/linshokaku/cyclegan-submission</a>\nSubmission code</li>\n</ol>\n\n<p>Running from 1 to 3 in order is equivalent to the method I used in this competition.\nDue to execution time and hardware resources, the batch size, training epoch, etc. are set very small, but if you run it with the hyper parameters as mentioned above, you should get results comparable to my execution results.\nI hope you find it helpful.</p>",
  "messages": [
    {
      "id": 775842,
      "postDate": "2020-03-17T01:39:24.787Z",
      "content": "<h1>1st Place Solution --- Cyclegan Based Zero Shot Learning</h1>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F5231a0ab7a0bf93611fb6fd3d72c6295%2F1.png?generation=1584591840196431&amp;alt=media\" alt=\"\"></p>\n\n<h2>Classes and Labeling</h2>\n\n<p>I did not make inferences about the parts of the character. In other words, all my models classify against the 14784 (168  * 11  * 8) class.\nTherefore, I needed to know what the combination of labels made up of Grapheme.</p>\n\n<p>I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.</p>\n\n<p>```python=</p>\n\n<p>class_map = pd.read_csv('../input/bengaliai-cv19/class_map.csv')\ngrapheme_root = class_map[class_map['component_type'] == 'grapheme_root']\nvowel_diacritic = class_map[class_map['component_type'] == 'vowel_diacritic']\nconsonant_diacritic = class_map[class_map['component_type'] == 'consonant_diacritic']\ngrapheme_root_list = grapheme_root['component'].tolist()\nvowel_diacritic_list = vowel_diacritic['component'].tolist()\nconsonant_diacritic_list = consonant_diacritic['component'].tolist()</p>\n\n<p>def label_to_grapheme(grapheme_root, vowel_diacritic, consonant_diacritic):\n    if consonant_diacritic == 0:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 1:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic] + consonant_diacritic_list[consonant_diacritic]\n    elif consonant_diacritic == 2:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root]\n        else:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 3:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:]\n        else:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 4:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            if grapheme_root == 123 and vowel_diacritic == 1:\n                return grapheme_root_list[grapheme_root] + '\\u200d' + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n            return grapheme_root_list[grapheme_root]  + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 5:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 6:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 7:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1]\n        else:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1] + vowel_diacritic_list[vowel_diacritic]\n```</p>\n\n<p>The generation of synthetic data and the conversion of the prediction results into three components are based on this correspondence.</p>\n\n<h2>Split Data for Unseen Cross Validation</h2>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F2fd56df85b7442295bc605b10053aac9%2F2.png?generation=1584591905364753&amp;alt=media\" alt=\"\"></p>\n\n<p>All are randomly selected and split.Ashamedly, I split the data without thinking, so that a non-existent Grapheme root class was created at the time of evaluation, and proper evaluation could not be performed.\nHowever, since the learning cost was very high, it could not be easily recreated, and all local cv were evaluated as they were.\n😭</p>\n\n<h2>(1) Out of Distribution Detection Model</h2>\n\n<p>It is a model for distinguishing whether the input image is a Seen class or an Unseen class.\nThis model outputs confidence for each of the 1295 classes independently. If all confidences are low, it is judged as Unseen, and if there is at least one confidence, it is judged as Seen class.</p>\n\n<ul>\n<li>No resize and crop</li>\n<li>Preprocess --- AutoAugment Policy for SVHN (<a href=\"https://github.com/DeepVoltaire/AutoAugment\">https://github.com/DeepVoltaire/AutoAugment</a>)</li>\n<li>CNN --- EfficientNet-b7(ImageNet Pretrained)</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- WarmUpAndLinearDecay\n<code>python=\ndef warmup_linear_decay(step):\nif step &amp;lt; WARM_UP_STEP:\n    return step/WARM_UP_STEP\nelse:\n    return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n</code></li>\n<li>Output Lyaer --- LayerNorm-FC(2560 -&gt; 1295)-BCEWithLogitsLoss + OHEM?\n<code>python=\n    out = model(image)\n    sig_out = out.sigmoid()\n    loss = criterion(out, one_hot_label)\n    train_loss_position = (1-one_hot_label)*(sig_out.detach() &amp;gt; 0.1) + one_hot_label\n    loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\n</code></li>\n<li>Epoch --- 200</li>\n<li>Batch size --- 32</li>\n<li>dataset split --- 1:0</li>\n<li>single fold</li>\n<li>Machine Resource --- 1 Tesla V100 6 days</li>\n</ul>\n\n<p>| 1168 class Local CV(auroc) |\n| -------- |\n| 0.9967         |</p>\n\n<h2>(2) Seen Class Model</h2>\n\n<p>This model classifies 1295 classes included in the training data.</p>\n\n<ul>\n<li>No resize and crop</li>\n<li>Preprocess --- AutoAugment Policy for SVHN (<a href=\"https://github.com/DeepVoltaire/AutoAugment\">https://github.com/DeepVoltaire/AutoAugment</a>)</li>\n<li>CNN --- EfficientNet-b7(ImageNet Pretrained)</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- WarmUpAndLinearDecay\n<code>python=\ndef warmup_linear_decay(step):\nif step &amp;lt; WARM_UP_STEP:\n    return step/WARM_UP_STEP\nelse:\n    return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n</code></li>\n<li>Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy</li>\n<li>Epoch --- 200</li>\n<li>Batch size --- 32</li>\n<li>dataset split --- 9:1 random split</li>\n<li>single fold</li>\n<li>Machine Resource --- 1 Tesla V100 6 days</li>\n</ul>\n\n<p>| CV Score | LB Score |\n| -------- | -------- |\n| 0.9985     | 0.9874     |</p>\n\n<p>Large gaps can be predicted due to the presence of Unseen Class.</p>\n\n<h2>(3) Unseen Class Model</h2>\n\n<p>Learning this model is done in two stages. The first step is training a classifier for images synthesized from ttf files. The second step is training the generator that converts handwritten characters into the desired synthesized data-like image. To perform these learnings, first select one ttf and generate a synthetic dataset.\nThe image size of the synthesized data was 236x137, the same as the training data. Using Pillow and raqm, I drew Graphheme in four sizes, <code>[84, 96, 108, 120]</code>. The size of the dataset is 59136.</p>\n\n<h3>Font Classifier Pre-training</h3>\n\n<ul>\n<li>crop and resize to 224x224</li>\n<li>preprocess --- random affine, random rotate, random crop, cutout</li>\n<li>CNN --- EfficientNet-b0</li>\n<li>Optimizer --- <code>torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)</code> use defaule value</li>\n<li>LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5</li>\n</ul>\n\n<p>def warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 60\n- Batch size --- 32\n- Machine Resource --- 1 Tesla V100 4 hours</p>\n\n<h3>CycleGan Training</h3>\n\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fac780d7f0e17487c7ac2338346da5e93%2F3.png?generation=1584591955177298&amp;alt=media\" alt=\"\"></p>\n\n<ul>\n<li>crop and resize to 224x224</li>\n<li>preprocess --- random affine, random rotate, random crop (smaller than pre-training one), and no cutout</li>\n<li>Model --- Based on <a href=\"https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix\">https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix</a> + Pre-trained Font Classifier(fixed parameter and eval mode)</li>\n<li>Optimzer --- <code>torch.optim.Adam(params, lr=0.0002, betas=(0.5, 0.999))</code></li>\n<li>LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5</li>\n</ul>\n\n<p>def warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\ngenerator_scheduler = torch.optim.lr_scheduler.LambdaLR(generator_optimizer, warmup_linear_decay)\ndiscriminator_scheduler = torch.optim.lr_scheduler.LambdaLR(discriminator_optimizer, warmup_linear_decay)\n```\n- Epoch --- 40\n- Batch size --- 32\n- Machine Resource --- 4 Tesla V100 2.5 days\n- HyperParameter --- lambda_consistency=10, lambda_cls=1.0~5.0</p>\n\n<p>Please see the paper for CycleGan. The points that are different from normal CycleGan are as follows. The discriminator adds the supervised loss of the pre-trained font classifier when calculating the loss of a handwritten2font generator.</p>\n\n<p>The CV of the one that gave the highest score (lambda_cls = 4.0) is as follows. To avoid the influence of non-existent Graphheme root classes, macro average recall is calculated after excluding non-existent classes. (It does not mean that the recall value of a class that does not exist is calculated as 0.0 or 1.0.)</p>\n\n<p>| Local CV Score for Unseen Class | Local CV Score for Seen Class    |\n| ------------------------- | --- |\n| 0.8804                    |   0.9377  |</p>\n\n<p>After performing hyperparameter tuning, I trained two other types of ttf without evaluating local cv. They gave a higher LB score than the model trained in the first ttf, so the CV score of the parameter used in private may be higher.</p>\n\n<p>I created two models using different ttf for submission. At the time of submission, inferences were made using these ensembles.</p>\n\n<ul>\n<li><a href=\"https://www.omicronlab.com/download/fonts/kalpurush.ttf\">https://www.omicronlab.com/download/fonts/kalpurush.ttf</a></li>\n<li><a href=\"https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf\">https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf</a></li>\n</ul>\n\n<p>CycleGan's training code will be released after being modified so that it can run on 1GPU. Please wait.</p>\n\n<h2>Strange Points</h2>\n\n<p>To be honest, I can't justify why this method would increase the generalization of the Unseen class.\nI expected that the generation of images very similar to the synthetic data would affect Consistency Loss and Discriminator and gain generalization to the Unseen Class. However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.</p>\n\n<p>| lambda_cls | Input Image | Generated Image | True Synthesis Image | Local CV |\n| ---------- | ----------- | --------------- | -------------------- | -------- |\n| 1.0        |       <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F711934da5f230beddb44a8739df91485%2Fa.png?generation=1584592112177362&amp;alt=media\" alt=\"\">      |     <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fe191a2b21f412a494f069c1f20a658bb%2Fc.png?generation=1584592112054776&amp;alt=media\" alt=\"\"> | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Ff8a1a40285305ea497c1602d149c4177%2Fb.png?generation=1584592116047842&amp;alt=media\" alt=\"\">|     0.8618     |\n|    4.0        |   <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb3f573d385e3b9469d0ce6324e51b480%2Fe.png?generation=1584592113807041&amp;alt=media\" alt=\"\">     | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F7a2f830547a3a2b8f5a4daec2e0382f3%2Fg.png?generation=1584592111614129&amp;alt=media\" alt=\"\">        | <img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb40309c1b75ade826b394b326fba9201%2Ff.png?generation=1584592114057138&amp;alt=media\" alt=\"\">                |     <strong>0.8804</strong>     |</p>\n\n<h2>Code</h2>\n\n<p>The reduced version of CycleGAN code is now available.</p>\n\n<ol>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-classifier\">https://www.kaggle.com/linshokaku/cyclegan-classifier</a>\nFont image classifier training code (7h)</li>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-training\">https://www.kaggle.com/linshokaku/cyclegan-training</a>\nTraining code for a generator that converts a handwritten image to a font image (8h)</li>\n<li><a href=\"https://www.kaggle.com/linshokaku/cyclegan-submission\">https://www.kaggle.com/linshokaku/cyclegan-submission</a>\nSubmission code</li>\n</ol>\n\n<p>Running from 1 to 3 in order is equivalent to the method I used in this competition.\nDue to execution time and hardware resources, the batch size, training epoch, etc. are set very small, but if you run it with the hyper parameters as mentioned above, you should get results comparable to my execution results.\nI hope you find it helpful.</p>",
      "rawMarkdown": "# 1st Place Solution --- Cyclegan Based Zero Shot Learning\n\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F5231a0ab7a0bf93611fb6fd3d72c6295%2F1.png?generation=1584591840196431&amp;alt=media)\n\n\n## Classes and Labeling\n\nI did not make inferences about the parts of the character. In other words, all my models classify against the 14784 (168  * 11  * 8) class.\nTherefore, I needed to know what the combination of labels made up of Grapheme.\n\nI predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\n\n```python=\n\nclass_map = pd.read_csv('../input/bengaliai-cv19/class_map.csv')\ngrapheme_root = class_map[class_map['component_type'] == 'grapheme_root']\nvowel_diacritic = class_map[class_map['component_type'] == 'vowel_diacritic']\nconsonant_diacritic = class_map[class_map['component_type'] == 'consonant_diacritic']\ngrapheme_root_list = grapheme_root['component'].tolist()\nvowel_diacritic_list = vowel_diacritic['component'].tolist()\nconsonant_diacritic_list = consonant_diacritic['component'].tolist()\n\ndef label_to_grapheme(grapheme_root, vowel_diacritic, consonant_diacritic):\n    if consonant_diacritic == 0:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 1:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic] + consonant_diacritic_list[consonant_diacritic]\n    elif consonant_diacritic == 2:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root]\n        else:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 3:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:]\n        else:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 4:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            if grapheme_root == 123 and vowel_diacritic == 1:\n                return grapheme_root_list[grapheme_root] + '\\u200d' + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n            return grapheme_root_list[grapheme_root]  + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 5:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 6:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 7:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1]\n        else:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1] + vowel_diacritic_list[vowel_diacritic]\n```\n\n\nThe generation of synthetic data and the conversion of the prediction results into three components are based on this correspondence.\n\n## Split Data for Unseen Cross Validation\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F2fd56df85b7442295bc605b10053aac9%2F2.png?generation=1584591905364753&amp;alt=media)\n\nAll are randomly selected and split.Ashamedly, I split the data without thinking, so that a non-existent Grapheme root class was created at the time of evaluation, and proper evaluation could not be performed.\nHowever, since the learning cost was very high, it could not be easily recreated, and all local cv were evaluated as they were.\n😭\n\n\n## (1) Out of Distribution Detection Model\n\nIt is a model for distinguishing whether the input image is a Seen class or an Unseen class.\nThis model outputs confidence for each of the 1295 classes independently. If all confidences are low, it is judged as Unseen, and if there is at least one confidence, it is judged as Seen class.\n\n\n- No resize and crop\n- Preprocess --- AutoAugment Policy for SVHN ([https://github.com/DeepVoltaire/AutoAugment](https://github.com/DeepVoltaire/AutoAugment))\n- CNN --- EfficientNet-b7(ImageNet Pretrained)\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- WarmUpAndLinearDecay\n```python=\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return step/WARM_UP_STEP\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 1295)-BCEWithLogitsLoss + OHEM?\n```python=\n        out = model(image)\n        sig_out = out.sigmoid()\n        loss = criterion(out, one_hot_label)\n        train_loss_position = (1-one_hot_label)*(sig_out.detach() &gt; 0.1) + one_hot_label\n        loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\n```\n- Epoch --- 200\n- Batch size --- 32\n- dataset split --- 1:0\n- single fold\n- Machine Resource --- 1 Tesla V100 6 days\n\n\n\n| 1168 class Local CV(auroc) |\n| -------- |\n| 0.9967         |\n\n\n## (2) Seen Class Model\n\nThis model classifies 1295 classes included in the training data.\n\n- No resize and crop\n- Preprocess --- AutoAugment Policy for SVHN ([https://github.com/DeepVoltaire/AutoAugment](https://github.com/DeepVoltaire/AutoAugment))\n- CNN --- EfficientNet-b7(ImageNet Pretrained)\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- WarmUpAndLinearDecay\n```python=\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return step/WARM_UP_STEP\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 200\n- Batch size --- 32\n- dataset split --- 9:1 random split\n- single fold\n- Machine Resource --- 1 Tesla V100 6 days\n\n\n\n\n| CV Score | LB Score |\n| -------- | -------- |\n| 0.9985     | 0.9874     |\n\nLarge gaps can be predicted due to the presence of Unseen Class.\n\n## (3) Unseen Class Model\n\nLearning this model is done in two stages. The first step is training a classifier for images synthesized from ttf files. The second step is training the generator that converts handwritten characters into the desired synthesized data-like image. To perform these learnings, first select one ttf and generate a synthetic dataset.\nThe image size of the synthesized data was 236x137, the same as the training data. Using Pillow and raqm, I drew Graphheme in four sizes, `[84, 96, 108, 120]`. The size of the dataset is 59136.\n\n\n\n### Font Classifier Pre-training\n\n\n- crop and resize to 224x224\n- preprocess --- random affine, random rotate, random crop, cutout\n- CNN --- EfficientNet-b0\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5\n\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 60\n- Batch size --- 32\n- Machine Resource --- 1 Tesla V100 4 hours\n\n\n### CycleGan Training\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fac780d7f0e17487c7ac2338346da5e93%2F3.png?generation=1584591955177298&amp;alt=media)\n\n- crop and resize to 224x224\n- preprocess --- random affine, random rotate, random crop (smaller than pre-training one), and no cutout\n- Model --- Based on [https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix](https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix) + Pre-trained Font Classifier(fixed parameter and eval mode)\n- Optimzer --- `torch.optim.Adam(params, lr=0.0002, betas=(0.5, 0.999))`\n- LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5\n\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\ngenerator_scheduler = torch.optim.lr_scheduler.LambdaLR(generator_optimizer, warmup_linear_decay)\ndiscriminator_scheduler = torch.optim.lr_scheduler.LambdaLR(discriminator_optimizer, warmup_linear_decay)\n```\n- Epoch --- 40\n- Batch size --- 32\n- Machine Resource --- 4 Tesla V100 2.5 days\n- HyperParameter --- lambda_consistency=10, lambda_cls=1.0~5.0\n\n\nPlease see the paper for CycleGan. The points that are different from normal CycleGan are as follows. The discriminator adds the supervised loss of the pre-trained font classifier when calculating the loss of a handwritten2font generator.\n\nThe CV of the one that gave the highest score (lambda_cls = 4.0) is as follows. To avoid the influence of non-existent Graphheme root classes, macro average recall is calculated after excluding non-existent classes. (It does not mean that the recall value of a class that does not exist is calculated as 0.0 or 1.0.)\n\n\n\n| Local CV Score for Unseen Class | Local CV Score for Seen Class    |\n| ------------------------- | --- |\n| 0.8804                    |   0.9377  |\n\nAfter performing hyperparameter tuning, I trained two other types of ttf without evaluating local cv. They gave a higher LB score than the model trained in the first ttf, so the CV score of the parameter used in private may be higher.\n\n\nI created two models using different ttf for submission. At the time of submission, inferences were made using these ensembles.\n\n-   [https://www.omicronlab.com/download/fonts/kalpurush.ttf](https://www.omicronlab.com/download/fonts/kalpurush.ttf)\n-   [https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf](https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf)\n\nCycleGan's training code will be released after being modified so that it can run on 1GPU. Please wait.\n\n\n## Strange Points\n\nTo be honest, I can't justify why this method would increase the generalization of the Unseen class.\nI expected that the generation of images very similar to the synthetic data would affect Consistency Loss and Discriminator and gain generalization to the Unseen Class. However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.\n\n\n\n\n| lambda_cls | Input Image | Generated Image | True Synthesis Image | Local CV |\n| ---------- | ----------- | --------------- | -------------------- | -------- |\n| 1.0        |       ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F711934da5f230beddb44a8739df91485%2Fa.png?generation=1584592112177362&amp;alt=media)      |     ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fe191a2b21f412a494f069c1f20a658bb%2Fc.png?generation=1584592112054776&amp;alt=media) | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Ff8a1a40285305ea497c1602d149c4177%2Fb.png?generation=1584592116047842&amp;alt=media)|     0.8618     |\n|    4.0        |   ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb3f573d385e3b9469d0ce6324e51b480%2Fe.png?generation=1584592113807041&amp;alt=media)     | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F7a2f830547a3a2b8f5a4daec2e0382f3%2Fg.png?generation=1584592111614129&amp;alt=media)        | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb40309c1b75ade826b394b326fba9201%2Ff.png?generation=1584592114057138&amp;alt=media)                |     **0.8804**     |\n\n\n## Code\n\nThe reduced version of CycleGAN code is now available.\n\n1. https://www.kaggle.com/linshokaku/cyclegan-classifier\n   Font image classifier training code (7h)\n2. https://www.kaggle.com/linshokaku/cyclegan-training\n   Training code for a generator that converts a handwritten image to a font image (8h)\n3. https://www.kaggle.com/linshokaku/cyclegan-submission\n   Submission code\n\nRunning from 1 to 3 in order is equivalent to the method I used in this competition.\nDue to execution time and hardware resources, the batch size, training epoch, etc. are set very small, but if you run it with the hyper parameters as mentioned above, you should get results comparable to my execution results.\nI hope you find it helpful.",
      "votes": 488
    },
    {
      "id": 776542,
      "postDate": "2020-03-17T13:17:17.150Z",
      "content": "<p>This is kaggling at different level 👍 🙏 </p>",
      "rawMarkdown": "This is kaggling at different level 👍 🙏 ",
      "votes": 24
    },
    {
      "id": 783058,
      "postDate": "2020-03-23T00:15:56.593Z",
      "content": "<p>The CycleGAN training code is now available. If you have any bugs or questions, please don't hesitate to ask.</p>",
      "rawMarkdown": "The CycleGAN training code is now available. If you have any bugs or questions, please don't hesitate to ask.",
      "votes": 14,
      "replies": [
        {
          "id": 785324,
          "postDate": "2020-03-25T01:05:15.643Z",
          "content": "<p>This is really outstanding! Thanks for sharing!</p>",
          "rawMarkdown": "This is really outstanding! Thanks for sharing!"
        }
      ]
    },
    {
      "id": 776514,
      "postDate": "2020-03-17T13:04:41.677Z",
      "content": "<p>Congrats on the solo win and the amazing solution.  I think I'll need to read this again and again in the coming months to fully grasp what you did.</p>",
      "rawMarkdown": "Congrats on the solo win and the amazing solution.  I think I'll need to read this again and again in the coming months to fully grasp what you did.",
      "votes": 12
    },
    {
      "id": 779108,
      "postDate": "2020-03-19T03:05:44.660Z",
      "content": "<p>Absolutely brilliant. I need to read and re-read this. This is much to learn here. Congrats on well deserved victory!</p>",
      "rawMarkdown": "Absolutely brilliant. I need to read and re-read this. This is much to learn here. Congrats on well deserved victory!",
      "votes": 10
    },
    {
      "id": 778589,
      "postDate": "2020-03-18T15:21:30.943Z",
      "content": "<p>I'm not sure whether you will see old reply again so I'm making a new one ;)</p>\n\n<p>Congratulation again and here's my questions:</p>\n\n<ul>\n<li>You are using 2 effnet-b7 to predict seen/unseen and graphemes separately. Have you tried using a single model with 2 heads? Because it can save 20min for you.</li>\n<li>Did you try arcface to detect unseen? Because it performs better than sigmoid in my case.</li>\n<li>You are using effnet-b0 to predict generated hand written graphemes. Is it due to time limitation or big model doesn't work?</li>\n<li>Seems that generators are taking much more time than effnet-b7. Did you tune the architecture of CycleGAN?</li>\n<li>In your unseen graphemes pipeline, which is more important for improving performance? Generator or font classifier (effnet-b0)?</li>\n</ul>",
      "rawMarkdown": "I'm not sure whether you will see old reply again so I'm making a new one ;)\n\nCongratulation again and here's my questions:\n\n* You are using 2 effnet-b7 to predict seen/unseen and graphemes separately. Have you tried using a single model with 2 heads? Because it can save 20min for you.\n* Did you try arcface to detect unseen? Because it performs better than sigmoid in my case.\n* You are using effnet-b0 to predict generated hand written graphemes. Is it due to time limitation or big model doesn't work?\n* Seems that generators are taking much more time than effnet-b7. Did you tune the architecture of CycleGAN?\n* In your unseen graphemes pipeline, which is more important for improving performance? Generator or font classifier (effnet-b0)?\n",
      "votes": 7,
      "replies": [
        {
          "id": 778650,
          "postDate": "2020-03-18T16:01:39.857Z",
          "content": "<p>also is there reason you are using <code>8</code> classes instead of <code>7</code> in the 14784 (168 * 11 * 8) ?</p>",
          "rawMarkdown": "also is there reason you are using `8` classes instead of `7` in the 14784 (168 * 11 * 8) ?",
          "votes": 2
        },
        {
          "id": 779519,
          "postDate": "2020-03-19T12:44:29.480Z",
          "content": "<p><strong>About seen/unseen detection</strong>\nSince the inference time was not considered in the experimental stage, the model for detecting the Unseen class was trained separately from the standard CNN models.\nI also thought that improving the model that recognizes the Unseen class was more important than detecting the Unseen class, so I deferred those experiments.\nIn the introduction of the solution after the competition, I knew technique called ArcFace at the first time. This technique seems to have been used in some of the top solutions, but was it mentioned in the paper or post that it was good for performing seen/unseen detection?</p>\n\n<p><strong>About unseen model</strong>\nI used efn-b0 as a classification model for synthesized images because I thought it had enough capacity to identify synthesized images with fewer variations than handwritten characters. And CycleGAN uses a lot of RAM to train multiple models at the same time. It can be said that a small model was used because of constraints during training, rather than constraints during inference.\nI wanted to reduce the cost of tuning and fixing bugs by copying as much of the publicly available implementation as possible to efficiently score in a limited amount of time and resources. Therefore, modification of the model was of low priority, and in the end, did not make any changes from the published model.\nThe question of whether generator or classifier improvement is more important is definitely generator. I feel that the 40epoch learning time is not enough. If you take 1.5 to 2 times the training time for CycleGAN training, the accuracy may have improved. To that end, optimization and speeding up of the learning code are indispensable, and it was one of my reflections in this competition that I could not do it.</p>\n\n<p>I haven't been able to do many experiments, and I haven't been able to answer the results of comparing some experiments, but it should be helpful.</p>",
          "rawMarkdown": "\n**About seen/unseen detection**\nSince the inference time was not considered in the experimental stage, the model for detecting the Unseen class was trained separately from the standard CNN models.\nI also thought that improving the model that recognizes the Unseen class was more important than detecting the Unseen class, so I deferred those experiments.\nIn the introduction of the solution after the competition, I knew technique called ArcFace at the first time. This technique seems to have been used in some of the top solutions, but was it mentioned in the paper or post that it was good for performing seen/unseen detection?\n\n**About unseen model**\nI used efn-b0 as a classification model for synthesized images because I thought it had enough capacity to identify synthesized images with fewer variations than handwritten characters. And CycleGAN uses a lot of RAM to train multiple models at the same time. It can be said that a small model was used because of constraints during training, rather than constraints during inference.\nI wanted to reduce the cost of tuning and fixing bugs by copying as much of the publicly available implementation as possible to efficiently score in a limited amount of time and resources. Therefore, modification of the model was of low priority, and in the end, did not make any changes from the published model.\nThe question of whether generator or classifier improvement is more important is definitely generator. I feel that the 40epoch learning time is not enough. If you take 1.5 to 2 times the training time for CycleGAN training, the accuracy may have improved. To that end, optimization and speeding up of the learning code are indispensable, and it was one of my reflections in this competition that I could not do it.\n\n\n\n\nI haven't been able to do many experiments, and I haven't been able to answer the results of comparing some experiments, but it should be helpful.",
          "votes": 8
        },
        {
          "id": 779528,
          "postDate": "2020-03-19T12:52:35.097Z",
          "content": "<p><a href=\"/drhabib\">@drhabib</a> \nWhen I tried an approach to directly classify Grapheme, I realized that there were some with the same labeling but different Graphemes. This problem made it difficult to make a reasonable mapping between Grapheme and labels. So I decided to solve this problem by adding another class to Consonant Diacritics.\nThis issue was posted to discussion in the middle of the competition, and was eventually answered by <a href=\"https://www.kaggle.com/c/bengaliai-cv19/discussion/134258\">https://www.kaggle.com/c/bengaliai-cv19/discussion/134258</a> . I was fortunate that this content was consistent with my solution.</p>",
          "rawMarkdown": "@drhabib \nWhen I tried an approach to directly classify Grapheme, I realized that there were some with the same labeling but different Graphemes. This problem made it difficult to make a reasonable mapping between Grapheme and labels. So I decided to solve this problem by adding another class to Consonant Diacritics.\nThis issue was posted to discussion in the middle of the competition, and was eventually answered by https://www.kaggle.com/c/bengaliai-cv19/discussion/134258 . I was fortunate that this content was consistent with my solution.",
          "votes": 3
        },
        {
          "id": 779544,
          "postDate": "2020-03-19T13:12:30.073Z",
          "content": "<p>Thanks for you answer! Now I'm looking forward to read your excellent code ;)</p>\n\n<blockquote>\n  <p>Arcface was good for performing seen/unseen detection?</p>\n</blockquote>\n\n<p>Arcface is the SOTA method developed for dealing face recognition problem. An open set recognition problem.\nIn facial recognition, it's impossible to collect faces from all human being so we usually have only a little set of it, say 100k images from 10k unique people. But when the product released, we may have 10x ~ 100x unique faces inputed into the model. The test set is \"open\" so it's called open set recognition. When dealing this problem, arcface is significantly better than sigmoid (You can refer to the original paper or some blog if you're interested in it).</p>",
          "rawMarkdown": "Thanks for you answer! Now I'm looking forward to read your excellent code ;)\n\n&gt; Arcface was good for performing seen/unseen detection?\n\nArcface is the SOTA method developed for dealing face recognition problem. An open set recognition problem.\nIn facial recognition, it's impossible to collect faces from all human being so we usually have only a little set of it, say 100k images from 10k unique people. But when the product released, we may have 10x ~ 100x unique faces inputed into the model. The test set is \"open\" so it's called open set recognition. When dealing this problem, arcface is significantly better than sigmoid (You can refer to the original paper or some blog if you're interested in it).\n",
          "votes": 4
        }
      ]
    },
    {
      "id": 776523,
      "postDate": "2020-03-17T13:10:52.460Z",
      "content": "<p>Okay . I have never seen anything like this . I should read this multiple times , try to implement it and even then the brilliance of thinking of this solution at the first place would not be diminished by a bit . I am overwhelmed . Congrats !</p>",
      "rawMarkdown": "Okay . I have never seen anything like this . I should read this multiple times , try to implement it and even then the brilliance of thinking of this solution at the first place would not be diminished by a bit . I am overwhelmed . Congrats !",
      "votes": 7
    },
    {
      "id": 775880,
      "postDate": "2020-03-17T02:15:47.840Z",
      "content": "<p>Guessed as such! Really elegant solution with deserving Top 1 results🎉 🎉 . Interesting to see the introduction of GAN into training pipeline! </p>",
      "rawMarkdown": "Guessed as such! Really elegant solution with deserving Top 1 results🎉 🎉 . Interesting to see the introduction of GAN into training pipeline! ",
      "votes": 7
    },
    {
      "id": 776432,
      "postDate": "2020-03-17T11:43:51.387Z",
      "content": "<p>Amazing stuff, congrats, looking froward to full writeup.</p>\n\n<p>What I am cruious about: you write in your profile that you are an expert in OCR. Is this something that you also have applied to other OCR tasks, or did the task at hand require a more custom-tailed solution?</p>",
      "rawMarkdown": "Amazing stuff, congrats, looking froward to full writeup.\n\nWhat I am cruious about: you write in your profile that you are an expert in OCR. Is this something that you also have applied to other OCR tasks, or did the task at hand require a more custom-tailed solution?",
      "votes": 8,
      "replies": [
        {
          "id": 776521,
          "postDate": "2020-03-17T13:09:06.763Z",
          "content": "<p>This is my first time working on zero shot learning. Although the performance has been quite good for recent zero shot learning, it is still insufficient for application to real tasks. Actually, the local evaluation of the Unseen class was about 80% accuracy. It will be useless unless you devise another idea.</p>",
          "rawMarkdown": "\nThis is my first time working on zero shot learning. Although the performance has been quite good for recent zero shot learning, it is still insufficient for application to real tasks. Actually, the local evaluation of the Unseen class was about 80% accuracy. It will be useless unless you devise another idea.",
          "votes": 8
        }
      ]
    },
    {
      "id": 775905,
      "postDate": "2020-03-17T02:34:44.073Z",
      "content": "<p>4 months on Kaggle and you are already killing it. Congrats on winning the competition and looking forward to your solution </p>",
      "rawMarkdown": "4 months on Kaggle and you are already killing it. Congrats on winning the competition and looking forward to your solution ",
      "votes": 6
    },
    {
      "id": 776771,
      "postDate": "2020-03-17T16:15:49.150Z",
      "content": "<p>Fantastic! What is the meaning of seen/unseen class? How do you get 1295 classes? </p>",
      "rawMarkdown": "Fantastic! What is the meaning of seen/unseen class? How do you get 1295 classes? ",
      "votes": 3,
      "replies": [
        {
          "id": 778351,
          "postDate": "2020-03-18T11:11:13.163Z",
          "content": "<p>The training dataset used in this competition contained 1295 types of Grapheme. However, there can be up to 168 * 11 * 8 types of Grapheme in this competition. Graphemes that are not included in the training dataset are called Unseen classes. This designation follows <a href=\"/haqishen\">@haqishen</a>'s post. <a href=\"https://www.kaggle.com/c/bengaliai-cv19/discussion/134035\">https://www.kaggle.com/c/bengaliai-cv19/discussion/134035</a></p>",
          "rawMarkdown": "The training dataset used in this competition contained 1295 types of Grapheme. However, there can be up to 168 * 11 * 8 types of Grapheme in this competition. Graphemes that are not included in the training dataset are called Unseen classes. This designation follows @haqishen's post. https://www.kaggle.com/c/bengaliai-cv19/discussion/134035",
          "votes": 2
        },
        {
          "id": 778372,
          "postDate": "2020-03-18T11:33:58.930Z",
          "content": "<p>I see. Thanks for the explanation. </p>",
          "rawMarkdown": "I see. Thanks for the explanation. ",
          "votes": 1
        }
      ]
    },
    {
      "id": 776357,
      "postDate": "2020-03-17T10:29:03.620Z",
      "content": "<p>Congrats on your victory!\nI too had a similar idea. I wrote a selenium script to poll <a href=\"http://www.banglatext.com/text2image.html\">this site</a> and convert the grapheme texts to images.</p>\n\n<p>I am relatively new to Deep Learning (this is my first kaggle competition), so I do not know much about GAN's. Instead of using CycleGAN's, I used a custom DenseNet that I trained from scratch to perform the image-image translation. But I couldn't get an LB beyond 0.92.</p>\n\n<p>So, thank you so much for posting about your methodology. It is honestly a huge inspiration and and sort of helps to verify my idea. So thank you once again!</p>\n\n<p>Edit: Also, can you point me to some good sources, which would help me start learning about GANs?</p>",
      "rawMarkdown": "Congrats on your victory!\nI too had a similar idea. I wrote a selenium script to poll [this site](http://www.banglatext.com/text2image.html) and convert the grapheme texts to images.\n\nI am relatively new to Deep Learning (this is my first kaggle competition), so I do not know much about GAN's. Instead of using CycleGAN's, I used a custom DenseNet that I trained from scratch to perform the image-image translation. But I couldn't get an LB beyond 0.92.\n\nSo, thank you so much for posting about your methodology. It is honestly a huge inspiration and and sort of helps to verify my idea. So thank you once again!\n\nEdit: Also, can you point me to some good sources, which would help me start learning about GANs?",
      "votes": 3
    },
    {
      "id": 775999,
      "postDate": "2020-03-17T04:18:07.793Z",
      "content": "<p>dream solution!</p>",
      "rawMarkdown": "dream solution!",
      "votes": 3
    },
    {
      "id": 775967,
      "postDate": "2020-03-17T03:49:00.843Z",
      "content": "<p>[question placeholder]</p>\n\n<p>Congratulation and wow, your illustration is fantastic, cant wait to see your full post!</p>",
      "rawMarkdown": "[question placeholder]\n\nCongratulation and wow, your illustration is fantastic, cant wait to see your full post!",
      "votes": 4
    },
    {
      "id": 776204,
      "postDate": "2020-03-17T07:39:41.033Z",
      "content": "<p><a href=\"/linshokaku\">@linshokaku</a> Congrats. \nWhat is your hardware setup like number of GPUs, memory?</p>",
      "rawMarkdown": "@linshokaku Congrats. \nWhat is your hardware setup like number of GPUs, memory?",
      "votes": 2
    },
    {
      "id": 775946,
      "postDate": "2020-03-17T03:23:21.653Z",
      "content": "<p>This solution is so elegant and thats why there is larger gap between you and others !</p>",
      "rawMarkdown": "This solution is so elegant and thats why there is larger gap between you and others !",
      "votes": 2
    },
    {
      "id": 812566,
      "postDate": "2020-04-18T20:15:33.450Z",
      "content": "<p>First of all, Congrats for the win. Sorry for asking a naive question but thus zero shot learning means that we do nothing about the unseen classes at the time of training? If so, how is using ttf files and CycleGANs helping. I am not able to clearly grasp the idea. Can anyone please help me with it. Thanks in advance!</p>",
      "rawMarkdown": "First of all, Congrats for the win. Sorry for asking a naive question but thus zero shot learning means that we do nothing about the unseen classes at the time of training? If so, how is using ttf files and CycleGANs helping. I am not able to clearly grasp the idea. Can anyone please help me with it. Thanks in advance!",
      "votes": 1
    },
    {
      "id": 786520,
      "postDate": "2020-03-26T00:28:07.270Z",
      "content": "<p>Re: \"I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\"</p>\n\n<p>Can you please share an insight in to how did you end up creating this code please? </p>",
      "rawMarkdown": "Re: \"I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\"\n\nCan you please share an insight in to how did you end up creating this code please? ",
      "votes": 1
    },
    {
      "id": 779241,
      "postDate": "2020-03-19T06:06:33.183Z",
      "content": "<p>Great Solution</p>",
      "rawMarkdown": "Great Solution",
      "votes": 1
    },
    {
      "id": 778681,
      "postDate": "2020-03-18T16:33:33.167Z",
      "content": "<p>Probably the best solution on Kaggle I've ever seen. Congrats! </p>",
      "rawMarkdown": "Probably the best solution on Kaggle I've ever seen. Congrats! ",
      "votes": 1
    },
    {
      "id": 778541,
      "postDate": "2020-03-18T14:41:03.563Z",
      "content": "<p>Wao, my mind is blown, great work keep it up.👌 </p>",
      "rawMarkdown": "Wao, my mind is blown, great work keep it up.👌 ",
      "votes": 1
    },
    {
      "id": 778469,
      "postDate": "2020-03-18T13:22:27.230Z",
      "content": "<p>Amazing!</p>",
      "rawMarkdown": "Amazing!",
      "votes": 1
    },
    {
      "id": 778315,
      "postDate": "2020-03-18T10:41:57.767Z",
      "content": "<p>Great</p>",
      "rawMarkdown": "Great\n",
      "votes": 1
    },
    {
      "id": 778010,
      "postDate": "2020-03-18T04:35:27.587Z",
      "content": "<p>@deoxy Congrats on locking down 1st. I might have to try this out myself to understand this.\n It would be great if you can be a little more elaborative of the CycleGan pipeline. Thanks!</p>\n\n<p>I tried following one-shot approach and came up with my own recipe for producing all Grapheme combinations. Let me know your thoughts on this <a href=\"https://www.kaggle.com/harshpatel1692/all-combinations-168-x-11-x-7-edge-cases\">kernel</a></p>",
      "rawMarkdown": "@deoxy Congrats on locking down 1st. I might have to try this out myself to understand this.\n It would be great if you can be a little more elaborative of the CycleGan pipeline. Thanks!\n\nI tried following one-shot approach and came up with my own recipe for producing all Grapheme combinations. Let me know your thoughts on this [kernel](https://www.kaggle.com/harshpatel1692/all-combinations-168-x-11-x-7-edge-cases)",
      "votes": 1
    },
    {
      "id": 777978,
      "postDate": "2020-03-18T03:50:37.250Z",
      "content": "<p>Congratulations. Your approach is interesting. Thanks for sharing.</p>",
      "rawMarkdown": "Congratulations. Your approach is interesting. Thanks for sharing.",
      "votes": 1
    },
    {
      "id": 777766,
      "postDate": "2020-03-17T23:25:25.250Z",
      "content": "<p>Congrats and thanks for sharing. I'm surprised that all class are treated differently and very interesting to know that GAN is combined for unseen classes!</p>",
      "rawMarkdown": "Congrats and thanks for sharing. I'm surprised that all class are treated differently and very interesting to know that GAN is combined for unseen classes!",
      "votes": 1
    },
    {
      "id": 777667,
      "postDate": "2020-03-17T20:59:17.943Z",
      "content": "<p>Congratulations ! Thank you for sharing solution.\nThis is so cool!</p>",
      "rawMarkdown": "Congratulations ! Thank you for sharing solution.\nThis is so cool!",
      "votes": 1
    },
    {
      "id": 777570,
      "postDate": "2020-03-17T19:20:39.337Z",
      "content": "<p>Congratulations on your 1st place! It was a pleasure to read your elegant solution!</p>",
      "rawMarkdown": "Congratulations on your 1st place! It was a pleasure to read your elegant solution!",
      "votes": 1
    },
    {
      "id": 777557,
      "postDate": "2020-03-17T19:10:56.613Z",
      "content": "<p>Congratulations and thanks for the writeup. </p>",
      "rawMarkdown": "Congratulations and thanks for the writeup. ",
      "votes": 1
    },
    {
      "id": 777539,
      "postDate": "2020-03-17T18:51:14.020Z",
      "content": "<p>Very elegant solution. Congrats!</p>",
      "rawMarkdown": "Very elegant solution. Congrats!",
      "votes": 1
    },
    {
      "id": 776785,
      "postDate": "2020-03-17T16:26:47.243Z",
      "content": "<p>Congratulations and thanks for sharing. I believe I will go over it many times to digest those knowledge. Good chance to learn state-of-art image classification techniques. I cannot wait to see you full post. </p>",
      "rawMarkdown": "Congratulations and thanks for sharing. I believe I will go over it many times to digest those knowledge. Good chance to learn state-of-art image classification techniques. I cannot wait to see you full post. \n ",
      "votes": 1
    },
    {
      "id": 776696,
      "postDate": "2020-03-17T15:10:25.280Z",
      "content": "<p>congrats</p>",
      "rawMarkdown": "congrats",
      "votes": 1
    },
    {
      "id": 776694,
      "postDate": "2020-03-17T15:08:55.660Z",
      "content": "<p>This is whole another level !</p>",
      "rawMarkdown": "This is whole another level !",
      "votes": 1
    },
    {
      "id": 776658,
      "postDate": "2020-03-17T14:38:54.627Z",
      "content": "<p>wow, very nice man 👍 </p>",
      "rawMarkdown": "wow, very nice man 👍 ",
      "votes": 1
    },
    {
      "id": 776646,
      "postDate": "2020-03-17T14:31:42.167Z",
      "content": "<p>few questions regarding part (1): \n- What is the criterion used here <code>loss = criterion(out, one_hot_label)</code> in the part (1) ?\n- you only used the green part of the data in this step right?\n- what is SVHN ?  all I could find is a house number dataset.</p>",
      "rawMarkdown": "few questions regarding part (1): \n- What is the criterion used here `loss = criterion(out, one_hot_label)` in the part (1) ?\n- you only used the green part of the data in this step right?\n- what is SVHN ?  all I could find is a house number dataset.",
      "votes": 1,
      "replies": [
        {
          "id": 776654,
          "postDate": "2020-03-17T14:36:51.273Z",
          "content": "<p>It is torch.nn.BCEWithLogitsLoss.</p>",
          "rawMarkdown": "It is torch.nn.BCEWithLogitsLoss.",
          "votes": 1
        },
        {
          "id": 776664,
          "postDate": "2020-03-17T14:41:25.777Z",
          "content": "<p>When I get auroc score, Yes. But when create submission model, I use all data.</p>",
          "rawMarkdown": "When I get auroc score, Yes. But when create submission model, I use all data.",
          "votes": 1
        },
        {
          "id": 776670,
          "postDate": "2020-03-17T14:44:55.060Z",
          "content": "<p>Yes, I used augmentation policy that is optimized to SVHN Dataset.</p>",
          "rawMarkdown": "Yes, I used augmentation policy that is optimized to SVHN Dataset.",
          "votes": 1
        }
      ]
    },
    {
      "id": 776644,
      "postDate": "2020-03-17T14:29:02.630Z",
      "content": "<p>Cngrats!! The solution is amazing</p>",
      "rawMarkdown": "Cngrats!! The solution is amazing",
      "votes": 1
    },
    {
      "id": 776640,
      "postDate": "2020-03-17T14:26:49.160Z",
      "content": "<p>Congrats on Winning the Competition. You spend quite alot money for GPU (Tesla V100)</p>",
      "rawMarkdown": "Congrats on Winning the Competition. You spend quite alot money for GPU (Tesla V100)",
      "votes": 1
    },
    {
      "id": 776616,
      "postDate": "2020-03-17T14:06:15.483Z",
      "content": "<p>Upcoming bestfitting at Kaggle!</p>",
      "rawMarkdown": "Upcoming bestfitting at Kaggle!",
      "votes": 1
    },
    {
      "id": 776517,
      "postDate": "2020-03-17T13:06:17.580Z",
      "content": "<p>Nice....</p>\n\n<p>Too much for me to grasp..</p>",
      "rawMarkdown": "Nice....\n\nToo much for me to grasp..",
      "votes": 1
    },
    {
      "id": 776351,
      "postDate": "2020-03-17T10:21:45.317Z",
      "content": "<p>Good job!!!</p>",
      "rawMarkdown": "Good job!!!",
      "votes": 1
    },
    {
      "id": 776271,
      "postDate": "2020-03-17T08:55:26.073Z",
      "content": "<p>congrats, very well deserved 1st place! really clean and elegant solution :) learned a lot through this competition. looking forward to seeing more details from your solution</p>",
      "rawMarkdown": "congrats, very well deserved 1st place! really clean and elegant solution :) learned a lot through this competition. looking forward to seeing more details from your solution",
      "votes": 1
    },
    {
      "id": 776246,
      "postDate": "2020-03-17T08:29:46.343Z",
      "content": "<p>Amazing!!\nI am waiting for the details of the solution. I will review about GAN by then.</p>",
      "rawMarkdown": "Amazing!!\nI am waiting for the details of the solution. I will review about GAN by then.",
      "votes": 1
    },
    {
      "id": 776239,
      "postDate": "2020-03-17T08:26:47.950Z",
      "content": "<p>Congrats. Excited to see details of your solution!</p>",
      "rawMarkdown": "Congrats. Excited to see details of your solution!",
      "votes": 1
    },
    {
      "id": 776203,
      "postDate": "2020-03-17T07:39:24.487Z",
      "content": "<p>Amazing! Hope you will write full post soon.</p>",
      "rawMarkdown": "Amazing! Hope you will write full post soon.",
      "votes": 1
    },
    {
      "id": 776168,
      "postDate": "2020-03-17T07:00:05.347Z",
      "content": "<p>Amazing solution!</p>",
      "rawMarkdown": "Amazing solution!",
      "votes": 1
    },
    {
      "id": 776152,
      "postDate": "2020-03-17T06:49:05.527Z",
      "content": "<p>Wow it is amazing congratulations </p>",
      "rawMarkdown": "Wow it is amazing congratulations ",
      "votes": 1
    },
    {
      "id": 776140,
      "postDate": "2020-03-17T06:30:20.023Z",
      "content": "<p>great work🙌 </p>",
      "rawMarkdown": "great work🙌 ",
      "votes": 1
    },
    {
      "id": 776091,
      "postDate": "2020-03-17T05:46:05.717Z",
      "content": "<p>Congratulations.\nAnd will be waiting for your detail updates.</p>",
      "rawMarkdown": "Congratulations.\nAnd will be waiting for your detail updates.",
      "votes": 1
    },
    {
      "id": 775995,
      "postDate": "2020-03-17T04:15:07.427Z",
      "content": "<p>Eagerly waiting to see your full updates. :) </p>",
      "rawMarkdown": "Eagerly waiting to see your full updates. :) ",
      "votes": 1
    },
    {
      "id": 775992,
      "postDate": "2020-03-17T04:14:11.053Z",
      "content": "<p>o_O</p>",
      "rawMarkdown": "o_O",
      "votes": 1
    },
    {
      "id": 775934,
      "postDate": "2020-03-17T03:04:29.913Z",
      "content": "<p>Cool! Amazing! Congrats! Waiting for your updates!</p>",
      "rawMarkdown": "Cool! Amazing! Congrats! Waiting for your updates!",
      "votes": 1
    },
    {
      "id": 775882,
      "postDate": "2020-03-17T02:16:48.070Z",
      "content": "<p>Amazing congrats! Such a unique way to deal with unseen data!</p>",
      "rawMarkdown": "Amazing congrats! Such a unique way to deal with unseen data!",
      "votes": 1
    },
    {
      "id": 781246,
      "postDate": "2020-03-21T04:23:06.897Z",
      "content": "<p>Congratulations !  And, thank you for sharing your wonderful solution.</p>\n\n<p>About the Out of Distribution Detection Model, I tried to implement your loss function, but this part of the calculation is exactly the same as BCLosswithLogitsLoss. Is there something wrong with it?</p>\n\n<p><code>loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()</code></p>\n\n<p>Here's my code.\n```\ntarget = torch.tensor([[0,0,1,0], [0,1,0,0], [1,0,0,0]], dtype=torch.float32)\noutput = torch.randn_like(target, dtype=torch.float32)\nsig_out = output.sigmoid()\ncriterion = torch.nn.BCEWithLogitsLoss()\nloss = criterion(output, target)\nprint(loss)\ntrain_loss_position = (1-target)*(sig_out.detach() &gt; 0.1) + target\nloss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\nprint(loss)</p>\n\n<p>tensor(0.9078)\ntensor(0.9078)\n```</p>",
      "rawMarkdown": "Congratulations !  And, thank you for sharing your wonderful solution.\n\nAbout the Out of Distribution Detection Model, I tried to implement your loss function, but this part of the calculation is exactly the same as BCLosswithLogitsLoss. Is there something wrong with it?\n\n`loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()`\n\nHere's my code.\n```\ntarget = torch.tensor([[0,0,1,0], [0,1,0,0], [1,0,0,0]], dtype=torch.float32)\noutput = torch.randn_like(target, dtype=torch.float32)\nsig_out = output.sigmoid()\ncriterion = torch.nn.BCEWithLogitsLoss()\nloss = criterion(output, target)\nprint(loss)\ntrain_loss_position = (1-target)*(sig_out.detach() &gt; 0.1) + target\nloss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\nprint(loss)\n\ntensor(0.9078)\ntensor(0.9078)\n```\n\n\n",
      "votes": 2,
      "replies": [
        {
          "id": 781539,
          "postDate": "2020-03-21T12:09:51.207Z",
          "content": "<p>In order to calculate OHEM we need to get the loss per element, since pytorch by default takes the average of all the elements, we need to pass 'none' to the 'reduction' argument of BCEWithLogitsLoss.</p>",
          "rawMarkdown": "In order to calculate OHEM we need to get the loss per element, since pytorch by default takes the average of all the elements, we need to pass 'none' to the 'reduction' argument of BCEWithLogitsLoss.",
          "votes": 3
        },
        {
          "id": 781639,
          "postDate": "2020-03-21T14:22:58.350Z",
          "content": "<p>As you said, I can calculate correctly by passing 'none'  to the 'reduction' argument of BCEWithLogitsLoss. Thank you!</p>",
          "rawMarkdown": "As you said, I can calculate correctly by passing 'none'  to the 'reduction' argument of BCEWithLogitsLoss. Thank you!",
          "votes": 1
        }
      ]
    },
    {
      "id": 778397,
      "postDate": "2020-03-18T12:05:08.987Z",
      "content": "<p>congratulations for your first place and I have learnt something new from your solution.</p>",
      "rawMarkdown": "congratulations for your first place and I have learnt something new from your solution.",
      "votes": 2
    },
    {
      "id": 778202,
      "postDate": "2020-03-18T08:15:10.650Z",
      "content": "<p>I leant much from your solution! And sorry to disturb the discussion area for my naive questions.  </p>\n\n<hr>\n\n<p><strong>First</strong> <br>\nIs that your processing can be describe like below(2 separated parts)? <br>\n- judge the image is seen or not\n- if seen, use the model train for seen to classify. <br>\nif not, feed GAN the image and generilize a data-like image. After that, feed the output of GAN to the font classifier and classify\nIs it right?</p>\n\n<p><strong>Second</strong>  </p>\n\n<blockquote>\n  <p>Using Pillow and raqm, I drew Graphheme in four sizes, [84, 96, 108, 120]. The size of the dataset is 59136.  </p>\n</blockquote>\n\n<p>The mean of the sentence is that you train GAN based on the Grapheme which you drew on hand instead of the train data? And you drew 59136 pictures and save them as .ttf?(it's amazing!)  </p>\n\n<hr>\n\n<p>Could you(or anyone who else) solve my doubts?\nThanks a lot!😄 </p>",
      "rawMarkdown": "I leant much from your solution! And sorry to disturb the discussion area for my naive questions.  \n***\n**First**  \nIs that your processing can be describe like below(2 separated parts)?  \n- judge the image is seen or not\n- if seen, use the model train for seen to classify.  \nif not, feed GAN the image and generilize a data-like image. After that, feed the output of GAN to the font classifier and classify\nIs it right?\n\n**Second**  \n&gt; Using Pillow and raqm, I drew Graphheme in four sizes, [84, 96, 108, 120]. The size of the dataset is 59136.  \n\nThe mean of the sentence is that you train GAN based on the Grapheme which you drew on hand instead of the train data? And you drew 59136 pictures and save them as .ttf?(it's amazing!)  \n***\nCould you(or anyone who else) solve my doubts?\nThanks a lot!😄 ",
      "votes": 2,
      "replies": [
        {
          "id": 778362,
          "postDate": "2020-03-18T11:22:26.400Z",
          "content": "<p>First</p>\n\n<p>That interpretation is almost correct. However, if the output of the pipeline when it is not \"seen\" is the \"seen\" class, the inference is performed again in the pipeline when it is \"seen\".</p>\n\n<p>Second</p>\n\n<p>ttf is an abbreviation of true type font and is a file that defines font images to be output on a computer. This time, I downloaded several free fonts and synthesized all possible Grapheme font images.</p>",
          "rawMarkdown": "First\n\nThat interpretation is almost correct. However, if the output of the pipeline when it is not \"seen\" is the \"seen\" class, the inference is performed again in the pipeline when it is \"seen\".\n\nSecond\n\nttf is an abbreviation of true type font and is a file that defines font images to be output on a computer. This time, I downloaded several free fonts and synthesized all possible Grapheme font images.\n",
          "votes": 3
        },
        {
          "id": 779010,
          "postDate": "2020-03-18T23:40:22.490Z",
          "content": "<p>Thanks a lot! I start to get some points of your solution =)</p>",
          "rawMarkdown": "Thanks a lot! I start to get some points of your solution =)"
        }
      ]
    },
    {
      "id": 777930,
      "postDate": "2020-03-18T02:58:17.580Z",
      "content": "<p>Congratulation!\nIs it possible to release your full code?\nFor Font Classifier Pre-training, why are you using EfficientNet-b0 instead of deeper model?</p>",
      "rawMarkdown": "Congratulation!\nIs it possible to release your full code?\nFor Font Classifier Pre-training, why are you using EfficientNet-b0 instead of deeper model?",
      "votes": 2
    },
    {
      "id": 777512,
      "postDate": "2020-03-17T18:24:29.760Z",
      "content": "<p>Congratulations. Your approach is really interesting</p>",
      "rawMarkdown": "Congratulations. Your approach is really interesting",
      "votes": 2
    },
    {
      "id": 776701,
      "postDate": "2020-03-17T15:18:17.553Z",
      "content": "<p>People are awesome. </p>",
      "rawMarkdown": "People are awesome. ",
      "votes": 2
    },
    {
      "id": 776698,
      "postDate": "2020-03-17T15:12:59.310Z",
      "content": "<p>\"However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.\"</p>\n\n<p>this is interesting.</p>\n\n<p>is there any GAN example with the input is font and output is handwritten image?</p>",
      "rawMarkdown": "\"However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.\"\n\nthis is interesting.\n\nis there any GAN example with the input is font and output is handwritten image?",
      "votes": 2,
      "replies": [
        {
          "id": 778336,
          "postDate": "2020-03-18T11:01:20.227Z",
          "content": "<p>I understand that looking at what the other generator produces is important to analyze this problem. However, in this competition, no snapshot was created because the opposite generator was not needed. I'm going to do some training to analyze this problem.</p>",
          "rawMarkdown": "I understand that looking at what the other generator produces is important to analyze this problem. However, in this competition, no snapshot was created because the opposite generator was not needed. I'm going to do some training to analyze this problem."
        },
        {
          "id": 779271,
          "postDate": "2020-03-19T06:54:17.813Z",
          "content": "<p>at first one may think of generating samples that looks like the real samples (these virtual samples  probably lie in the region of high probability density).</p>\n\n<p>But what improve classification results may be those at the decision boundary. It is like the support vectors in SVM. these samples don't make any visual sense, bout are nevertheless decides how the decision boundary are drawn.</p>\n\n<p>you can try to embedded train samples, test samples, gan samples in lower dimension like tSNE or UMAP to see what actually happens</p>",
          "rawMarkdown": "at first one may think of generating samples that looks like the real samples (these virtual samples  probably lie in the region of high probability density).\n\nBut what improve classification results may be those at the decision boundary. It is like the support vectors in SVM. these samples don't make any visual sense, bout are nevertheless decides how the decision boundary are drawn.\n\nyou can try to embedded train samples, test samples, gan samples in lower dimension like tSNE or UMAP to see what actually happens",
          "votes": 3
        }
      ]
    },
    {
      "id": 776033,
      "postDate": "2020-03-17T04:57:46.210Z",
      "content": "<p>why cyclegan, but no just generate new graphemes from noise? Adapt other dataset to competition data domain?\nlooking forward to a complete solution!</p>",
      "rawMarkdown": "why cyclegan, but no just generate new graphemes from noise? Adapt other dataset to competition data domain?\nlooking forward to a complete solution!",
      "votes": 2
    },
    {
      "id": 778119,
      "postDate": "2020-03-18T07:00:29.883Z",
      "content": "<p>Amazing!</p>",
      "rawMarkdown": "Amazing!"
    },
    {
      "id": 776265,
      "postDate": "2020-03-17T08:50:47.627Z",
      "content": "<p>It is cool thing to see, that someone is using GAN s for this type of competition. I hope you will share code for GAN training. </p>",
      "rawMarkdown": "It is cool thing to see, that someone is using GAN s for this type of competition. I hope you will share code for GAN training. "
    },
    {
      "id": 775877,
      "postDate": "2020-03-17T02:13:36.630Z",
      "content": "<p>wow～～</p>",
      "rawMarkdown": "wow～～"
    },
    {
      "id": 784412,
      "postDate": "2020-03-24T07:45:48.493Z",
      "rawMarkdown": "",
      "votes": -1
    },
    {
      "id": 959655,
      "postDate": "2020-08-05T19:29:18.560Z",
      "content": "<p>Great idea !!</p>",
      "rawMarkdown": "Great idea !!"
    },
    {
      "id": 892193,
      "postDate": "2020-06-18T17:51:57.887Z",
      "content": "<p>Great stuff buddy....</p>",
      "rawMarkdown": "Great stuff buddy...."
    },
    {
      "id": 827626,
      "postDate": "2020-04-30T12:25:14.987Z",
      "content": "<p>Excellent work!  What were some of the biggest challenges?</p>",
      "rawMarkdown": "Excellent work!  What were some of the biggest challenges?"
    },
    {
      "id": 792581,
      "postDate": "2020-03-31T10:49:59.487Z",
      "content": "<p>Great</p>",
      "rawMarkdown": "Great"
    },
    {
      "id": 792155,
      "postDate": "2020-03-30T23:50:19.860Z",
      "content": "<p><a href=\"/linshokaku\">@linshokaku</a> I did not find any good benchmark for mixed precision training in generative models. Did you try mixed precision training for generative models? If used, how did it affect the accuracy/loss and speedup?</p>",
      "rawMarkdown": "@linshokaku I did not find any good benchmark for mixed precision training in generative models. Did you try mixed precision training for generative models? If used, how did it affect the accuracy/loss and speedup?",
      "replies": [
        {
          "id": 792276,
          "postDate": "2020-03-31T03:56:26.750Z",
          "content": "<p>This is the first time for me to use GAN. So, I'm not so familiar with GAN. Furthermore, since GAN learning is inherently unstable, it is difficult to analyze whether normal learning is taking place. Therefore, we did not introduce mixed precision.</p>",
          "rawMarkdown": "This is the first time for me to use GAN. So, I'm not so familiar with GAN. Furthermore, since GAN learning is inherently unstable, it is difficult to analyze whether normal learning is taking place. Therefore, we did not introduce mixed precision.",
          "votes": 1
        }
      ]
    },
    {
      "id": 790860,
      "postDate": "2020-03-29T22:41:51.047Z",
      "content": "<p>Great!</p>",
      "rawMarkdown": "Great!"
    },
    {
      "id": 787679,
      "postDate": "2020-03-27T01:49:34.083Z",
      "content": "<p>Great job!</p>",
      "rawMarkdown": "Great job!"
    },
    {
      "id": 787494,
      "postDate": "2020-03-26T20:39:02.597Z",
      "content": "<p>Many congratulations on the victory. Well deserved! 🙏 </p>",
      "rawMarkdown": "Many congratulations on the victory. Well deserved! 🙏 "
    },
    {
      "id": 785953,
      "postDate": "2020-03-25T14:36:33.833Z",
      "content": "<p>Elegant solution!</p>",
      "rawMarkdown": "Elegant solution!"
    },
    {
      "id": 785846,
      "postDate": "2020-03-25T12:51:40.290Z",
      "content": "<p>Congratulations!</p>",
      "rawMarkdown": "Congratulations!"
    },
    {
      "id": 785549,
      "postDate": "2020-03-25T06:37:01.843Z",
      "content": "<p>That's really interesting.</p>",
      "rawMarkdown": "That's really interesting."
    },
    {
      "id": 784925,
      "postDate": "2020-03-24T16:02:38.237Z",
      "content": "<p>amazing</p>",
      "rawMarkdown": "amazing\n"
    },
    {
      "id": 784561,
      "postDate": "2020-03-24T10:21:42.283Z",
      "content": "<p>nice solution </p>",
      "rawMarkdown": "nice solution \n"
    },
    {
      "id": 784418,
      "postDate": "2020-03-24T07:55:28.827Z",
      "content": "<p>just asking, How did you get this idea of implementing GANs in this problem statement? </p>",
      "rawMarkdown": "just asking, How did you get this idea of implementing GANs in this problem statement? ",
      "replies": [
        {
          "id": 784461,
          "postDate": "2020-03-24T08:22:05.637Z",
          "content": "<ol>\n<li>I was able to produce the high CVs that were up in the Best Single Model discussion early on and predicted that the content of the gap between the high CVs and LBs was due to the Unseen class. At the same time, I predicted that the identification accuracy of the Unseen class would have a significant impact on the final LB.</li>\n<li>I thought it was necessary to generate some form of Unseen class to identify the Unseen class. \nIn the beginning I created a model that was trained only with a composite image from a TTF file, and a model that mixed it with handwriting from the training data, but neither of these models performed well enough.</li>\n<li>So, I thought about the strategy of generating Unseen class handwritten characters, and as a method of generation, I decided to create a CycleGAN that does style conversion from a ttf image instead of a normal GAN.</li>\n<li>However, the generation of data sets by CycleGAN makes the process of verification and tuning difficult.</li>\n<li>Furthermore, throughout the experiment, it was observed that the generation of handwritten characters from ttf images by CycleGAN did not result in any change in shape (texture-only transformation). This phenomenon indicates that the generated handwriting may be dissociated from the actual handwriting.</li>\n<li>For these reasons, I switched to a strategy of generating TTF-style images from handwritten text at the expense of time at submission.</li>\n</ol>\n\n<p>The result of this strategy is the current solution.</p>",
          "rawMarkdown": "1. I was able to produce the high CVs that were up in the Best Single Model discussion early on and predicted that the content of the gap between the high CVs and LBs was due to the Unseen class. At the same time, I predicted that the identification accuracy of the Unseen class would have a significant impact on the final LB.\n2. I thought it was necessary to generate some form of Unseen class to identify the Unseen class. \nIn the beginning I created a model that was trained only with a composite image from a TTF file, and a model that mixed it with handwriting from the training data, but neither of these models performed well enough.\n3. So, I thought about the strategy of generating Unseen class handwritten characters, and as a method of generation, I decided to create a CycleGAN that does style conversion from a ttf image instead of a normal GAN.\n4. However, the generation of data sets by CycleGAN makes the process of verification and tuning difficult.\n5. Furthermore, throughout the experiment, it was observed that the generation of handwritten characters from ttf images by CycleGAN did not result in any change in shape (texture-only transformation). This phenomenon indicates that the generated handwriting may be dissociated from the actual handwriting.\n6. For these reasons, I switched to a strategy of generating TTF-style images from handwritten text at the expense of time at submission.\n\n\nThe result of this strategy is the current solution.\n",
          "votes": 5
        }
      ]
    },
    {
      "id": 784094,
      "postDate": "2020-03-23T23:43:19.563Z",
      "content": "<p>thx for sharing</p>",
      "rawMarkdown": "thx for sharing"
    },
    {
      "id": 783720,
      "postDate": "2020-03-23T15:44:09.427Z",
      "content": "<p>Impressive</p>",
      "rawMarkdown": "Impressive"
    },
    {
      "id": 783575,
      "postDate": "2020-03-23T13:37:47.133Z",
      "content": "<p>The beauty and intricacy of this art is one of the main reasons that compel me to pursue such career.</p>",
      "rawMarkdown": "The beauty and intricacy of this art is one of the main reasons that compel me to pursue such career."
    },
    {
      "id": 783500,
      "postDate": "2020-03-23T12:19:11.257Z",
      "content": "<p>Great job</p>",
      "rawMarkdown": "Great job"
    },
    {
      "id": 783108,
      "postDate": "2020-03-23T02:10:37.123Z",
      "content": "<p>congrats!</p>",
      "rawMarkdown": "congrats!"
    },
    {
      "id": 783094,
      "postDate": "2020-03-23T01:47:59.507Z",
      "content": "<p>Cool! Thanks for releasing the code! Gonna give it a try!</p>",
      "rawMarkdown": "Cool! Thanks for releasing the code! Gonna give it a try!"
    },
    {
      "id": 782561,
      "postDate": "2020-03-22T12:45:07.037Z",
      "content": "<p>Amazing work!</p>",
      "rawMarkdown": "Amazing work!"
    },
    {
      "id": 782552,
      "postDate": "2020-03-22T12:29:56.473Z",
      "content": "<p>Wow, nice one. Congrats for Victory. Really helpful in my progress. Thanks a bunch for sharing solution.</p>",
      "rawMarkdown": "Wow, nice one. Congrats for Victory. Really helpful in my progress. Thanks a bunch for sharing solution."
    },
    {
      "id": 782377,
      "postDate": "2020-03-22T07:59:29.070Z",
      "content": "<p>helpful</p>",
      "rawMarkdown": "helpful"
    },
    {
      "id": 781347,
      "postDate": "2020-03-21T07:20:19.503Z",
      "content": "<p>Hi I am Anuj just started Kaggle and it is looking very promising</p>",
      "rawMarkdown": "Hi I am Anuj just started Kaggle and it is looking very promising"
    },
    {
      "id": 781084,
      "postDate": "2020-03-20T22:33:48.930Z",
      "content": "<p>zoo wee mama</p>",
      "rawMarkdown": "zoo wee mama"
    },
    {
      "id": 781012,
      "postDate": "2020-03-20T20:26:44.090Z",
      "content": "<p>Wow! Looks very difficult</p>",
      "rawMarkdown": "Wow! Looks very difficult"
    },
    {
      "id": 780890,
      "postDate": "2020-03-20T17:57:59.713Z",
      "content": "<p>Absolutely its really awesome</p>",
      "rawMarkdown": "Absolutely its really awesome"
    },
    {
      "id": 780879,
      "postDate": "2020-03-20T17:41:55.530Z",
      "content": "<p>Great job!</p>",
      "rawMarkdown": "Great job!"
    },
    {
      "id": 780416,
      "postDate": "2020-03-20T08:38:58.743Z",
      "content": "<p>nice</p>",
      "rawMarkdown": "nice"
    },
    {
      "id": 780209,
      "postDate": "2020-03-20T04:07:13.780Z",
      "content": "<p>Congrats!</p>",
      "rawMarkdown": "Congrats!"
    },
    {
      "id": 779648,
      "postDate": "2020-03-19T15:05:46.683Z",
      "content": "<p>Congrats..It is very different.</p>",
      "rawMarkdown": "Congrats..It is very different."
    },
    {
      "id": 779375,
      "postDate": "2020-03-19T09:27:42.863Z",
      "content": "<p>Congrates!</p>",
      "rawMarkdown": "Congrates!\n"
    },
    {
      "id": 779310,
      "postDate": "2020-03-19T07:40:59.687Z",
      "content": "<p>Impressive</p>",
      "rawMarkdown": "Impressive"
    },
    {
      "id": 779297,
      "postDate": "2020-03-19T07:18:42.933Z",
      "content": "<p>woww</p>",
      "rawMarkdown": "woww"
    },
    {
      "id": 779086,
      "postDate": "2020-03-19T02:37:38.080Z",
      "content": "<p>I am new to Kaggle, but this looks really interesting!</p>",
      "rawMarkdown": "I am new to Kaggle, but this looks really interesting!"
    },
    {
      "id": 779077,
      "postDate": "2020-03-19T02:32:19.853Z",
      "content": "<p>Learning a lot from this. Cheers!</p>",
      "rawMarkdown": "Learning a lot from this. Cheers!"
    },
    {
      "id": 827061,
      "postDate": "2020-04-30T03:57:20.177Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 783577,
      "postDate": "2020-03-23T13:40:01.393Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 782263,
      "postDate": "2020-03-22T05:00:36.957Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 780589,
      "postDate": "2020-03-20T12:29:38.107Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 780587,
      "postDate": "2020-03-20T12:27:30.163Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 780101,
      "postDate": "2020-03-20T01:21:39.463Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 780062,
      "postDate": "2020-03-20T00:02:40.393Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 779343,
      "postDate": "2020-03-19T08:36:24.800Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 779045,
      "postDate": "2020-03-19T01:23:26.657Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 777947,
      "postDate": "2020-03-18T03:14:12.010Z",
      "rawMarkdown": "",
      "votes": 1,
      "isDeleted": true
    },
    {
      "id": 777976,
      "postDate": "2020-03-18T03:49:10.077Z",
      "content": "<p>Wow! Thank  you 🙏 </p>",
      "rawMarkdown": "Wow! Thank  you 🙏 ",
      "votes": 1
    },
    {
      "id": 777916,
      "postDate": "2020-03-18T02:48:39.357Z",
      "content": "<p>Congrats! thanks for sharing</p>",
      "rawMarkdown": "Congrats! thanks for sharing",
      "votes": 1
    },
    {
      "id": 845012,
      "postDate": "2020-05-13T02:12:03.263Z",
      "content": "<p>This is helpful my solution! Thank you!</p>",
      "rawMarkdown": "This is helpful my solution! Thank you!"
    },
    {
      "id": 806796,
      "postDate": "2020-04-14T04:36:09.270Z",
      "content": "<p>Thanks for sharing</p>",
      "rawMarkdown": "Thanks for sharing"
    },
    {
      "id": 783520,
      "postDate": "2020-03-23T12:40:55.910Z",
      "content": "<p>thank you, it is very helpful</p>",
      "rawMarkdown": "thank you, it is very helpful"
    },
    {
      "id": 782536,
      "postDate": "2020-03-22T12:03:35.510Z",
      "content": "<p>Congrats. And thanks for sharing!</p>",
      "rawMarkdown": "Congrats. And thanks for sharing!"
    },
    {
      "id": 780886,
      "postDate": "2020-03-20T17:52:16.447Z",
      "content": "<p>very insteresting. Thanks a lot</p>",
      "rawMarkdown": "very insteresting. Thanks a lot"
    },
    {
      "id": 780319,
      "postDate": "2020-03-20T06:38:44.333Z",
      "content": "<p>Congratulations.. Thanks for sharing👍 </p>",
      "rawMarkdown": "Congratulations.. Thanks for sharing👍 "
    }
  ],
  "comments": [
    {
      "id": 776542,
      "author_name": "Bibek",
      "author_url": "",
      "post_date": "2020-03-17T13:17:17.150000",
      "content": "<p>This is kaggling at different level 👍 🙏 </p>",
      "votes": 24,
      "replies": []
    },
    {
      "id": 783058,
      "author_name": "deoxy",
      "author_url": "",
      "post_date": "2020-03-23T00:15:56.593000",
      "content": "<p>The CycleGAN training code is now available. If you have any bugs or questions, please don't hesitate to ask.</p>",
      "votes": 14,
      "replies": [
        {
          "id": 785324,
          "author_name": "Warren Keil",
          "author_url": "",
          "post_date": "2020-03-25T01:05:15.643000",
          "content": "<p>This is really outstanding! Thanks for sharing!</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 776514,
      "author_name": "CPMP",
      "author_url": "",
      "post_date": "2020-03-17T13:04:41.677000",
      "content": "<p>Congrats on the solo win and the amazing solution.  I think I'll need to read this again and again in the coming months to fully grasp what you did.</p>",
      "votes": 12,
      "replies": []
    },
    {
      "id": 779108,
      "author_name": "Chris Deotte",
      "author_url": "",
      "post_date": "2020-03-19T03:05:44.660000",
      "content": "<p>Absolutely brilliant. I need to read and re-read this. This is much to learn here. Congrats on well deserved victory!</p>",
      "votes": 10,
      "replies": []
    },
    {
      "id": 778589,
      "author_name": "Qishen Ha",
      "author_url": "",
      "post_date": "2020-03-18T15:21:30.943000",
      "content": "<p>I'm not sure whether you will see old reply again so I'm making a new one ;)</p>\n\n<p>Congratulation again and here's my questions:</p>\n\n<ul>\n<li>You are using 2 effnet-b7 to predict seen/unseen and graphemes separately. Have you tried using a single model with 2 heads? Because it can save 20min for you.</li>\n<li>Did you try arcface to detect unseen? Because it performs better than sigmoid in my case.</li>\n<li>You are using effnet-b0 to predict generated hand written graphemes. Is it due to time limitation or big model doesn't work?</li>\n<li>Seems that generators are taking much more time than effnet-b7. Did you tune the architecture of CycleGAN?</li>\n<li>In your unseen graphemes pipeline, which is more important for improving performance? Generator or font classifier (effnet-b0)?</li>\n</ul>",
      "votes": 7,
      "replies": [
        {
          "id": 778650,
          "author_name": "DrHB",
          "author_url": "",
          "post_date": "2020-03-18T16:01:39.857000",
          "content": "<p>also is there reason you are using <code>8</code> classes instead of <code>7</code> in the 14784 (168 * 11 * 8) ?</p>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 779519,
          "author_name": "deoxy",
          "author_url": "",
          "post_date": "2020-03-19T12:44:29.480000",
          "content": "<p><strong>About seen/unseen detection</strong>\nSince the inference time was not considered in the experimental stage, the model for detecting the Unseen class was trained separately from the standard CNN models.\nI also thought that improving the model that recognizes the Unseen class was more important than detecting the Unseen class, so I deferred those experiments.\nIn the introduction of the solution after the competition, I knew technique called ArcFace at the first time. This technique seems to have been used in some of the top solutions, but was it mentioned in the paper or post that it was good for performing seen/unseen detection?</p>\n\n<p><strong>About unseen model</strong>\nI used efn-b0 as a classification model for synthesized images because I thought it had enough capacity to identify synthesized images with fewer variations than handwritten characters. And CycleGAN uses a lot of RAM to train multiple models at the same time. It can be said that a small model was used because of constraints during training, rather than constraints during inference.\nI wanted to reduce the cost of tuning and fixing bugs by copying as much of the publicly available implementation as possible to efficiently score in a limited amount of time and resources. Therefore, modification of the model was of low priority, and in the end, did not make any changes from the published model.\nThe question of whether generator or classifier improvement is more important is definitely generator. I feel that the 40epoch learning time is not enough. If you take 1.5 to 2 times the training time for CycleGAN training, the accuracy may have improved. To that end, optimization and speeding up of the learning code are indispensable, and it was one of my reflections in this competition that I could not do it.</p>\n\n<p>I haven't been able to do many experiments, and I haven't been able to answer the results of comparing some experiments, but it should be helpful.</p>",
          "votes": 8,
          "replies": []
        },
        {
          "id": 779528,
          "author_name": "deoxy",
          "author_url": "",
          "post_date": "2020-03-19T12:52:35.097000",
          "content": "<p><a href=\"/drhabib\">@drhabib</a> \nWhen I tried an approach to directly classify Grapheme, I realized that there were some with the same labeling but different Graphemes. This problem made it difficult to make a reasonable mapping between Grapheme and labels. So I decided to solve this problem by adding another class to Consonant Diacritics.\nThis issue was posted to discussion in the middle of the competition, and was eventually answered by <a href=\"https://www.kaggle.com/c/bengaliai-cv19/discussion/134258\">https://www.kaggle.com/c/bengaliai-cv19/discussion/134258</a> . I was fortunate that this content was consistent with my solution.</p>",
          "votes": 3,
          "replies": []
        },
        {
          "id": 779544,
          "author_name": "Qishen Ha",
          "author_url": "",
          "post_date": "2020-03-19T13:12:30.073000",
          "content": "<p>Thanks for you answer! Now I'm looking forward to read your excellent code ;)</p>\n\n<blockquote>\n  <p>Arcface was good for performing seen/unseen detection?</p>\n</blockquote>\n\n<p>Arcface is the SOTA method developed for dealing face recognition problem. An open set recognition problem.\nIn facial recognition, it's impossible to collect faces from all human being so we usually have only a little set of it, say 100k images from 10k unique people. But when the product released, we may have 10x ~ 100x unique faces inputed into the model. The test set is \"open\" so it's called open set recognition. When dealing this problem, arcface is significantly better than sigmoid (You can refer to the original paper or some blog if you're interested in it).</p>",
          "votes": 4,
          "replies": []
        }
      ]
    },
    {
      "id": 776523,
      "author_name": "Nirjhar Roy",
      "author_url": "",
      "post_date": "2020-03-17T13:10:52.460000",
      "content": "<p>Okay . I have never seen anything like this . I should read this multiple times , try to implement it and even then the brilliance of thinking of this solution at the first place would not be diminished by a bit . I am overwhelmed . Congrats !</p>",
      "votes": 7,
      "replies": []
    },
    {
      "id": 775880,
      "author_name": "Nicholas Lyu",
      "author_url": "",
      "post_date": "2020-03-17T02:15:47.840000",
      "content": "<p>Guessed as such! Really elegant solution with deserving Top 1 results🎉 🎉 . Interesting to see the introduction of GAN into training pipeline! </p>",
      "votes": 7,
      "replies": []
    },
    {
      "id": 776432,
      "author_name": "Psi",
      "author_url": "",
      "post_date": "2020-03-17T11:43:51.387000",
      "content": "<p>Amazing stuff, congrats, looking froward to full writeup.</p>\n\n<p>What I am cruious about: you write in your profile that you are an expert in OCR. Is this something that you also have applied to other OCR tasks, or did the task at hand require a more custom-tailed solution?</p>",
      "votes": 8,
      "replies": [
        {
          "id": 776521,
          "author_name": "deoxy",
          "author_url": "",
          "post_date": "2020-03-17T13:09:06.763000",
          "content": "<p>This is my first time working on zero shot learning. Although the performance has been quite good for recent zero shot learning, it is still insufficient for application to real tasks. Actually, the local evaluation of the Unseen class was about 80% accuracy. It will be useless unless you devise another idea.</p>",
          "votes": 8,
          "replies": []
        }
      ]
    },
    {
      "id": 775905,
      "author_name": "Bibek",
      "author_url": "",
      "post_date": "2020-03-17T02:34:44.073000",
      "content": "<p>4 months on Kaggle and you are already killing it. Congrats on winning the competition and looking forward to your solution </p>",
      "votes": 6,
      "replies": []
    },
    {
      "id": 776771,
      "author_name": "Stephen Lau",
      "author_url": "",
      "post_date": "2020-03-17T16:15:49.150000",
      "content": "<p>Fantastic! What is the meaning of seen/unseen class? How do you get 1295 classes? </p>",
      "votes": 3,
      "replies": [
        {
          "id": 778351,
          "author_name": "deoxy",
          "author_url": "",
          "post_date": "2020-03-18T11:11:13.163000",
          "content": "<p>The training dataset used in this competition contained 1295 types of Grapheme. However, there can be up to 168 * 11 * 8 types of Grapheme in this competition. Graphemes that are not included in the training dataset are called Unseen classes. This designation follows <a href=\"/haqishen\">@haqishen</a>'s post. <a href=\"https://www.kaggle.com/c/bengaliai-cv19/discussion/134035\">https://www.kaggle.com/c/bengaliai-cv19/discussion/134035</a></p>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 778372,
          "author_name": "Stephen Lau",
          "author_url": "",
          "post_date": "2020-03-18T11:33:58.930000",
          "content": "<p>I see. Thanks for the explanation. </p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 776357,
      "author_name": "Varun Anand",
      "author_url": "",
      "post_date": "2020-03-17T10:29:03.620000",
      "content": "<p>Congrats on your victory!\nI too had a similar idea. I wrote a selenium script to poll <a href=\"http://www.banglatext.com/text2image.html\">this site</a> and convert the grapheme texts to images.</p>\n\n<p>I am relatively new to Deep Learning (this is my first kaggle competition), so I do not know much about GAN's. Instead of using CycleGAN's, I used a custom DenseNet that I trained from scratch to perform the image-image translation. But I couldn't get an LB beyond 0.92.</p>\n\n<p>So, thank you so much for posting about your methodology. It is honestly a huge inspiration and and sort of helps to verify my idea. So thank you once again!</p>\n\n<p>Edit: Also, can you point me to some good sources, which would help me start learning about GANs?</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 775999,
      "author_name": "hengck23",
      "author_url": "",
      "post_date": "2020-03-17T04:18:07.793000",
      "content": "<p>dream solution!</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 775967,
      "author_name": "Qishen Ha",
      "author_url": "",
      "post_date": "2020-03-17T03:49:00.843000",
      "content": "<p>[question placeholder]</p>\n\n<p>Congratulation and wow, your illustration is fantastic, cant wait to see your full post!</p>",
      "votes": 4,
      "replies": []
    },
    {
      "id": 776204,
      "author_name": "Shayekh Islam",
      "author_url": "",
      "post_date": "2020-03-17T07:39:41.033000",
      "content": "<p><a href=\"/linshokaku\">@linshokaku</a> Congrats. \nWhat is your hardware setup like number of GPUs, memory?</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 775946,
      "author_name": "Nirjhar Roy",
      "author_url": "",
      "post_date": "2020-03-17T03:23:21.653000",
      "content": "<p>This solution is so elegant and thats why there is larger gap between you and others !</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 812566,
      "author_name": "Anirban Sen",
      "author_url": "",
      "post_date": "2020-04-18T20:15:33.450000",
      "content": "<p>First of all, Congrats for the win. Sorry for asking a naive question but thus zero shot learning means that we do nothing about the unseen classes at the time of training? If so, how is using ttf files and CycleGANs helping. I am not able to clearly grasp the idea. Can anyone please help me with it. Thanks in advance!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 786520,
      "author_name": "Aman Arora",
      "author_url": "",
      "post_date": "2020-03-26T00:28:07.270000",
      "content": "<p>Re: \"I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\"</p>\n\n<p>Can you please share an insight in to how did you end up creating this code please? </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 779241,
      "author_name": "Shivam Singhal",
      "author_url": "",
      "post_date": "2020-03-19T06:06:33.183000",
      "content": "<p>Great Solution</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 778681,
      "author_name": "silverstone",
      "author_url": "",
      "post_date": "2020-03-18T16:33:33.167000",
      "content": "<p>Probably the best solution on Kaggle I've ever seen. Congrats! </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 778541,
      "author_name": "Anshuman Singh",
      "author_url": "",
      "post_date": "2020-03-18T14:41:03.563000",
      "content": "<p>Wao, my mind is blown, great work keep it up.👌 </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 778469,
      "author_name": "dealforest",
      "author_url": "",
      "post_date": "2020-03-18T13:22:27.230000",
      "content": "<p>Amazing!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 778315,
      "author_name": "Murad Mirzayev",
      "author_url": "",
      "post_date": "2020-03-18T10:41:57.767000",
      "content": "<p>Great</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 778010,
      "author_name": "Harsh Patel",
      "author_url": "",
      "post_date": "2020-03-18T04:35:27.587000",
      "content": "<p>@deoxy Congrats on locking down 1st. I might have to try this out myself to understand this.\n It would be great if you can be a little more elaborative of the CycleGan pipeline. Thanks!</p>\n\n<p>I tried following one-shot approach and came up with my own recipe for producing all Grapheme combinations. Let me know your thoughts on this <a href=\"https://www.kaggle.com/harshpatel1692/all-combinations-168-x-11-x-7-edge-cases\">kernel</a></p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777978,
      "author_name": "Purba",
      "author_url": "",
      "post_date": "2020-03-18T03:50:37.250000",
      "content": "<p>Congratulations. Your approach is interesting. Thanks for sharing.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777766,
      "author_name": "corochann",
      "author_url": "",
      "post_date": "2020-03-17T23:25:25.250000",
      "content": "<p>Congrats and thanks for sharing. I'm surprised that all class are treated differently and very interesting to know that GAN is combined for unseen classes!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777667,
      "author_name": "Tawara",
      "author_url": "",
      "post_date": "2020-03-17T20:59:17.943000",
      "content": "<p>Congratulations ! Thank you for sharing solution.\nThis is so cool!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777570,
      "author_name": "Robin Smits",
      "author_url": "",
      "post_date": "2020-03-17T19:20:39.337000",
      "content": "<p>Congratulations on your 1st place! It was a pleasure to read your elegant solution!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777557,
      "author_name": "Deep Chatterjee",
      "author_url": "",
      "post_date": "2020-03-17T19:10:56.613000",
      "content": "<p>Congratulations and thanks for the writeup. </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777539,
      "author_name": "Jonathan Rebello",
      "author_url": "",
      "post_date": "2020-03-17T18:51:14.020000",
      "content": "<p>Very elegant solution. Congrats!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776785,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T16:26:47.243000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776696,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T15:10:25.280000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776694,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T15:08:55.660000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776658,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T14:38:54.627000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776646,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T14:31:42.167000",
      "content": "",
      "votes": 1,
      "replies": [
        {
          "id": 776654,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-17T14:36:51.273000",
          "content": "",
          "votes": 1,
          "replies": []
        },
        {
          "id": 776664,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-17T14:41:25.777000",
          "content": "",
          "votes": 1,
          "replies": []
        },
        {
          "id": 776670,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-17T14:44:55.060000",
          "content": "",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 776644,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T14:29:02.630000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776640,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T14:26:49.160000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776616,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T14:06:15.483000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776517,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T13:06:17.580000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776351,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T10:21:45.317000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776271,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T08:55:26.073000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776246,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T08:29:46.343000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776239,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T08:26:47.950000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776203,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T07:39:24.487000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776168,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T07:00:05.347000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776152,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T06:49:05.527000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776140,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T06:30:20.023000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 776091,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T05:46:05.717000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 775995,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T04:15:07.427000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 775992,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T04:14:11.053000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 775934,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T03:04:29.913000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 775882,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T02:16:48.070000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 781246,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-21T04:23:06.897000",
      "content": "",
      "votes": 2,
      "replies": [
        {
          "id": 781539,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-21T12:09:51.207000",
          "content": "",
          "votes": 3,
          "replies": []
        },
        {
          "id": 781639,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-21T14:22:58.350000",
          "content": "",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 778397,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T12:05:08.987000",
      "content": "",
      "votes": 2,
      "replies": []
    },
    {
      "id": 778202,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T08:15:10.650000",
      "content": "",
      "votes": 2,
      "replies": [
        {
          "id": 778362,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-18T11:22:26.400000",
          "content": "",
          "votes": 3,
          "replies": []
        },
        {
          "id": 779010,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-18T23:40:22.490000",
          "content": "",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 777930,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T02:58:17.580000",
      "content": "",
      "votes": 2,
      "replies": []
    },
    {
      "id": 777512,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T18:24:29.760000",
      "content": "",
      "votes": 2,
      "replies": []
    },
    {
      "id": 776701,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T15:18:17.553000",
      "content": "",
      "votes": 2,
      "replies": []
    },
    {
      "id": 776698,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T15:12:59.310000",
      "content": "",
      "votes": 2,
      "replies": [
        {
          "id": 778336,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-18T11:01:20.227000",
          "content": "",
          "votes": 0,
          "replies": []
        },
        {
          "id": 779271,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-19T06:54:17.813000",
          "content": "",
          "votes": 3,
          "replies": []
        }
      ]
    },
    {
      "id": 776033,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T04:57:46.210000",
      "content": "",
      "votes": 2,
      "replies": []
    },
    {
      "id": 778119,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T07:00:29.883000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 776265,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T08:50:47.627000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 775877,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-17T02:13:36.630000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 784412,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-24T07:45:48.493000",
      "content": "",
      "votes": -1,
      "replies": []
    },
    {
      "id": 959655,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-08-05T19:29:18.560000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 892193,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-06-18T17:51:57.887000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 827626,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-04-30T12:25:14.987000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 792581,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-31T10:49:59.487000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 792155,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-30T23:50:19.860000",
      "content": "",
      "votes": 0,
      "replies": [
        {
          "id": 792276,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-31T03:56:26.750000",
          "content": "",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 790860,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-29T22:41:51.047000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 787679,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-27T01:49:34.083000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 787494,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-26T20:39:02.597000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 785953,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-25T14:36:33.833000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 785846,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-25T12:51:40.290000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 785549,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-25T06:37:01.843000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 784925,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-24T16:02:38.237000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 784561,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-24T10:21:42.283000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 784418,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-24T07:55:28.827000",
      "content": "",
      "votes": 0,
      "replies": [
        {
          "id": 784461,
          "author_name": "",
          "author_url": "",
          "post_date": "2020-03-24T08:22:05.637000",
          "content": "",
          "votes": 5,
          "replies": []
        }
      ]
    },
    {
      "id": 784094,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T23:43:19.563000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783720,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T15:44:09.427000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783575,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T13:37:47.133000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783500,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T12:19:11.257000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783108,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T02:10:37.123000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783094,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T01:47:59.507000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 782561,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-22T12:45:07.037000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 782552,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-22T12:29:56.473000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 782377,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-22T07:59:29.070000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 781347,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-21T07:20:19.503000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 781084,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T22:33:48.930000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 781012,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T20:26:44.090000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780890,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T17:57:59.713000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780879,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T17:41:55.530000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780416,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T08:38:58.743000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780209,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T04:07:13.780000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779648,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T15:05:46.683000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779375,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T09:27:42.863000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779310,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T07:40:59.687000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779297,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T07:18:42.933000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779086,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T02:37:38.080000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779077,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T02:32:19.853000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 827061,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-04-30T03:57:20.177000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783577,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T13:40:01.393000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 782263,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-22T05:00:36.957000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780589,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T12:29:38.107000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780587,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T12:27:30.163000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780101,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T01:21:39.463000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780062,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T00:02:40.393000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779343,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T08:36:24.800000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 779045,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-19T01:23:26.657000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 777947,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T03:14:12.010000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777976,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T03:49:10.077000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 777916,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-18T02:48:39.357000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 845012,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-05-13T02:12:03.263000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 806796,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-04-14T04:36:09.270000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 783520,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-23T12:40:55.910000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 782536,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-22T12:03:35.510000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780886,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T17:52:16.447000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 780319,
      "author_name": "",
      "author_url": "",
      "post_date": "2020-03-20T06:38:44.333000",
      "content": "",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "775842": "# 1st Place Solution --- Cyclegan Based Zero Shot Learning\n\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F5231a0ab7a0bf93611fb6fd3d72c6295%2F1.png?generation=1584591840196431&amp;alt=media)\n\n\n## Classes and Labeling\n\nI did not make inferences about the parts of the character. In other words, all my models classify against the 14784 (168  * 11  * 8) class.\nTherefore, I needed to know what the combination of labels made up of Grapheme.\n\nI predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\n\n```python=\n\nclass_map = pd.read_csv('../input/bengaliai-cv19/class_map.csv')\ngrapheme_root = class_map[class_map['component_type'] == 'grapheme_root']\nvowel_diacritic = class_map[class_map['component_type'] == 'vowel_diacritic']\nconsonant_diacritic = class_map[class_map['component_type'] == 'consonant_diacritic']\ngrapheme_root_list = grapheme_root['component'].tolist()\nvowel_diacritic_list = vowel_diacritic['component'].tolist()\nconsonant_diacritic_list = consonant_diacritic['component'].tolist()\n\ndef label_to_grapheme(grapheme_root, vowel_diacritic, consonant_diacritic):\n    if consonant_diacritic == 0:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 1:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic] + consonant_diacritic_list[consonant_diacritic]\n    elif consonant_diacritic == 2:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root]\n        else:\n            return consonant_diacritic_list[consonant_diacritic] + grapheme_root_list[grapheme_root] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 3:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:]\n        else:\n            return consonant_diacritic_list[consonant_diacritic][:2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic][1:] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 4:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            if grapheme_root == 123 and vowel_diacritic == 1:\n                return grapheme_root_list[grapheme_root] + '\\u200d' + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n            return grapheme_root_list[grapheme_root]  + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 5:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 6:\n        if vowel_diacritic == 0:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic]\n        else:\n            return grapheme_root_list[grapheme_root] + consonant_diacritic_list[consonant_diacritic] + vowel_diacritic_list[vowel_diacritic]\n    elif consonant_diacritic == 7:\n        if vowel_diacritic == 0:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1]\n        else:\n            return consonant_diacritic_list[2] + grapheme_root_list[grapheme_root] + consonant_diacritic_list[2][::-1] + vowel_diacritic_list[vowel_diacritic]\n```\n\n\nThe generation of synthetic data and the conversion of the prediction results into three components are based on this correspondence.\n\n## Split Data for Unseen Cross Validation\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F2fd56df85b7442295bc605b10053aac9%2F2.png?generation=1584591905364753&amp;alt=media)\n\nAll are randomly selected and split.Ashamedly, I split the data without thinking, so that a non-existent Grapheme root class was created at the time of evaluation, and proper evaluation could not be performed.\nHowever, since the learning cost was very high, it could not be easily recreated, and all local cv were evaluated as they were.\n😭\n\n\n## (1) Out of Distribution Detection Model\n\nIt is a model for distinguishing whether the input image is a Seen class or an Unseen class.\nThis model outputs confidence for each of the 1295 classes independently. If all confidences are low, it is judged as Unseen, and if there is at least one confidence, it is judged as Seen class.\n\n\n- No resize and crop\n- Preprocess --- AutoAugment Policy for SVHN ([https://github.com/DeepVoltaire/AutoAugment](https://github.com/DeepVoltaire/AutoAugment))\n- CNN --- EfficientNet-b7(ImageNet Pretrained)\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- WarmUpAndLinearDecay\n```python=\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return step/WARM_UP_STEP\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 1295)-BCEWithLogitsLoss + OHEM?\n```python=\n        out = model(image)\n        sig_out = out.sigmoid()\n        loss = criterion(out, one_hot_label)\n        train_loss_position = (1-one_hot_label)*(sig_out.detach() &gt; 0.1) + one_hot_label\n        loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\n```\n- Epoch --- 200\n- Batch size --- 32\n- dataset split --- 1:0\n- single fold\n- Machine Resource --- 1 Tesla V100 6 days\n\n\n\n| 1168 class Local CV(auroc) |\n| -------- |\n| 0.9967         |\n\n\n## (2) Seen Class Model\n\nThis model classifies 1295 classes included in the training data.\n\n- No resize and crop\n- Preprocess --- AutoAugment Policy for SVHN ([https://github.com/DeepVoltaire/AutoAugment](https://github.com/DeepVoltaire/AutoAugment))\n- CNN --- EfficientNet-b7(ImageNet Pretrained)\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- WarmUpAndLinearDecay\n```python=\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return step/WARM_UP_STEP\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 200\n- Batch size --- 32\n- dataset split --- 9:1 random split\n- single fold\n- Machine Resource --- 1 Tesla V100 6 days\n\n\n\n\n| CV Score | LB Score |\n| -------- | -------- |\n| 0.9985     | 0.9874     |\n\nLarge gaps can be predicted due to the presence of Unseen Class.\n\n## (3) Unseen Class Model\n\nLearning this model is done in two stages. The first step is training a classifier for images synthesized from ttf files. The second step is training the generator that converts handwritten characters into the desired synthesized data-like image. To perform these learnings, first select one ttf and generate a synthetic dataset.\nThe image size of the synthesized data was 236x137, the same as the training data. Using Pillow and raqm, I drew Graphheme in four sizes, `[84, 96, 108, 120]`. The size of the dataset is 59136.\n\n\n\n### Font Classifier Pre-training\n\n\n- crop and resize to 224x224\n- preprocess --- random affine, random rotate, random crop, cutout\n- CNN --- EfficientNet-b0\n- Optimizer --- `torch.optim.AdamW(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)` use defaule value\n- LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5\n\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, warmup_linear_decay)\n```\n- Output Lyaer --- LayerNorm-FC(2560 -&gt; 14784)-SoftmaxCrossEntropy\n- Epoch --- 60\n- Batch size --- 32\n- Machine Resource --- 1 Tesla V100 4 hours\n\n\n### CycleGan Training\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fac780d7f0e17487c7ac2338346da5e93%2F3.png?generation=1584591955177298&amp;alt=media)\n\n- crop and resize to 224x224\n- preprocess --- random affine, random rotate, random crop (smaller than pre-training one), and no cutout\n- Model --- Based on [https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix](https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix) + Pre-trained Font Classifier(fixed parameter and eval mode)\n- Optimzer --- `torch.optim.Adam(params, lr=0.0002, betas=(0.5, 0.999))`\n- LRScheduler --- LinearDecay\n```python=\nWARM_UP_STEP = train_steps*0.5\n\ndef warmup_linear_decay(step):\n    if step &lt; WARM_UP_STEP:\n        return 1.0\n    else:\n        return (train_steps-step)/(train_steps-WARM_UP_STEP)\ngenerator_scheduler = torch.optim.lr_scheduler.LambdaLR(generator_optimizer, warmup_linear_decay)\ndiscriminator_scheduler = torch.optim.lr_scheduler.LambdaLR(discriminator_optimizer, warmup_linear_decay)\n```\n- Epoch --- 40\n- Batch size --- 32\n- Machine Resource --- 4 Tesla V100 2.5 days\n- HyperParameter --- lambda_consistency=10, lambda_cls=1.0~5.0\n\n\nPlease see the paper for CycleGan. The points that are different from normal CycleGan are as follows. The discriminator adds the supervised loss of the pre-trained font classifier when calculating the loss of a handwritten2font generator.\n\nThe CV of the one that gave the highest score (lambda_cls = 4.0) is as follows. To avoid the influence of non-existent Graphheme root classes, macro average recall is calculated after excluding non-existent classes. (It does not mean that the recall value of a class that does not exist is calculated as 0.0 or 1.0.)\n\n\n\n| Local CV Score for Unseen Class | Local CV Score for Seen Class    |\n| ------------------------- | --- |\n| 0.8804                    |   0.9377  |\n\nAfter performing hyperparameter tuning, I trained two other types of ttf without evaluating local cv. They gave a higher LB score than the model trained in the first ttf, so the CV score of the parameter used in private may be higher.\n\n\nI created two models using different ttf for submission. At the time of submission, inferences were made using these ensembles.\n\n-   [https://www.omicronlab.com/download/fonts/kalpurush.ttf](https://www.omicronlab.com/download/fonts/kalpurush.ttf)\n-   [https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf](https://www.omicronlab.com/download/fonts/NikoshLightBan.ttf)\n\nCycleGan's training code will be released after being modified so that it can run on 1GPU. Please wait.\n\n\n## Strange Points\n\nTo be honest, I can't justify why this method would increase the generalization of the Unseen class.\nI expected that the generation of images very similar to the synthetic data would affect Consistency Loss and Discriminator and gain generalization to the Unseen Class. However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.\n\n\n\n\n| lambda_cls | Input Image | Generated Image | True Synthesis Image | Local CV |\n| ---------- | ----------- | --------------- | -------------------- | -------- |\n| 1.0        |       ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F711934da5f230beddb44a8739df91485%2Fa.png?generation=1584592112177362&amp;alt=media)      |     ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fe191a2b21f412a494f069c1f20a658bb%2Fc.png?generation=1584592112054776&amp;alt=media) | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Ff8a1a40285305ea497c1602d149c4177%2Fb.png?generation=1584592116047842&amp;alt=media)|     0.8618     |\n|    4.0        |   ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb3f573d385e3b9469d0ce6324e51b480%2Fe.png?generation=1584592113807041&amp;alt=media)     | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2F7a2f830547a3a2b8f5a4daec2e0382f3%2Fg.png?generation=1584592111614129&amp;alt=media)        | ![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4114579%2Fb40309c1b75ade826b394b326fba9201%2Ff.png?generation=1584592114057138&amp;alt=media)                |     **0.8804**     |\n\n\n## Code\n\nThe reduced version of CycleGAN code is now available.\n\n1. https://www.kaggle.com/linshokaku/cyclegan-classifier\n   Font image classifier training code (7h)\n2. https://www.kaggle.com/linshokaku/cyclegan-training\n   Training code for a generator that converts a handwritten image to a font image (8h)\n3. https://www.kaggle.com/linshokaku/cyclegan-submission\n   Submission code\n\nRunning from 1 to 3 in order is equivalent to the method I used in this competition.\nDue to execution time and hardware resources, the batch size, training epoch, etc. are set very small, but if you run it with the hyper parameters as mentioned above, you should get results comparable to my execution results.\nI hope you find it helpful.",
    "776542": "This is kaggling at different level 👍 🙏 ",
    "783058": "The CycleGAN training code is now available. If you have any bugs or questions, please don't hesitate to ask.",
    "776514": "Congrats on the solo win and the amazing solution.  I think I'll need to read this again and again in the coming months to fully grasp what you did.",
    "779108": "Absolutely brilliant. I need to read and re-read this. This is much to learn here. Congrats on well deserved victory!",
    "778589": "I'm not sure whether you will see old reply again so I'm making a new one ;)\n\nCongratulation again and here's my questions:\n\n* You are using 2 effnet-b7 to predict seen/unseen and graphemes separately. Have you tried using a single model with 2 heads? Because it can save 20min for you.\n* Did you try arcface to detect unseen? Because it performs better than sigmoid in my case.\n* You are using effnet-b0 to predict generated hand written graphemes. Is it due to time limitation or big model doesn't work?\n* Seems that generators are taking much more time than effnet-b7. Did you tune the architecture of CycleGAN?\n* In your unseen graphemes pipeline, which is more important for improving performance? Generator or font classifier (effnet-b0)?\n",
    "776523": "Okay . I have never seen anything like this . I should read this multiple times , try to implement it and even then the brilliance of thinking of this solution at the first place would not be diminished by a bit . I am overwhelmed . Congrats !",
    "775880": "Guessed as such! Really elegant solution with deserving Top 1 results🎉 🎉 . Interesting to see the introduction of GAN into training pipeline! ",
    "776432": "Amazing stuff, congrats, looking froward to full writeup.\n\nWhat I am cruious about: you write in your profile that you are an expert in OCR. Is this something that you also have applied to other OCR tasks, or did the task at hand require a more custom-tailed solution?",
    "775905": "4 months on Kaggle and you are already killing it. Congrats on winning the competition and looking forward to your solution ",
    "776771": "Fantastic! What is the meaning of seen/unseen class? How do you get 1295 classes? ",
    "776357": "Congrats on your victory!\nI too had a similar idea. I wrote a selenium script to poll [this site](http://www.banglatext.com/text2image.html) and convert the grapheme texts to images.\n\nI am relatively new to Deep Learning (this is my first kaggle competition), so I do not know much about GAN's. Instead of using CycleGAN's, I used a custom DenseNet that I trained from scratch to perform the image-image translation. But I couldn't get an LB beyond 0.92.\n\nSo, thank you so much for posting about your methodology. It is honestly a huge inspiration and and sort of helps to verify my idea. So thank you once again!\n\nEdit: Also, can you point me to some good sources, which would help me start learning about GANs?",
    "775999": "dream solution!",
    "775967": "[question placeholder]\n\nCongratulation and wow, your illustration is fantastic, cant wait to see your full post!",
    "776204": "@linshokaku Congrats. \nWhat is your hardware setup like number of GPUs, memory?",
    "775946": "This solution is so elegant and thats why there is larger gap between you and others !",
    "812566": "First of all, Congrats for the win. Sorry for asking a naive question but thus zero shot learning means that we do nothing about the unseen classes at the time of training? If so, how is using ttf files and CycleGANs helping. I am not able to clearly grasp the idea. Can anyone please help me with it. Thanks in advance!",
    "786520": "Re: \"I predicted the relationship between the combination of labels and Grapheme from the label of the given train data, and created the following code.\"\n\nCan you please share an insight in to how did you end up creating this code please? ",
    "779241": "Great Solution",
    "778681": "Probably the best solution on Kaggle I've ever seen. Congrats! ",
    "778541": "Wao, my mind is blown, great work keep it up.👌 ",
    "778469": "Amazing!",
    "778315": "Great\n",
    "778010": "@deoxy Congrats on locking down 1st. I might have to try this out myself to understand this.\n It would be great if you can be a little more elaborative of the CycleGan pipeline. Thanks!\n\nI tried following one-shot approach and came up with my own recipe for producing all Grapheme combinations. Let me know your thoughts on this [kernel](https://www.kaggle.com/harshpatel1692/all-combinations-168-x-11-x-7-edge-cases)",
    "777978": "Congratulations. Your approach is interesting. Thanks for sharing.",
    "777766": "Congrats and thanks for sharing. I'm surprised that all class are treated differently and very interesting to know that GAN is combined for unseen classes!",
    "777667": "Congratulations ! Thank you for sharing solution.\nThis is so cool!",
    "777570": "Congratulations on your 1st place! It was a pleasure to read your elegant solution!",
    "777557": "Congratulations and thanks for the writeup. ",
    "777539": "Very elegant solution. Congrats!",
    "776785": "Congratulations and thanks for sharing. I believe I will go over it many times to digest those knowledge. Good chance to learn state-of-art image classification techniques. I cannot wait to see you full post. \n ",
    "776696": "congrats",
    "776694": "This is whole another level !",
    "776658": "wow, very nice man 👍 ",
    "776646": "few questions regarding part (1): \n- What is the criterion used here `loss = criterion(out, one_hot_label)` in the part (1) ?\n- you only used the green part of the data in this step right?\n- what is SVHN ?  all I could find is a house number dataset.",
    "776644": "Cngrats!! The solution is amazing",
    "776640": "Congrats on Winning the Competition. You spend quite alot money for GPU (Tesla V100)",
    "776616": "Upcoming bestfitting at Kaggle!",
    "776517": "Nice....\n\nToo much for me to grasp..",
    "776351": "Good job!!!",
    "776271": "congrats, very well deserved 1st place! really clean and elegant solution :) learned a lot through this competition. looking forward to seeing more details from your solution",
    "776246": "Amazing!!\nI am waiting for the details of the solution. I will review about GAN by then.",
    "776239": "Congrats. Excited to see details of your solution!",
    "776203": "Amazing! Hope you will write full post soon.",
    "776168": "Amazing solution!",
    "776152": "Wow it is amazing congratulations ",
    "776140": "great work🙌 ",
    "776091": "Congratulations.\nAnd will be waiting for your detail updates.",
    "775995": "Eagerly waiting to see your full updates. :) ",
    "775992": "o_O",
    "775934": "Cool! Amazing! Congrats! Waiting for your updates!",
    "775882": "Amazing congrats! Such a unique way to deal with unseen data!",
    "781246": "Congratulations !  And, thank you for sharing your wonderful solution.\n\nAbout the Out of Distribution Detection Model, I tried to implement your loss function, but this part of the calculation is exactly the same as BCLosswithLogitsLoss. Is there something wrong with it?\n\n`loss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()`\n\nHere's my code.\n```\ntarget = torch.tensor([[0,0,1,0], [0,1,0,0], [1,0,0,0]], dtype=torch.float32)\noutput = torch.randn_like(target, dtype=torch.float32)\nsig_out = output.sigmoid()\ncriterion = torch.nn.BCEWithLogitsLoss()\nloss = criterion(output, target)\nprint(loss)\ntrain_loss_position = (1-target)*(sig_out.detach() &gt; 0.1) + target\nloss = ((loss*train_loss_position).sum(dim=1)/train_loss_position.sum(dim=1)).mean()\nprint(loss)\n\ntensor(0.9078)\ntensor(0.9078)\n```\n\n\n",
    "778397": "congratulations for your first place and I have learnt something new from your solution.",
    "778202": "I leant much from your solution! And sorry to disturb the discussion area for my naive questions.  \n***\n**First**  \nIs that your processing can be describe like below(2 separated parts)?  \n- judge the image is seen or not\n- if seen, use the model train for seen to classify.  \nif not, feed GAN the image and generilize a data-like image. After that, feed the output of GAN to the font classifier and classify\nIs it right?\n\n**Second**  \n&gt; Using Pillow and raqm, I drew Graphheme in four sizes, [84, 96, 108, 120]. The size of the dataset is 59136.  \n\nThe mean of the sentence is that you train GAN based on the Grapheme which you drew on hand instead of the train data? And you drew 59136 pictures and save them as .ttf?(it's amazing!)  \n***\nCould you(or anyone who else) solve my doubts?\nThanks a lot!😄 ",
    "777930": "Congratulation!\nIs it possible to release your full code?\nFor Font Classifier Pre-training, why are you using EfficientNet-b0 instead of deeper model?",
    "777512": "Congratulations. Your approach is really interesting",
    "776701": "People are awesome. ",
    "776698": "\"However, as the hyperparameters were adjusted, it was observed that the generalization performance improved while the image became unnatural.\"\n\nthis is interesting.\n\nis there any GAN example with the input is font and output is handwritten image?",
    "776033": "why cyclegan, but no just generate new graphemes from noise? Adapt other dataset to competition data domain?\nlooking forward to a complete solution!",
    "778119": "Amazing!",
    "776265": "It is cool thing to see, that someone is using GAN s for this type of competition. I hope you will share code for GAN training. ",
    "775877": "wow～～",
    "784412": "",
    "959655": "Great idea !!",
    "892193": "Great stuff buddy....",
    "827626": "Excellent work!  What were some of the biggest challenges?",
    "792581": "Great",
    "792155": "@linshokaku I did not find any good benchmark for mixed precision training in generative models. Did you try mixed precision training for generative models? If used, how did it affect the accuracy/loss and speedup?",
    "790860": "Great!",
    "787679": "Great job!",
    "787494": "Many congratulations on the victory. Well deserved! 🙏 ",
    "785953": "Elegant solution!",
    "785846": "Congratulations!",
    "785549": "That's really interesting.",
    "784925": "amazing\n",
    "784561": "nice solution \n",
    "784418": "just asking, How did you get this idea of implementing GANs in this problem statement? ",
    "784094": "thx for sharing",
    "783720": "Impressive",
    "783575": "The beauty and intricacy of this art is one of the main reasons that compel me to pursue such career.",
    "783500": "Great job",
    "783108": "congrats!",
    "783094": "Cool! Thanks for releasing the code! Gonna give it a try!",
    "782561": "Amazing work!",
    "782552": "Wow, nice one. Congrats for Victory. Really helpful in my progress. Thanks a bunch for sharing solution.",
    "782377": "helpful",
    "781347": "Hi I am Anuj just started Kaggle and it is looking very promising",
    "781084": "zoo wee mama",
    "781012": "Wow! Looks very difficult",
    "780890": "Absolutely its really awesome",
    "780879": "Great job!",
    "780416": "nice",
    "780209": "Congrats!",
    "779648": "Congrats..It is very different.",
    "779375": "Congrates!\n",
    "779310": "Impressive",
    "779297": "woww",
    "779086": "I am new to Kaggle, but this looks really interesting!",
    "779077": "Learning a lot from this. Cheers!",
    "827061": "",
    "783577": "",
    "782263": "",
    "780589": "",
    "780587": "",
    "780101": "",
    "780062": "",
    "779343": "",
    "779045": "",
    "777947": "",
    "777976": "Wow! Thank  you 🙏 ",
    "777916": "Congrats! thanks for sharing",
    "845012": "This is helpful my solution! Thank you!",
    "806796": "Thanks for sharing",
    "783520": "thank you, it is very helpful",
    "782536": "Congrats. And thanks for sharing!",
    "780886": "very insteresting. Thanks a lot",
    "780319": "Congratulations.. Thanks for sharing👍 "
  }
}