{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":14897,"databundleVersionId":1020216,"sourceType":"competition"},{"sourceId":10873118,"sourceType":"datasetVersion","datasetId":6755607}],"dockerImageVersionId":30887,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **1.  Import**","metadata":{}},{"cell_type":"code","source":"ls ../input","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:27:51.754035Z","iopub.execute_input":"2025-03-04T19:27:51.754484Z","iopub.status.idle":"2025-03-04T19:27:51.885635Z","shell.execute_reply.started":"2025-03-04T19:27:51.754454Z","shell.execute_reply":"2025-03-04T19:27:51.884548Z"},"scrolled":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport joblib\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch\n\nfrom tqdm import tqdm\nfrom tqdm import tqdm_notebook\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\nfrom sklearn.metrics import recall_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:27:51.887009Z","iopub.execute_input":"2025-03-04T19:27:51.887327Z","iopub.status.idle":"2025-03-04T19:27:55.342963Z","shell.execute_reply.started":"2025-03-04T19:27:51.887304Z","shell.execute_reply":"2025-03-04T19:27:55.341983Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **2. Revise data**","metadata":{}},{"cell_type":"code","source":"!mkdir /kaggle/tmp\n!mkdir /kaggle/tmp/images","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:27:55.344667Z","iopub.execute_input":"2025-03-04T19:27:55.345062Z","iopub.status.idle":"2025-03-04T19:27:55.608424Z","shell.execute_reply.started":"2025-03-04T19:27:55.345040Z","shell.execute_reply":"2025-03-04T19:27:55.607585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dir = '../input/bengaliai-cv19/'\nfiles_train = [f'train_image_data_{fid}.parquet' for fid in range(4)]\n\nfor fname in files_train:\n    F = os.path.join(data_dir, fname)\n    df_train = pd.read_parquet(F)\n    img_ids = df_train['image_id'].values\n    img_array = df_train.iloc[:, 1:].values\n    for idx in range(len(df_train)):\n        img_id = img_ids[idx]\n        img = img_array[idx]\n        joblib.dump(img, os.path.join('/kaggle/tmp/images/', f'{img_id}.pkl'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:27:55.609807Z","iopub.execute_input":"2025-03-04T19:27:55.610030Z","iopub.status.idle":"2025-03-04T19:32:03.222374Z","shell.execute_reply.started":"2025-03-04T19:27:55.610010Z","shell.execute_reply":"2025-03-04T19:32:03.221265Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **3. Define Dataset, DataLoader**","metadata":{}},{"cell_type":"code","source":"HEIGHT = 137\nWIDTH = 236\nclass BengaliDataset(Dataset):\n    def __init__(self, csv, img_height, img_width, transform):\n        self.csv = csv.reset_index()\n        self.img_ids = csv['image_id'].values\n        self.img_height = img_height\n        self.img_width = img_width\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.csv)\n\n    def __getitem__(self, index):\n        img_id = self.img_ids[index]\n        img = joblib.load(f'/kaggle/tmp/images/{img_id}.pkl').astype(np.uint8)\n        img = img.reshape(HEIGHT, WIDTH)\n        img = 255 - img\n        img = img[:, :, np.newaxis]\n        img = np.repeat(img, 3, 2)\n        if self.transform is not None:\n            img = self.transform(image=img)['image']\n\n        label1 = self.csv.iloc[index].grapheme_root\n        label2 = self.csv.iloc[index].vowel_diacritic\n        label3 = self.csv.iloc[index].consonant_diacritic\n\n        return img, np.array([label1, label2, label3])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:03.223457Z","iopub.execute_input":"2025-03-04T19:32:03.223724Z","iopub.status.idle":"2025-03-04T19:32:03.230344Z","shell.execute_reply.started":"2025-03-04T19:32:03.223702Z","shell.execute_reply":"2025-03-04T19:32:03.229294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_augmentation = A.Compose(\n    [\n        A.Rotate(20),\n        A.Normalize(mean=0.5, std=1),\n        ToTensorV2()\n    ]\n)\n\nvalid_augmentation = A.Compose(\n    [\n        A.Normalize(mean=0.5, std=1),\n        ToTensorV2()\n    ]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:03.232222Z","iopub.execute_input":"2025-03-04T19:32:03.232536Z","iopub.status.idle":"2025-03-04T19:32:03.530259Z","shell.execute_reply.started":"2025-03-04T19:32:03.232499Z","shell.execute_reply":"2025-03-04T19:32:03.529325Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train = pd.read_csv(os.path.join('/kaggle/input/bengali', 'df_folds.csv'))\n\ntrn_fold = [i for i in range(6) if i not in [5]]\nvld_fold = [5]\n\ntrn_idx = df_train.loc[df_train['fold'].isin(trn_fold)].index\nvld_idx = df_train.loc[df_train['fold'].isin(vld_fold)].index\n\ntrn_dataset = BengaliDataset(csv=df_train.loc[trn_idx][:], img_height=137, img_width=236, transform=train_augmentation)\nvld_dataset = BengaliDataset(csv=df_train.loc[vld_idx][:], img_height=137, img_width=236, transform=valid_augmentation)\n\ntrn_loader = DataLoader(trn_dataset, shuffle=True, num_workers=4, batch_size=256)\nvld_loader = DataLoader(vld_dataset, shuffle=True, num_workers=4, batch_size=256)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:03.531241Z","iopub.execute_input":"2025-03-04T19:32:03.531556Z","iopub.status.idle":"2025-03-04T19:32:04.035141Z","shell.execute_reply.started":"2025-03-04T19:32:03.531533Z","shell.execute_reply":"2025-03-04T19:32:04.034464Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **4. Import pretrained model**","metadata":{}},{"cell_type":"code","source":"# -*- coding: utf-8 -*-\nfrom __future__ import print_function, division, absolute_import\nimport torchvision.models as models\nimport torch\nimport torch.utils.model_zoo as model_zoo\nimport torch.nn.functional as F\nimport types\nimport re\n\n#################################################################\n# You can find the definitions of those models here:\n# https://github.com/pytorch/vision/blob/master/torchvision/models\n#\n# To fit the API, we usually added/redefined some methods and\n# renamed some attributs (see below for each models).\n#\n# However, you usually do not need to see the original model\n# definition from torchvision. Just use `print(model)` to see\n# the modules and see bellow the `model.features` and\n# `model.classifier` definitions.\n#################################################################\n\n__all__ = [\n    'alexnet',\n    'densenet121', 'densenet169', 'densenet201', 'densenet161',\n    'resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152',\n    'inceptionv3',\n    'squeezenet1_0', 'squeezenet1_1',\n    'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn',\n    'vgg19_bn', 'vgg19'\n]\n\nmodel_urls = {\n    'alexnet': 'https://download.pytorch.org/models/alexnet-owt-4df8aa71.pth',\n    'densenet121': 'http://data.lip6.fr/cadene/pretrainedmodels/densenet121-fbdb23505.pth',\n    'densenet169': 'http://data.lip6.fr/cadene/pretrainedmodels/densenet169-f470b90a4.pth',\n    'densenet201': 'http://data.lip6.fr/cadene/pretrainedmodels/densenet201-5750cbb1e.pth',\n    'densenet161': 'http://data.lip6.fr/cadene/pretrainedmodels/densenet161-347e6b360.pth',\n    'inceptionv3': 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth',\n    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',\n    'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',\n    'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',\n    'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',\n    'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',\n    'squeezenet1_0': 'https://download.pytorch.org/models/squeezenet1_0-a815701f.pth',\n    'squeezenet1_1': 'https://download.pytorch.org/models/squeezenet1_1-f364aa15.pth',\n    'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth',\n    'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth',\n    'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth',\n    'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth',\n    'vgg11_bn': 'https://download.pytorch.org/models/vgg11_bn-6002323d.pth',\n    'vgg13_bn': 'https://download.pytorch.org/models/vgg13_bn-abd245e5.pth',\n    'vgg16_bn': 'https://download.pytorch.org/models/vgg16_bn-6c64b313.pth',\n    'vgg19_bn': 'https://download.pytorch.org/models/vgg19_bn-c79401a0.pth',\n    # 'vgg16_caffe': 'https://s3-us-west-2.amazonaws.com/jcjohns-models/vgg16-00b39a1b.pth',\n    # 'vgg19_caffe': 'https://s3-us-west-2.amazonaws.com/jcjohns-models/vgg19-d01eb7cb.pth'\n}\n\ninput_sizes = {}\nmeans = {}\nstds = {}\n\nfor model_name in __all__:\n    input_sizes[model_name] = [3, 224, 224]\n    means[model_name] = [0.485, 0.456, 0.406]\n    stds[model_name] = [0.229, 0.224, 0.225]\n\nfor model_name in ['inceptionv3']:\n    input_sizes[model_name] = [3, 299, 299]\n    means[model_name] = [0.5, 0.5, 0.5]\n    stds[model_name] = [0.5, 0.5, 0.5]\n\npretrained_settings = {}\n\nfor model_name in __all__:\n    pretrained_settings[model_name] = {\n        'imagenet': {\n            'url': model_urls[model_name],\n            'input_space': 'RGB',\n            'input_size': input_sizes[model_name],\n            'input_range': [0, 1],\n            'mean': means[model_name],\n            'std': stds[model_name],\n            'num_classes': 1000\n        }\n    }\n\n# for model_name in ['vgg16', 'vgg19']:\n#     pretrained_settings[model_name]['imagenet_caffe'] = {\n#         'url': model_urls[model_name + '_caffe'],\n#         'input_space': 'BGR',\n#         'input_size': input_sizes[model_name],\n#         'input_range': [0, 255],\n#         'mean': [103.939, 116.779, 123.68],\n#         'std': [1., 1., 1.],\n#         'num_classes': 1000\n#     }\n\ndef update_state_dict(state_dict):\n    # '.'s are no longer allowed in module names, but pervious _DenseLayer\n    # has keys 'norm.1', 'relu.1', 'conv.1', 'norm.2', 'relu.2', 'conv.2'.\n    # They are also in the checkpoints in model_urls. This pattern is used\n    # to find such keys.\n    pattern = re.compile(\n        r'^(.*denselayer\\d+\\.(?:norm|relu|conv))\\.((?:[12])\\.(?:weight|bias|running_mean|running_var))$')\n    for key in list(state_dict.keys()):\n        res = pattern.match(key)\n        if res:\n            new_key = res.group(1) + res.group(2)\n            state_dict[new_key] = state_dict[key]\n            del state_dict[key]\n    return state_dict\n\ndef load_pretrained(model, num_classes, settings):\n    assert num_classes == settings['num_classes'], \\\n        \"num_classes should be {}, but is {}\".format(settings['num_classes'], num_classes)\n\n    state_dict = torch.load('/kaggle/input/bengali/resnet34-333f7ec4.pth', weights_only=True)\n    state_dict = update_state_dict(state_dict)\n    model.load_state_dict(state_dict)\n    model.input_space = settings['input_space']\n    model.input_size = settings['input_size']\n    model.input_range = settings['input_range']\n    model.mean = settings['mean']\n    model.std = settings['std']\n    return model\n\n#################################################################\n# AlexNet\n\ndef modify_alexnet(model):\n    # Modify attributs\n    model._features = model.features\n    del model.features\n    model.dropout0 = model.classifier[0]\n    model.linear0 = model.classifier[1]\n    model.relu0 = model.classifier[2]\n    model.dropout1 = model.classifier[3]\n    model.linear1 = model.classifier[4]\n    model.relu1 = model.classifier[5]\n    model.last_linear = model.classifier[6]\n    del model.classifier\n\n    def features(self, input):\n        x = self._features(input)\n        x = x.view(x.size(0), 256 * 6 * 6)\n        x = self.dropout0(x)\n        x = self.linear0(x)\n        x = self.relu0(x)\n        x = self.dropout1(x)\n        x = self.linear1(x)\n        return x\n\n    def logits(self, features):\n        x = self.relu1(features)\n        x = self.last_linear(x)\n        return x\n\n    def forward(self, input):\n        x = self.features(input)\n        x = self.logits(x)\n        return x\n\n    # Modify methods\n    model.features = types.MethodType(features, model)\n    model.logits = types.MethodType(logits, model)\n    model.forward = types.MethodType(forward, model)\n    return model\n\ndef alexnet(num_classes=1000, pretrained='imagenet'):\n    r\"\"\"AlexNet model architecture from the\n    `\"One weird trick...\" <https://arxiv.org/abs/1404.5997>`_ paper.\n    \"\"\"\n    # https://github.com/pytorch/vision/blob/master/torchvision/models/alexnet.py\n    model = models.alexnet(pretrained=False)\n    if pretrained is not None:\n        settings = pretrained_settings['alexnet'][pretrained]\n        model = load_pretrained(model, num_classes, settings)\n    model = modify_alexnet(model)\n    return model\n\n###############################################################\n# DenseNets\n\ndef modify_densenets(model):\n    # Modify attributs\n    model.last_linear = model.classifier\n    del model.classifier\n\n    def logits(self, features):\n        x = F.relu(features, inplace=True)\n        x = F.avg_pool2d(x, kernel_size=7, stride=1)\n        x = x.view(x.size(0), -1)\n        x = self.last_linear(x)\n        return x\n\n    def forward(self, input):\n        x = self.features(input)\n        x = self.logits(x)\n        return x\n\n    # Modify methods\n    model.logits = types.MethodType(logits, model)\n    model.forward = types.MethodType(forward, model)\n    return model\n\n###############################################################\n# ResNets\n\ndef modify_resnets(model):\n    # Modify attributs\n    model.last_linear = model.fc\n    model.fc = None\n\n    def features(self, input):\n        x = self.conv1(input)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n        return x\n\n    def logits(self, features):\n        x = self.avgpool(features)\n        x = x.view(x.size(0), -1)\n        x = self.last_linear(x)\n        return x\n\n    def forward(self, input):\n        x = self.features(input)\n        x = self.logits(x)\n        return x\n\n    # Modify methods\n    model.features = types.MethodType(features, model)\n    model.logits = types.MethodType(logits, model)\n    model.forward = types.MethodType(forward, model)\n    return model\n\ndef resnet18(num_classes=1000, pretrained='imagenet'):\n    \"\"\"Constructs a ResNet-18 model.\n    \"\"\"\n    model = models.resnet18(pretrained=False)\n    if pretrained is not None:\n        settings = pretrained_settings['resnet18'][pretrained]\n        model = load_pretrained(model, num_classes, settings)\n    model = modify_resnets(model)\n    return model\n\ndef resnet34(num_classes=1000, pretrained='imagenet'):\n    \"\"\"Constructs a ResNet-34 model.\n    \"\"\"\n    model = models.resnet34(pretrained=False)\n    if pretrained is not None:\n        settings = pretrained_settings['resnet34'][pretrained]\n        model = load_pretrained(model, num_classes, settings)\n    model = modify_resnets(model)\n    return model","metadata":{"trusted":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-03-04T19:32:04.037947Z","iopub.execute_input":"2025-03-04T19:32:04.038192Z","iopub.status.idle":"2025-03-04T19:32:05.198951Z","shell.execute_reply.started":"2025-03-04T19:32:04.038171Z","shell.execute_reply":"2025-03-04T19:32:05.198296Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_name = 'resnet34'\nmodel = resnet34(pretrained='imagenet')\n\nin_features = model.last_linear.in_features\nmodel.last_linear = nn.Linear(in_features, 186)\n\nmodel.cuda()","metadata":{"trusted":true,"scrolled":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:05.202585Z","iopub.execute_input":"2025-03-04T19:32:05.202808Z","iopub.status.idle":"2025-03-04T19:32:07.616624Z","shell.execute_reply.started":"2025-03-04T19:32:05.202789Z","shell.execute_reply":"2025-03-04T19:32:07.615747Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\nloss_fn = nn.CrossEntropyLoss()\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', verbose=True, patience=7, factor=0.5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:07.617377Z","iopub.execute_input":"2025-03-04T19:32:07.617613Z","iopub.status.idle":"2025-03-04T19:32:07.622429Z","shell.execute_reply.started":"2025-03-04T19:32:07.617593Z","shell.execute_reply":"2025-03-04T19:32:07.621495Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **5. Train model**","metadata":{}},{"cell_type":"code","source":"best_score = -1\nfor epoch in range(1, 7):\n    train_loss = []\n    model.train()\n    \n    for inputs, targets in trn_loader:\n        inputs = inputs.cuda()\n        targets = targets.cuda()\n        logits = model(inputs)\n        \n        grapheme = logits[:, :168]\n        vowel = logits[:, 168:179]\n        cons = logits[:, 179:]\n        \n        loss = loss_fn(grapheme, targets[:, 0]) + loss_fn(vowel, targets[:, 1]) + loss_fn(cons, targets[:, 2])\n        \n        loss.backward()\n        \n        optimizer.step()\n        optimizer.zero_grad()\n        train_loss.append(loss.item())\n    \n    val_loss = []\n    val_true = []\n    val_pred = []\n    \n    model.eval()\n    \n    with torch.no_grad():\n        for inputs, targets in vld_loader:\n            inputs = inputs.cuda()\n            targets = targets.cuda()\n            \n            logits = model(inputs)\n            \n            grapheme = logits[:, :168]\n            vowel = logits[:, 168:179]\n            cons = logits[:, 179:]\n            \n            loss = loss_fn(grapheme, targets[:, 0]) + loss_fn(vowel, targets[:, 1]) + loss_fn(cons, targets[:, 2])\n            val_loss.append(loss.item())\n    \n            grapheme = grapheme.cpu().argmax(dim=1).data.numpy()\n            vowel = vowel.cpu().argmax(dim=1).data.numpy()\n            cons = cons.cpu().argmax(dim=1).data.numpy()\n            \n            val_true.append(targets.cpu().numpy())\n            val_pred.append(np.stack([grapheme, vowel, cons], axis=1))\n    \n    val_true = np.concatenate(val_true)\n    val_pred = np.concatenate(val_pred)\n    \n    val_loss = np.mean(val_loss)\n    train_loss = np.mean(train_loss)\n\n    score_g = recall_score(val_true[:, 0], val_pred[:, 0], average='macro')\n    score_v = recall_score(val_true[:, 1], val_pred[:, 1], average='macro')\n    score_c = recall_score(val_true[:, 2], val_pred[:, 2], average='macro')\n\n    final_score = np.average([score_g, score_v, score_c], weights=[2, 1, 1])\n\n    if final_score > best_score:\n        best_score = final_score\n\n        state_dict = model.cpu().state_dict()\n        model = model.cuda()\n        torch.save(state_dict, os.path.join('/kaggle/working/', \"model.pt\"))\n\n    print(f'epoch {epoch}')\n    print(f'train_loss: {train_loss:.5f}; val_loss: {val_loss:.5f}; score: {final_score:.5f}')\n    print(f'score_g: {score_g:.5f}; score_v: {score_v:.5f}; score_c: {score_c:.5f}\\n')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T19:32:07.623256Z","iopub.execute_input":"2025-03-04T19:32:07.623450Z","iopub.status.idle":"2025-03-04T20:38:04.553383Z","shell.execute_reply.started":"2025-03-04T19:32:07.623434Z","shell.execute_reply":"2025-03-04T20:38:04.552183Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **6. Make Submission**","metadata":{}},{"cell_type":"code","source":"!mkdir /kaggle/tmp/images/test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T20:38:04.554646Z","iopub.execute_input":"2025-03-04T20:38:04.555014Z","iopub.status.idle":"2025-03-04T20:38:04.833947Z","shell.execute_reply.started":"2025-03-04T20:38:04.554976Z","shell.execute_reply":"2025-03-04T20:38:04.832661Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dir = '../input/bengaliai-cv19/'\nfiles_test = [f'test_image_data_{fid}.parquet' for fid in range(4)]\n\ndf_test = pd.read_csv(os.path.join(data_dir, 'test.csv'))\ndf_test.head()\ndf_test['id'] = df_test['image_id'].apply(lambda x: int(x.split('_')[1]))\n\ndf_test.to_csv(os.path.join('/kaggle/working/', 'df_test.csv'), index=False)\n\nfor fname in files_test:\n    F = os.path.join(data_dir, fname)\n    df_test = pd.read_parquet(F)\n    img_ids = df_test['image_id'].values\n    img_array = df_test.iloc[:, 1:].values\n    for idx in range(len(df_test)):\n        img_id = img_ids[idx]\n        img = img_array[idx]\n        joblib.dump(img, os.path.join('/kaggle/tmp/images/test/', f'{img_id}.pkl'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T20:38:04.835228Z","iopub.execute_input":"2025-03-04T20:38:04.835573Z","iopub.status.idle":"2025-03-04T20:38:11.694556Z","shell.execute_reply.started":"2025-03-04T20:38:04.835538Z","shell.execute_reply":"2025-03-04T20:38:11.693857Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_test = pd.read_csv(os.path.join(data_dir, 'test.csv'))\n\ndf_submit = pd.DataFrame()\ndf_submit['row_id'] = df_test['row_id']\ndf_submit['target'] = -1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T20:38:11.695326Z","iopub.execute_input":"2025-03-04T20:38:11.695590Z","iopub.status.idle":"2025-03-04T20:38:11.708256Z","shell.execute_reply.started":"2025-03-04T20:38:11.695567Z","shell.execute_reply":"2025-03-04T20:38:11.707393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.load_state_dict(torch.load(os.path.join('/kaggle/working/', \"model.pt\"), weights_only=True))\nwith torch.no_grad():\n    for index, row_id, image_id, component in df_test.itertuples():\n        img = joblib.load(f'/kaggle/tmp/images/test/{image_id}.pkl').astype(np.uint8)\n        img = img.reshape(HEIGHT, WIDTH)\n        img = 255 - img\n        img = img[:, :, np.newaxis]\n        img = np.repeat(img, 3, 2)\n        img = valid_augmentation(image=img)['image']\n\n        inputs = img.unsqueeze(dim=0).cuda()\n        \n        logits = model(inputs)\n        \n        grapheme = logits[0, :168]\n        vowel = logits[0, 168:179]\n        cons = logits[0, 179:]\n        \n        grapheme = grapheme.cpu().argmax(dim=0).data.numpy()\n        vowel = vowel.cpu().argmax(dim=0).data.numpy()\n        cons = cons.cpu().argmax(dim=0).data.numpy()\n\n        if component == \"grapheme_root\":\n            df_submit.loc[index, 'target'] = grapheme\n        elif component == \"vowel_diacritic\":\n            df_submit.loc[index, 'target'] = vowel\n        elif component == \"consonant_diacritic\":\n            df_submit.loc[index, 'target'] = cons\n\ndf_submit.to_csv(os.path.join('/kaggle/working/', 'submission.csv'), index=False)","metadata":{"trusted":true,"scrolled":true,"execution":{"iopub.status.busy":"2025-03-04T20:38:11.709287Z","iopub.execute_input":"2025-03-04T20:38:11.709620Z","iopub.status.idle":"2025-03-04T20:38:12.156879Z","shell.execute_reply.started":"2025-03-04T20:38:11.709587Z","shell.execute_reply":"2025-03-04T20:38:12.155962Z"}},"outputs":[],"execution_count":null}]}