{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport glob\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom PIL import Image\nimport cv2\nimport tensorflow as tf\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader, WeightedRandomSampler\nfrom torch.optim.lr_scheduler import CosineAnnealingLR\nfrom torchvision import models\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom sklearn.metrics import f1_score\nimport io\n\n# Define paths to TFRecord files\ntrain_files = '/kaggle/input/tpu-getting-started/tfrecords-jpeg-224x224/train/*.tfrec'\nvalid_files = '/kaggle/input/tpu-getting-started/tfrecords-jpeg-224x224/val/*.tfrec'\ntest_files = '/kaggle/input/tpu-getting-started/tfrecords-jpeg-224x224/test/*.tfrec'\n\n# Device selection\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# Constants\nn_epochs = 15\nbatch_size = 20\nval_batch_size = 16\nnum_prints = 10\ntrain_size = 12753\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:16.947887Z","iopub.execute_input":"2024-06-23T17:11:16.948291Z","iopub.status.idle":"2024-06-23T17:11:39.317186Z","shell.execute_reply.started":"2024-06-23T17:11:16.948255Z","shell.execute_reply":"2024-06-23T17:11:39.315863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Helper function to parse TFRecords into DataFrame\ndef tfdf_to_pddf(file_path, test=False):\n    def parse(pb, test=False):\n        features = {'id': tf.io.FixedLenFeature([], tf.string), 'image': tf.io.FixedLenFeature([], tf.string)}\n        if not test:\n            features['class'] = tf.io.FixedLenFeature([], tf.int64)\n        return tf.io.parse_single_example(pb, features)\n\n    df = {'id': [], 'image': []}\n    if not test:\n        df['class'] = []\n\n    dataset = tf.data.TFRecordDataset(glob.glob(file_path))\n    for sample in dataset.map(lambda pb: parse(pb, test)):\n        df['id'].append(sample['id'].numpy().decode('utf-8'))\n        df['image'].append(sample['image'].numpy())\n        if not test:\n            df['class'].append(sample['class'].numpy())\n    return pd.DataFrame(df)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:39.319527Z","iopub.execute_input":"2024-06-23T17:11:39.320418Z","iopub.status.idle":"2024-06-23T17:11:39.330919Z","shell.execute_reply.started":"2024-06-23T17:11:39.320372Z","shell.execute_reply":"2024-06-23T17:11:39.329753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Dataset class with transformations\nclass TransformDataset(Dataset):\n    def __init__(self, files, frac=1.0, test=False):\n        super().__init__()\n        if not (0 < frac <= 1):\n            raise ValueError(\"Fraction must be between 0 and 1.\")\n\n        self.df = tfdf_to_pddf(files, test).sample(frac=frac).reset_index(drop=True)\n        self.test = test\n        self.transformations = A.Compose([\n            A.Resize(300, 300),\n            A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n            ToTensorV2()\n        ])\n        if not self.test:\n            if 'class' not in self.df.columns:\n                raise AttributeError(\"Label column 'class' is missing from the DataFrame.\")\n            self.labels = self.df['class'].values\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        image = cv2.imdecode(np.frombuffer(row['image'], np.uint8), cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        transformed_image = self.transformations(image=image)['image']\n        label = row['class'] if not self.test else row['id']\n        return transformed_image, label\n\n    def get_weights(self):\n        if hasattr(self, 'labels'):\n            class_sample_count = np.array([len(np.where(self.labels == t)[0]) for t in np.unique(self.labels)])\n            weight = 1. / class_sample_count\n            samples_weight = np.array([weight[t] for t in self.labels])\n            return torch.from_numpy(samples_weight).double()\n        else:\n            raise RuntimeError(\"Attempting to calculate weights, but 'labels' are not set.\")\n\n    def weighted_loader(self, batch_size, num_workers=0):\n        weights = self.get_weights()\n        sampler = WeightedRandomSampler(weights, num_samples=len(weights), replacement=True)\n        return DataLoader(self, batch_size=batch_size, sampler=sampler, num_workers=num_workers)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:39.332312Z","iopub.execute_input":"2024-06-23T17:11:39.332838Z","iopub.status.idle":"2024-06-23T17:11:39.349008Z","shell.execute_reply.started":"2024-06-23T17:11:39.332776Z","shell.execute_reply":"2024-06-23T17:11:39.347752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# EfficientNet model with various configurations\nclass EfficientNetModel(nn.Module):\n    def __init__(self, n_classes, learnable_modules=None, dropout_rate=0.5, pretrained=True):\n        super().__init__()\n        self.efficientnet_b0 = models.efficientnet_b0(pretrained=pretrained)\n        self.dropout = nn.Dropout(p=dropout_rate)\n        self.efficientnet_b0.classifier = nn.Sequential(\n            nn.Dropout(p=dropout_rate),\n            nn.Linear(self.efficientnet_b0.classifier[1].in_features, n_classes)\n        )\n        if learnable_modules is None:\n            learnable_modules = ['features.5.2', 'features.6', 'features.7', 'features.8', 'classifier']\n        for param in self.efficientnet_b0.parameters():\n            param.requires_grad = False\n        for name, module in self.efficientnet_b0.named_modules():\n            if any(sub in name for sub in learnable_modules):\n                for param in module.parameters():\n                    param.requires_grad = True\n\n    def forward(self, x):\n        x = self.efficientnet_b0.features(x)\n        x = self.efficientnet_b0.avgpool(x)\n        x = torch.flatten(x, 1)\n        x = self.efficientnet_b0.classifier(x)\n        return F.log_softmax(x, dim=1)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:39.351419Z","iopub.execute_input":"2024-06-23T17:11:39.351828Z","iopub.status.idle":"2024-06-23T17:11:39.367073Z","shell.execute_reply.started":"2024-06-23T17:11:39.351786Z","shell.execute_reply":"2024-06-23T17:11:39.365860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Training and validation setup\ntrain_set = TransformDataset(files=train_files, test=False)\ntrain_loader = train_set.weighted_loader(batch_size=batch_size, num_workers=2)\nvalid_set = TransformDataset(files=valid_files, frac=0.20, test=False)\nvalid_loader = DataLoader(valid_set, batch_size=val_batch_size, shuffle=False, num_workers=2)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:39.368967Z","iopub.execute_input":"2024-06-23T17:11:39.369422Z","iopub.status.idle":"2024-06-23T17:11:50.236494Z","shell.execute_reply.started":"2024-06-23T17:11:39.369357Z","shell.execute_reply":"2024-06-23T17:11:50.235443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Model initialization\nmodel = nn.DataParallel(EfficientNetModel(n_classes=104)).to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4, weight_decay=1e-4)\nscheduler = CosineAnnealingLR(optimizer, T_max=n_epochs)\nloss_fn = torch.nn.functional.nll_loss\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:50.237792Z","iopub.execute_input":"2024-06-23T17:11:50.238130Z","iopub.status.idle":"2024-06-23T17:11:51.096751Z","shell.execute_reply.started":"2024-06-23T17:11:50.238100Z","shell.execute_reply":"2024-06-23T17:11:51.095483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training loop\nfor epoch in range(n_epochs):\n    model.train()\n    for i, (x, y) in enumerate(train_loader):\n        x, y = x.to(device), y.to(device)\n        optimizer.zero_grad()\n        output = model(x)\n        loss = loss_fn(output, y)\n        loss.backward()\n        optimizer.step()\n\n    # Validation\n    model.eval()\n    valid_true_labs, valid_pred_labs = [], []\n    with torch.no_grad():\n        for x, y in valid_loader:\n            x, y = x.to(device), y.to(device)\n            outputs = model(x)\n            valid_pred_labs.extend(outputs.argmax(dim=1).tolist())\n            valid_true_labs.extend(y.tolist())\n\n    valid_f1 = f1_score(valid_true_labs, valid_pred_labs, average='weighted')\n    print(f'Epoch {epoch}: Validation F1: {valid_f1 * 100:.2f}%')\n    scheduler.step()\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T17:11:51.097892Z","iopub.execute_input":"2024-06-23T17:11:51.098307Z","iopub.status.idle":"2024-06-23T19:48:56.742758Z","shell.execute_reply.started":"2024-06-23T17:11:51.098268Z","shell.execute_reply":"2024-06-23T19:48:56.740906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Testing and submission\ntest_set = TransformDataset(files=test_files, test=True)\ntest_loader = DataLoader(test_set, batch_size=val_batch_size, shuffle=False, num_workers=2)\n\nmodel.eval()\nids, predicted_labels = [], []\nwith torch.no_grad():\n    for x, batch_ids in test_loader:\n        x = x.to(device)\n        output = model(x)\n        predicted_labels.extend(output.argmax(dim=1).cpu().numpy())\n        ids.extend(batch_ids)\n\nsubmission = pd.DataFrame({'id': ids, 'label': predicted_labels})\nsubmission.to_csv('submission.csv', index=False)\nprint(submission.head())\n","metadata":{"execution":{"iopub.status.busy":"2024-06-23T19:49:26.045609Z","iopub.execute_input":"2024-06-23T19:49:26.046012Z","iopub.status.idle":"2024-06-23T19:55:34.236812Z","shell.execute_reply.started":"2024-06-23T19:49:26.045978Z","shell.execute_reply":"2024-06-23T19:55:34.235434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}