{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-03-31T04:06:07.553136Z","iopub.execute_input":"2023-03-31T04:06:07.553589Z","iopub.status.idle":"2023-03-31T04:12:01.876538Z","shell.execute_reply.started":"2023-03-31T04:06:07.553557Z","shell.execute_reply":"2023-03-31T04:12:01.875536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport math\nimport timm\nimport json\nimport torch\nimport warnings\nimport torchvision\nimport pandas as pd\nfrom PIL import Image\nfrom pathlib import Path\nfrom torchvision import io\nimport torch.optim as optim\nfrom torch import nn, Tensor\nfrom tqdm.notebook import tqdm\nimport matplotlib.pyplot as plt\nimport torchvision.models as models\nfrom torch.utils.data import DataLoader\nfrom torchvision import transforms as T\nimport torchvision.transforms as transforms\nfrom torch.optim.lr_scheduler import StepLR\nfrom sklearn import model_selection, metrics\n\nplt.style.use('fivethirtyeight')\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class MLP(nn.Module):\n    def __init__(self, dim, hidden_dim, out_dim=None) -> None:\n        super().__init__()\n        out_dim = out_dim or dim\n        self.fc1 = nn.Linear(dim, hidden_dim)\n        self.act = nn.GELU()\n        self.fc2 = nn.Linear(hidden_dim, out_dim)\n    def forward(self, x: Tensor):\n        return self.fc2(self.act(self.fc1(x)))\n\nclass PatchEmbedding(nn.Module):\n  \"\"\"\n  Image to Patch Embedding\n  \"\"\"\n  def __init__(self, img_size=224, patch_size=16, embed_dim=768):\n    super().__init__()\n    assert img_size % patch_size == 0, 'Image size must be divisible by patch size'\n\n    img_size = (img_size, img_size) if isinstance(img_size, int) else img_size\n    \n    self.grid_size = (img_size[0] // patch_size, img_size[1] // patch_size)\n    self.num_patches = self.grid_size[0] * self.grid_size[1]\n    self.proj = nn.Conv2d(3, embed_dim, patch_size, patch_size)\n  \n  def forward(self, x: torch.Tensor):\n    x = self.proj(x)                # b x hidden_dim x 14 x 14   \n    x = x.flatten(2).swapaxes(1,2)  # b x (14*14) x hidden_dim","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:05.033992Z","iopub.execute_input":"2023-03-31T04:12:05.034671Z","iopub.status.idle":"2023-03-31T04:12:05.047793Z","shell.execute_reply.started":"2023-03-31T04:12:05.034624Z","shell.execute_reply":"2023-03-31T04:12:05.046355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DropPath(nn.Module):\n    def __init__(self, p):\n        super().__init__()\n        self.p = p\n    \n    def forward(self, x):\n        if self.p == 0 or not self.training:\n            return x\n        kp = 1 - self.p\n        shape = (x.shape[0],) + (1,)*(x.ndim - 1)\n        random_tensor = kp + torch.rand(shape, dtype=x.dtype, device=x.device) #0->1\n        random_tensor.floor_() #binarize\n        return x.div(kp) * random_tensor\n","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:05.051953Z","iopub.execute_input":"2023-03-31T04:12:05.052698Z","iopub.status.idle":"2023-03-31T04:12:05.062786Z","shell.execute_reply.started":"2023-03-31T04:12:05.052641Z","shell.execute_reply":"2023-03-31T04:12:05.061749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch import nn, Tensor\n\n\nclass LayerNorm(nn.Module):\n    def __init__(self, normalized_shape, eps=1e-6):\n        super().__init__()\n        self.weight = nn.Parameter(torch.ones(normalized_shape))\n        self.bias = nn.Parameter(torch.zeros(normalized_shape))\n        self.eps = eps\n\n    def forward(self, x):\n        u = x.mean(1, keepdim=True)\n        s = (x - u).pow(2).mean(1, keepdim=True)\n        x = (x - u) / torch.sqrt(s + self.eps)\n        x = self.weight[:, None, None] * x + self.bias[:, None, None]\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:05.064211Z","iopub.execute_input":"2023-03-31T04:12:05.064754Z","iopub.status.idle":"2023-03-31T04:12:05.074813Z","shell.execute_reply.started":"2023-03-31T04:12:05.064713Z","shell.execute_reply":"2023-03-31T04:12:05.073181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LayerNorm(nn.Module):\n    \"\"\"Channel first layer norm\n    \"\"\"\n    def __init__(self, normalized_shape, eps=1e-6) -> None:\n        super().__init__()\n        self.weight = nn.Parameter(torch.ones(normalized_shape))\n        self.bias = nn.Parameter(torch.zeros(normalized_shape))\n        self.eps = eps\n\n    def forward(self, x: Tensor) -> Tensor:\n        u = x.mean(1, keepdim=True)\n        s = (x - u).pow(2).mean(1, keepdim=True)\n        x = (x - u) / torch.sqrt(s + self.eps)\n        x = self.weight[:, None, None] * x + self.bias[:, None, None]\n        return x\n\n    \nclass Block(nn.Module):\n    def __init__(self, dim, dpr=0., init_value=1e-6):\n        super().__init__()\n        self.dwconv = nn.Conv2d(dim, dim, 7, 1, 3, groups=dim)\n        self.norm = nn.LayerNorm(dim, eps=1e-6)\n        self.pwconv1 = nn.Linear(dim, 4*dim)\n        self.act = nn.GELU()\n        self.pwconv2 = nn.Linear(4*dim, dim)\n        self.gamma = nn.Parameter(init_value * torch.ones((dim)), requires_grad=True) if init_value > 0 else None\n        self.drop_path = DropPath(dpr) if dpr > 0. else nn.Identity()\n\n    def forward(self, x: Tensor) -> Tensor:\n        input = x\n        x = self.dwconv(x)\n        x = x.permute(0, 2, 3, 1)   # NCHW to NHWC\n        x = self.norm(x)\n        x = self.pwconv1(x)\n        x = self.act(x)\n        x = self.pwconv2(x)\n\n        if self.gamma is not None:\n            x = self.gamma * x\n        \n        x = x.permute(0, 3, 1, 2)\n        x = input + self.drop_path(x)\n        return x\n\n\nclass Stem(nn.Sequential):\n    def __init__(self, c1, c2, k, s):\n        super().__init__(\n            nn.Conv2d(c1, c2, k, s),\n            LayerNorm(c2)\n        )\n\n\nclass Downsample(nn.Sequential):\n    def __init__(self, c1, c2, k, s):\n        super().__init__(\n            LayerNorm(c1),\n            nn.Conv2d(c1, c2, k, s)\n        )\n\n\nconvnext_settings = {\n    'T': [[3, 3, 9, 3], [96, 192, 384, 768]],       # [depths, dims]\n    'S': [[3, 3, 27, 3], [96, 192, 384, 768]],\n    'B': [[3, 3, 27, 3], [128, 256, 512, 1024]]\n}\n\n\nclass ConvNeXt(nn.Module):     \n    def __init__(self, model_name: str = 'B', pretrained: str = None, num_classes: int = 1000, *args, **kwargs) -> None:\n        super().__init__()\n        assert model_name in convnext_settings.keys(), f\"ConvNeXt model name should be in {list(convnext_settings.keys())}\"\n        depths, embed_dims = convnext_settings[model_name]\n        drop_path_rate = 0.\n    \n        self.downsample_layers = nn.ModuleList([\n            Stem(3, embed_dims[0], 4, 4),\n            *[Downsample(embed_dims[i], embed_dims[i+1], 2, 2) for i in range(3)]\n        ])\n\n        self.stages = nn.ModuleList()\n        dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]\n        cur = 0\n\n        for i in range(4):\n            stage = nn.Sequential(*[\n                Block(embed_dims[i], dpr[cur+j])\n            for j in range(depths[i])])\n            self.stages.append(stage)\n            cur += depths[i]\n\n        self.norm = nn.LayerNorm(embed_dims[-1], eps=1e-6)\n        self.head = nn.Linear(embed_dims[-1], num_classes)\n\n        # use as a backbone\n        # for i in range(4):\n        #     self.add_module(f\"norm{i}\", LayerNorm(embed_dims[i]))\n\n        self._init_weights(pretrained)\n\n    def _init_weights(self, pretrained: str = None) -> None:\n        if pretrained:\n            try:\n                self.load_state_dict(torch.load(pretrained, map_location='cpu')['model'])\n            except RuntimeError:\n                pretrained_dict = torch.load(pretrained, map_location='cpu')['model']\n                pretrained_dict.popitem()   # remove bias\n                pretrained_dict.popitem()   # remove weight\n                self.load_state_dict(pretrained_dict, strict=False)\n            finally:\n                print(f\"Loaded imagenet pretrained from {pretrained}\")\n        else:\n            for n, m in self.named_modules():\n                if isinstance(m, nn.Linear):\n                    if n.startswith('head'):\n                        nn.init.zeros_(m.weight)\n                        nn.init.zeros_(m.bias)\n                    else:\n                        nn.init.xavier_uniform_(m.weight)\n                        if m.bias is not None:\n                            nn.init.zeros_(m.bias)\n                elif isinstance(m, nn.LayerNorm):\n                    nn.init.ones_(m.weight)\n                    nn.init.zeros_(m.bias)\n                elif isinstance(m, nn.Conv2d):\n                    nn.init.xavier_uniform_(m.weight)\n                    if m.bias is not None:\n                        nn.init.zeros_(m.bias)\n                \n    def return_features(self, x):\n        outs = []\n\n        for i in range(4):\n            x = self.downsample_layers[i](x)\n            x = self.stages[i](x)\n            norm_layer = getattr(self, f\"norm{i}\")\n            outs.append(norm_layer(x))\n        return outs\n        \n    def forward(self, x: torch.Tensor):\n        for i in range(4):\n            x = self.downsample_layers[i](x)\n            x = self.stages[i](x)\n        x = self.norm(x.mean([-2, -1])) # GAP NCHW to NC\n        x = self.head(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:05.076579Z","iopub.execute_input":"2023-03-31T04:12:05.077132Z","iopub.status.idle":"2023-03-31T04:12:05.110462Z","shell.execute_reply.started":"2023-03-31T04:12:05.077079Z","shell.execute_reply":"2023-03-31T04:12:05.109237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"use_cuda = torch.cuda.is_available()\ndevice = torch.device('cuda' if use_cuda else 'cpu')\nuse_cuda, device","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:10.789618Z","iopub.execute_input":"2023-03-31T04:12:10.790350Z","iopub.status.idle":"2023-03-31T04:12:10.901370Z","shell.execute_reply.started":"2023-03-31T04:12:10.790303Z","shell.execute_reply":"2023-03-31T04:12:10.900324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/products-10k-dataset/train.csv')\ndf\n#/kaggle/input/10k-products/train/","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:10.902828Z","iopub.execute_input":"2023-03-31T04:12:10.903556Z","iopub.status.idle":"2023-03-31T04:12:11.064398Z","shell.execute_reply.started":"2023-03-31T04:12:10.903517Z","shell.execute_reply":"2023-03-31T04:12:11.063348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_temp = pd.DataFrame({'class':df['class'].value_counts().index, 'count': df['class'].value_counts().values})\ndf_temp ","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.069831Z","iopub.execute_input":"2023-03-31T04:12:11.070164Z","iopub.status.idle":"2023-03-31T04:12:11.094277Z","shell.execute_reply.started":"2023-03-31T04:12:11.070133Z","shell.execute_reply":"2023-03-31T04:12:11.093119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_temp = df_temp.iloc[:1000, :]\ndf_temp","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.096050Z","iopub.execute_input":"2023-03-31T04:12:11.096458Z","iopub.status.idle":"2023-03-31T04:12:11.107684Z","shell.execute_reply.started":"2023-03-31T04:12:11.096419Z","shell.execute_reply":"2023-03-31T04:12:11.106448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cls = list(df_temp['class'])","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.109596Z","iopub.execute_input":"2023-03-31T04:12:11.110091Z","iopub.status.idle":"2023-03-31T04:12:11.116345Z","shell.execute_reply.started":"2023-03-31T04:12:11.110047Z","shell.execute_reply":"2023-03-31T04:12:11.115138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = df[df['class'].isin(cls)]\ndf_train.reset_index(inplace=True)\ndf_train = df_train[['name', 'class']]\ndf_train","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.118095Z","iopub.execute_input":"2023-03-31T04:12:11.118638Z","iopub.status.idle":"2023-03-31T04:12:11.145482Z","shell.execute_reply.started":"2023-03-31T04:12:11.118601Z","shell.execute_reply":"2023-03-31T04:12:11.144547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.read_csv('/kaggle/input/test-kaggletest-private/test_kaggletest.csv')\ndf_test = df_test[df_test['class'].isin(cls)]\ndf_test.reset_index(inplace=True)\ndf_test = df_test[['name', 'class']]\ndf_test","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.239992Z","iopub.execute_input":"2023-03-31T04:12:11.241692Z","iopub.status.idle":"2023-03-31T04:12:11.326676Z","shell.execute_reply.started":"2023-03-31T04:12:11.241646Z","shell.execute_reply":"2023-03-31T04:12:11.325463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.to_csv('train_1k', index=False)\ndf_test.to_csv('test_1k', index=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.328550Z","iopub.execute_input":"2023-03-31T04:12:11.328964Z","iopub.status.idle":"2023-03-31T04:12:11.355180Z","shell.execute_reply.started":"2023-03-31T04:12:11.328923Z","shell.execute_reply":"2023-03-31T04:12:11.354138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_to_int = {cls[i] : i for i in range(len(cls))}\nclass_to_int","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.356913Z","iopub.execute_input":"2023-03-31T04:12:11.357326Z","iopub.status.idle":"2023-03-31T04:12:11.395453Z","shell.execute_reply.started":"2023-03-31T04:12:11.357284Z","shell.execute_reply":"2023-03-31T04:12:11.394316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open ('convert_cls.json', 'w') as f:\n    json.dump(class_to_int, f)\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_PATH = '/kaggle/input/products-10k-dataset'","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.397095Z","iopub.execute_input":"2023-03-31T04:12:11.397767Z","iopub.status.idle":"2023-03-31T04:12:11.402823Z","shell.execute_reply.started":"2023-03-31T04:12:11.397727Z","shell.execute_reply":"2023-03-31T04:12:11.401691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image = cv2.imread('/kaggle/input/products-10k-dataset/train/train/1.jpg')\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\nplt.imshow(image)\nplt.show()\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.404801Z","iopub.execute_input":"2023-03-31T04:12:11.405193Z","iopub.status.idle":"2023-03-31T04:12:11.805575Z","shell.execute_reply.started":"2023-03-31T04:12:11.405127Z","shell.execute_reply":"2023-03-31T04:12:11.804604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 224\nBATCH_SIZE = 16\nLR = 1e-4\nEPOCHS = 10\nnum_classes = 5\n\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.807257Z","iopub.execute_input":"2023-03-31T04:12:11.807981Z","iopub.status.idle":"2023-03-31T04:12:11.814008Z","shell.execute_reply.started":"2023-03-31T04:12:11.807942Z","shell.execute_reply":"2023-03-31T04:12:11.812867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = df_train\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.816112Z","iopub.execute_input":"2023-03-31T04:12:11.817113Z","iopub.status.idle":"2023-03-31T04:12:11.829778Z","shell.execute_reply.started":"2023-03-31T04:12:11.817071Z","shell.execute_reply":"2023-03-31T04:12:11.828441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6, 3))\n\ntrain['class'].value_counts().plot(\n    kind='bar',\n    color='#558364',\n    width=0.7\n)\n\nplt.xlabel('Label', fontsize=12)\nplt.ylabel('Count', fontsize=12)\nplt.title('Distribution of Labels', fontsize=15)\nplt.xticks(rotation=360)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:11.831489Z","iopub.execute_input":"2023-03-31T04:12:11.831860Z","iopub.status.idle":"2023-03-31T04:12:22.180507Z","shell.execute_reply.started":"2023-03-31T04:12:11.831822Z","shell.execute_reply":"2023-03-31T04:12:22.179345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, val_df = model_selection.train_test_split(\n    train, test_size=0.12, random_state=42, stratify=train['class'].values\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.182008Z","iopub.execute_input":"2023-03-31T04:12:22.184995Z","iopub.status.idle":"2023-03-31T04:12:22.227630Z","shell.execute_reply.started":"2023-03-31T04:12:22.184962Z","shell.execute_reply":"2023-03-31T04:12:22.226664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.values","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.228986Z","iopub.execute_input":"2023-03-31T04:12:22.229455Z","iopub.status.idle":"2023-03-31T04:12:22.240317Z","shell.execute_reply.started":"2023-03-31T04:12:22.229413Z","shell.execute_reply":"2023-03-31T04:12:22.239068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ProductDataset(torch.utils.data.Dataset):\n    \n    def __init__(self, df, data_path=BASE_PATH, mode='train', transforms=None):\n        super().__init__()\n        self.df_data = df.values\n        self.data_path = data_path\n        self.transforms = transforms \n        self.mode = mode\n        self.data_dir = 'train' if mode == 'train' else 'test'\n    \n    def __len__(self):\n        return len(self.df_data)\n    \n    def __getitem__(self, index):\n        img_name, label = self.df_data[index]\n        img_path = os.path.join(self.data_path, self.data_dir, self.data_dir, img_name)\n        img = Image.open(img_path).convert('RGB')\n        \n        if self.transforms is not None:\n            img = self.transforms(img)\n            \n        return img, class_to_int[label]","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.241911Z","iopub.execute_input":"2023-03-31T04:12:22.243163Z","iopub.status.idle":"2023-03-31T04:12:22.252577Z","shell.execute_reply.started":"2023-03-31T04:12:22.243120Z","shell.execute_reply":"2023-03-31T04:12:22.251545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transforms_train = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.RandomHorizontalFlip(p=0.2),\n    transforms.RandomVerticalFlip(p=0.2),\n    transforms.RandomResizedCrop(IMG_SIZE),\n    transforms.ToTensor(),\n    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))\n])\n\ntransforms_val = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))\n])","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.253998Z","iopub.execute_input":"2023-03-31T04:12:22.254512Z","iopub.status.idle":"2023-03-31T04:12:22.263821Z","shell.execute_reply.started":"2023-03-31T04:12:22.254468Z","shell.execute_reply":"2023-03-31T04:12:22.262441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = ProductDataset(df=train_df, data_path=BASE_PATH, mode='train', transforms=transforms_train)\nval_dataset = ProductDataset(df=val_df, data_path=BASE_PATH, mode='train', transforms=transforms_val)","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.266135Z","iopub.execute_input":"2023-03-31T04:12:22.266548Z","iopub.status.idle":"2023-03-31T04:12:22.277436Z","shell.execute_reply.started":"2023-03-31T04:12:22.266520Z","shell.execute_reply":"2023-03-31T04:12:22.276202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_dataset), len(val_dataset)","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.283613Z","iopub.execute_input":"2023-03-31T04:12:22.283888Z","iopub.status.idle":"2023-03-31T04:12:22.290506Z","shell.execute_reply.started":"2023-03-31T04:12:22.283862Z","shell.execute_reply":"2023-03-31T04:12:22.289278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Visualize one training batch\n# train_dataloader = train_dataset\n# from torchvision.utils import make_grid\n# for images, labels in train_dataloader:\n#     fig, ax = plt.subplots(figsize = (10, 10))\n#     ax.set_xticks([])\n#     ax.set_yticks([])\n#     ax.imshow(make_grid(images, 4).permute(1,2,0))\n#     break","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.292347Z","iopub.execute_input":"2023-03-31T04:12:22.293099Z","iopub.status.idle":"2023-03-31T04:12:22.749575Z","shell.execute_reply.started":"2023-03-31T04:12:22.293063Z","shell.execute_reply":"2023-03-31T04:12:22.748474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = ConvNeXt('B', pretrained='/kaggle/input/convnext-weights/convnext/convnext_base_22k_224.pth')\nmodel.to(device)\n\n# from transformers import ViTForImageClassification, ViTConfig\n# model = ViTForImageClassification.from_pretrained(\"google/vit-base-patch16-224\")\n# # model.classifier = nn.Linear(in_features=768, out_features=num_classes, bias=True)\n# model.to(device)","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:22.751578Z","iopub.execute_input":"2023-03-31T04:12:22.752430Z","iopub.status.idle":"2023-03-31T04:12:31.411820Z","shell.execute_reply.started":"2023-03-31T04:12:22.752362Z","shell.execute_reply":"2023-03-31T04:12:31.410631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_losses = []\ntrain_accs = []\nval_losses = []\nval_accs = []\n\ndef train_model(model, train_dataset, val_dataset, learning_rate, epochs):\n\n    train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\n    val_dataloader = torch.utils.data.DataLoader(val_dataset, batch_size=BATCH_SIZE)\n    \n    criterion = nn.CrossEntropyLoss()\n    optimizer = optim.Adam(model.parameters(), lr=learning_rate)\n    scheduler = StepLR(optimizer, step_size=1, gamma=0.9)\n    \n    if use_cuda:\n        model = model.cuda()\n        criterion = criterion.cuda()\n\n    for epoch_num in range(epochs):\n\n            total_acc_train = 0\n            total_loss_train = 0\n\n            for train_images, train_labels in tqdm(train_dataloader):\n                \n                train_images = train_images.to(device)\n                train_labels = train_labels.to(device)\n                \n                optimizer.zero_grad()\n\n                output = model(train_images)\n                \n                batch_loss = criterion(output, train_labels.long())\n                total_loss_train += batch_loss.item()\n            \n                _, predicted = torch.max(output.data, 1)\n                acc = (predicted == train_labels).sum().item()\n                total_acc_train += acc\n\n                batch_loss.backward()\n                optimizer.step()\n                \n            scheduler.step()\n            \n            total_acc_val = 0\n            total_loss_val = 0\n\n            with torch.no_grad():\n\n                for val_images, val_labels in val_dataloader:\n                    \n                    val_images = val_images.to(device)\n                    val_labels = val_labels.to(device)\n                    \n                    output = model(val_images)\n\n                    batch_loss = criterion(output, val_labels.long())\n                    total_loss_val += batch_loss.item()\n                    \n                    _, predicted = torch.max(output.data, 1)\n                    acc = (predicted == val_labels).sum().item()\n                    total_acc_val += acc\n            \n            print(f'Epochs: {epoch_num + 1} | Train Loss: {total_loss_train / len(train_dataset): .3f} \\\n            | Train Accuracy: {total_acc_train / len(train_dataset): .3f} \\\n            | Val Loss: {total_loss_val / len(val_dataset): .3f} \\\n            | Val Accuracy: {total_acc_val / len(val_dataset): .3f}')\n            \n            train_losses.append(total_loss_train / len(train_dataset))\n            train_accs.append(total_acc_train / len(train_dataset))\n            val_losses.append(total_loss_val / len(val_dataset))\n            val_accs.append(total_acc_val / len(val_dataset))\n            \ntrain_model(model, train_dataset, val_dataset, LR, 10)\n#Epochs: 5 | Train Loss:  0.020             | Train Accuracy:  0.929             | Val Loss:  0.017             | Val Accuracy:  0.921   n\n\n\n# 100%|██████████| 1970/1970 [37:47<00:00,  1.15s/it]\n# Epochs: 1 | Train Loss:  0.193             | Train Accuracy:  0.508             | Val Loss:  0.045             | Val Accuracy:  0.851\n# 100%|██████████| 1970/1970 [34:57<00:00,  1.06s/it]\n# Epochs: 2 | Train Loss:  0.047             | Train Accuracy:  0.840             | Val Loss:  0.026             | Val Accuracy:  0.891\n# 100%|██████████| 1970/1970 [34:58<00:00,  1.07s/it]\n# Epochs: 3 | Train Loss:  0.031             | Train Accuracy:  0.890             | Val Loss:  0.022             | Val Accuracy:  0.903\n# 100%|██████████| 1970/1970 [34:49<00:00,  1.06s/it]\n# Epochs: 4 | Train Loss:  0.024             | Train Accuracy:  0.916             | Val Loss:  0.019             | Val Accuracy:  0.911\n# 100%|██████████| 1970/1970 [34:55<00:00,  1.06s/it]\n# Epochs: 5 | Train Loss:  0.020             | Train Accuracy:  0.929             | Val Loss:  0.017             | Val Accuracy:  0.921\n# 100%|██████████| 1970/1970 [35:02<00:00,  1.07s/it]\n# Epochs: 6 | Train Loss:  0.018             | Train Accuracy:  0.940             | Val Loss:  0.018             | Val Accuracy:  0.919","metadata":{"execution":{"iopub.status.busy":"2023-03-31T04:12:31.414717Z","iopub.execute_input":"2023-03-31T04:12:31.415607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(18, 6))\n\nplt.plot(\n    train_losses, \n    label='Train_Losses', \n    color='red', \n    linewidth=1.5\n)\nplt.plot(\n    val_losses, \n    label='Val_Losses', \n    color='blue', \n    linewidth=1.5\n)\n\nplt.plot(\n    train_accs, \n    label='Train_Accuracy', \n    color='green', \n    linewidth=1.5\n)\nplt.plot(\n    val_accs, \n    label='Val_Accuracy', \n    color='pink', \n    linewidth=1.5\n)\n\nplt.xlabel('Epoch')\nplt.ylabel('Loss / Accuracy')\nplt.title('Loss / Accuracy on train / validation')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/products-10k-dataset/sampleSubmission.csv')\nsub_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = []\n\ntest_dataset = ProductDataset(df=sub_df, data_path=BASE_PATH, mode='test', transforms=transforms_val)\n\ndef predict(model, test_dataset):\n    \n    test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=BATCH_SIZE)\n    \n    for test_images, test_labels in tqdm(test_dataloader):\n        test_images = test_images.to(device)\n        test_labels = test_labels.to(device)\n\n        output = model(test_images)\n\n        _, predicted = torch.max(output.data, 1)\n        preds.extend(predicted.cpu().data.numpy())\n        \n    print(preds)\n        \npredict(model, test_dataset)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df['label'] = preds\nsub_df.to_csv('submission.csv', index=False)\nsub_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}