{"cells":[{"metadata":{},"cell_type":"markdown","source":"Turns out if you train multiple models for grapheme_root, vowel, and consonant you can get private lb score as high as 0.93\nhere i have used a b7 on tpu for 40 epochs with batch_size 1024 and mixup for grapheme_root and couple of b3s with same config for vowel and consonant. On tpu it takes <8h to train. The inference is not the most efficient though.\n\nOriginal training code : https://www.kaggle.com/seesee/2-train"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"!pip install ../input/kaggle-efficientnet-repo/efficientnet-1.0.0-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np  # noqa\nimport pandas as pd\nimport argparse\nimport tensorflow as tf\nfrom tqdm.auto import tqdm\n\nfrom tensorflow.keras import layers as L\nimport efficientnet.tfkeras as efn\n\n\ndef normalize(image):\n  # https://github.com/tensorflow/tpu/blob/master/models/official/efficientnet/main.py#L325-L326\n  # https://github.com/tensorflow/tpu/blob/master/models/official/efficientnet/efficientnet_builder.py#L31-L32\n  image -= tf.constant([0.485 * 255, 0.456 * 255, 0.406 * 255])  # RGB\n  image /= tf.constant([0.229 * 255, 0.224 * 255, 0.225 * 255])  # RGB\n  return image\n\n\ndef get_model_grapheme(input_size, backbone='efficientnet-b7', weights='imagenet', tta=False):\n  print(f'Using backbone {backbone} and weights {weights}')\n  x = L.Input(shape=input_size, name='imgs', dtype='float32')\n  y = normalize(x)\n  if backbone.startswith('efficientnet'):\n    model_fn = getattr(efn, f'EfficientNetB{backbone[-1]}')\n\n  y = model_fn(input_shape=input_size, weights=weights, include_top=False)(y)\n  y = L.GlobalAveragePooling2D()(y)\n  # 1292 of 1295 are present\n  l1 = L.Dense(168, activation='softmax', name='l1')(y)\n  model = tf.keras.Model(x, outputs=[l1])\n\n  return model\n\ndef get_model_consonant(input_size, backbone='efficientnet-b3', weights='imagenet', tta=False):\n  print(f'Using backbone {backbone} and weights {weights}')\n  x = L.Input(shape=input_size, name='imgs', dtype='float32')\n  y = normalize(x)\n  if backbone.startswith('efficientnet'):\n    model_fn = getattr(efn, f'EfficientNetB{backbone[-1]}')\n\n  y = model_fn(input_shape=input_size, weights=weights, include_top=False)(y)\n  y = L.GlobalAveragePooling2D()(y)\n  #y = L.Dropout(0.2)(y)\n  # 1292 of 1295 are present\n  #y = L.Dense(168, activation='softmax')(y)\n  #y= L.Dense(11, activation='softmax')(y)\n  y= L.Dense(7, activation='softmax')(y) \n  #l1 = L.Dense(11,)\n  #l2 =  \n  model = tf.keras.Model(x, y)\n    \n  return model\n\n\ndef get_model_vowel(input_size, backbone='efficientnet-b3', weights='imagenet', tta=False):\n  print(f'Using backbone {backbone} and weights {weights}')\n  x = L.Input(shape=input_size, name='imgs', dtype='float32')\n  y = normalize(x)\n  if backbone.startswith('efficientnet'):\n    model_fn = getattr(efn, f'EfficientNetB{backbone[-1]}')\n\n  y = model_fn(input_shape=input_size, weights=weights, include_top=False)(y)\n  y = L.GlobalAveragePooling2D()(y)\n  #y = L.Dropout(0.2)(y)\n  # 1292 of 1295 are present\n  #y = L.Dense(168, activation='softmax')(y)\n  y= L.Dense(11, activation='softmax')(y)\n  #l2= L.Dense(7, activation='softmax')(y) \n\n  model = tf.keras.Model(x,y)\n  \n  return model\n\n\nimport cv2\nimport numpy as np\nimport os\n\n\ndef normalize_image(img, org_width, org_height, new_width, new_height):\n  # Invert\n  img = 255 - img\n  # Normalize\n  img = (img * (255.0 / img.max())).astype(np.uint8)\n  # Reshape\n  img = img.reshape(org_height, org_width)\n  image_resized = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_LINEAR)\n  return image_resized\n\n\ndef dump_images(args, org_width, org_height, new_width, new_height):\n  labels = pd.read_csv(args.labels)\n  iids = labels['image_id']\n  root = labels['grapheme_root']\n  vowel = labels['vowel_diacritic']\n  consonant = labels['consonant_diacritic']\n  labels = {a: (b, c, d) for a, b, c, d in zip(iids, root, vowel, consonant)}\n  tuples = sorted(set(labels.values()))\n  tuples_to_int = {v: k for k, v in enumerate(tuples)}\n  print(f'Got {len(tuples)} unique combinations')\n  for i in tqdm(range(0, 4)):\n    df = pd.read_parquet(args.data_template % i)\n    image_ids = df['image_id'].values\n    df = df.drop(['image_id'], axis=1)\n    for image_id, index in tqdm(zip(image_ids, range(df.shape[0])), total=df.shape[0]):\n      normalized = normalize_image(df.loc[df.index[index]].values,\n          org_width, org_height, new_width, new_height)\n      r, v, c = labels[image_id]\n      tuple_int = tuples_to_int[(r, v, c)]\n      # e.g: 'Train_300_rt_29_vl_5_ct_0_ti_179.png'\n      out_fn = os.path.join(args.image_dir, f'{image_id}_rt_{r}_vl_{v}_ct_{c}_ti_{tuple_int}.png')\n      cv2.imwrite(out_fn, normalized)\n\n\ndef decode_predictions(y_pred, inv_tuple_map):\n  # return predictions as tuple (root, vowel, consonant)\n  y_argmax = np.argmax(y_pred, -1)\n  decoded = []\n  for yy in y_argmax:\n    decoded.append(inv_tuple_map[int(yy)])\n  return decoded\n\n\ndef decode_predictions_v2(y_pred1,y_pred2,y_pred3):\n  # return predictions as tuple (root / 168, vowel / 11, consonant / 7) & ti 1292\n\n  decoded = []\n  for k in range(y_pred1.shape[0]):\n    rr=y_pred1[k]\n    vv=y_pred2[k]\n    cc=y_pred3[k]\n    \n    rr = rr.argmax(-1)\n    vv = vv.argmax(-1)\n    cc = cc.argmax(-1)\n    decoded.append((rr, vv, cc))\n\n  return decoded\n\n\ndef process_batch(image_id_batch, img_batch, row_id, target, model1, model2, model3):\n  img_batch = np.float32(img_batch)\n  # deal with single image\n  if img_batch.ndim != 4:\n    img_batch = np.expand_dims(img_batch, 0)\n  \n  y_pred1 = model1.predict(img_batch)\n  y_pred2 = model2.predict(img_batch)\n  y_pred3 = model3.predict(img_batch)\n  decoded = decode_predictions_v2(y_pred1,y_pred2,y_pred3)\n  for iid, dd in zip(image_id_batch, decoded):\n    row_id.append(iid + '_grapheme_root')\n    target.append(dd[0])\n    row_id.append(iid + '_vowel_diacritic')\n    target.append(dd[1])\n    row_id.append(iid + '_consonant_diacritic')\n    target.append(dd[2])\n\n\ndef main():\n  parser = argparse.ArgumentParser()\n  parser.add_argument('--seed', type=int, default=123)\n  parser.add_argument('--input_size', type=str, default='224,224')\n  parser.add_argument('--batch_size', type=int, default=32)\n  parser.add_argument('--backbone', type=str, default='efficientnet-b7')\n  parser.add_argument('--weights', type=str, default='../input/b3out3/efficientb3_weights00000040.h5')\n  args, _ = parser.parse_known_args()\n\n  org_height = 137\n  org_width = 236\n  args.input_size = tuple(int(x) for x in args.input_size.split(','))\n  np.random.seed(args.seed)\n  tf.random.set_seed(args.seed)\n\n  model1 = get_model_grapheme(input_size=args.input_size + (3, ),\n      weights=None)\n  \n  model2 = get_model_vowel(input_size=args.input_size + (3, ),\n      weights=None)\n  \n  model3 = get_model_consonant(input_size=args.input_size + (3, ),\n      weights=None)\n\n  print(f'Loading weights {args.weights}')\n  model1.load_weights('../input/separatemodels/graphemeb7.h5')\n  model2.load_weights('../input/vowelconsonant/weights00000096.h5')#vowel model\n  model3.load_weights('../input/vowelconsonant/weights00000080.h5')  #consonant model\n  #print(model.summary())\n  row_id, target = [], []\n  image_id_batch, img_batch = [], []\n  for i in tqdm(range(4)):\n    parquet_fn = f'../input/bengaliai-cv19/test_image_data_{i}.parquet'\n    df = pd.read_parquet(parquet_fn)\n    image_ids = df['image_id'].values\n    df = df.drop(['image_id'], axis=1)\n    for k in range(len(image_ids)):\n      image_id = image_ids[k]\n      img = df.iloc[k].values\n      img = normalize_image(img, org_width, org_height, args.input_size[1], args.input_size[0])\n      img_batch.append(np.dstack([img] * 3))\n      image_id_batch.append(image_id)\n      if len(img_batch) >= args.batch_size:\n        process_batch(image_id_batch, img_batch, row_id, target, model1, model2, model3)\n        image_id_batch, img_batch = [], []\n\n  # process remaining batch\n  if len(img_batch) > 0:\n    process_batch(image_id_batch, img_batch, row_id, target, model1, model2, model3)\n    image_id_batch, img_batch = [], []\n\n  sub_fn = 'submission.csv'\n  sub = pd.DataFrame({'row_id': row_id, 'target': target})\n  sub.to_csv(sub_fn, index=False)\n  print(f'Done wrote to {sub_fn}')\n\nmain()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!head submission.csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!wc -l submission.csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}