{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"initial_id","cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nimport torchvision\nimport torchvision.transforms as transforms\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import Dataset\nfrom PIL import Image\nimport os","metadata":{"ExecuteTime":{"end_time":"2026-09-12T11:57:09.610656Z","start_time":"2026-09-12T11:57:06.305754Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:29.683240Z","iopub.execute_input":"2026-09-13T08:25:29.683536Z","iopub.status.idle":"2026-09-13T08:25:38.385050Z","shell.execute_reply.started":"2026-09-13T08:25:29.683500Z","shell.execute_reply":"2026-09-13T08:25:38.384438Z"}},"outputs":[],"execution_count":null},{"id":"f212e5f888ae8b76","cell_type":"code","source":"train_class_size = 375\nval_class_size = 100\ncf_dir = '/kaggle/input/competitions/computer-vision-homework-2026/food_cv/'\ntrain_dir = cf_dir+'train/'\nval_dir = cf_dir+'val/'\ntest_dir = cf_dir+'test/'","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:21:44.006606Z","start_time":"2026-09-12T12:21:43.999569Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:38.386315Z","iopub.execute_input":"2026-09-13T08:25:38.386962Z","iopub.status.idle":"2026-09-13T08:25:38.391670Z","shell.execute_reply.started":"2026-09-13T08:25:38.386929Z","shell.execute_reply":"2026-09-13T08:25:38.390811Z"}},"outputs":[],"execution_count":null},{"id":"cb266e4b1e845869","cell_type":"code","source":"\n\nclass FoodDataset(Dataset):\n    def __init__(self,image_dir,train,set_size,transform=None):\n        self.image_dir = image_dir\n        self.transform = transform\n        self.train = train\n        self.set_size = set_size\n    def __len__(self):\n        # if self.labels_df is not None:\n        #     return len(self.labels_df)\n\n        return len(os.listdir(self.image_dir))\n    def __getitem__(self, index):\n        \n\n        \n        if self.train:\n            image_id = index % self.set_size\n            label_id = index // self.set_size\n            image_path = os.path.join(self.image_dir, f'{label_id}_{image_id}.jpg')\n            image = Image.open(image_path).convert('RGB')\n        else:\n            image_path = os.path.join(self.image_dir, f'{index}.jpg')\n            image = Image.open(image_path).convert('RGB')\n        if self.transform:\n            image = self.transform(image)\n        if self.train:\n            return image, label_id\n        return image, index\n\n","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:21:45.292522Z","start_time":"2026-09-12T12:21:45.279325Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:38.392622Z","iopub.execute_input":"2026-09-13T08:25:38.392953Z","iopub.status.idle":"2026-09-13T08:25:38.409298Z","shell.execute_reply.started":"2026-09-13T08:25:38.392931Z","shell.execute_reply":"2026-09-13T08:25:38.408572Z"}},"outputs":[],"execution_count":null},{"id":"7bb17eb1dd275a88","cell_type":"code","source":"mean = (0.5635, 0.4436, 0.3218)\nstd = (0.2598, 0.2633, 0.2637)\n\n\n# transform = transforms.Compose([\n#     transforms.Resize(140),\n#     transforms.RandomCrop(128),\n#     transforms.RandomHorizontalFlip(),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean, std)\n#     # transforms.Normalize(mean,std )\n# ])\ntransform = transforms.Compose([\n    transforms.Resize(140),\n    transforms.CenterCrop(128),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean,std)\n])\nval_transform = transforms.Compose([\n    transforms.Resize(140),\n    transforms.CenterCrop(128),\n    transforms.ToTensor(),\n    transforms.Normalize(mean, std)\n])\n\n# train_transform = transforms.Compose([\n#     transforms.ToTensor(),\n#     # transforms.Normalize(mean, std)\n# ])\n\n\n","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:21:45.689660Z","start_time":"2026-09-12T12:21:45.670589Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:38.410095Z","iopub.execute_input":"2026-09-13T08:25:38.410418Z","iopub.status.idle":"2026-09-13T08:25:38.421819Z","shell.execute_reply.started":"2026-09-13T08:25:38.410384Z","shell.execute_reply":"2026-09-13T08:25:38.421058Z"}},"outputs":[],"execution_count":null},{"id":"6c3a4d9f92a8d537","cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_set = FoodDataset(train_dir,True,375,transform=transform)\nval_set = FoodDataset(val_dir,True,100,transform=val_transform)\n# test_set = FoodDataset(img_dir,train=False,transform=transform)\n\n\nbatch_size = 64\ntrain_loader = DataLoader(train_set,batch_size = batch_size,shuffle = True,num_workers = 4)\nval_loader = DataLoader(val_set,batch_size = batch_size,shuffle = False,num_workers = 4)\n","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:21:46.432642Z","start_time":"2026-09-12T12:21:46.419351Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:29:05.246481Z","iopub.execute_input":"2026-09-13T08:29:05.247249Z","iopub.status.idle":"2026-09-13T08:29:05.263063Z","shell.execute_reply.started":"2026-09-13T08:29:05.247220Z","shell.execute_reply":"2026-09-13T08:29:05.262528Z"}},"outputs":[],"execution_count":null},{"id":"408ce9dfa131400","cell_type":"code","source":"class BasicBlock(nn.Module):\n    expansion = 1\n    def __init__(self, in_channels, out_channels, stride=1):\n        super().__init__()\n\n        self.conv1 = nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1,stride=stride),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True),\n        )\n        self.conv2 = nn.Sequential(\n            nn.Conv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, padding=1,stride=1),\n            nn.BatchNorm2d(num_features=out_channels),\n            # nn.ReLU(inplace=True),\n        )\n        if stride != 1 or in_channels != out_channels:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(\n                    in_channels,\n                    out_channels,\n                    kernel_size=1,\n                    stride=stride,\n                    bias=False\n                ),\n                nn.BatchNorm2d(out_channels)\n            )\n        else:\n            self.shortcut = nn.Identity()\n        self.relu = nn.ReLU(inplace=True)\n    def forward(self, x):\n        residual = self.shortcut(x)\n        out = self.conv1(x)\n        out = self.conv2(out)\n        out += residual\n        out = self.relu(out)\n        return out\n\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, in_channels, out_channels, stride=1):\n        super().__init__()\n        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n        self.bn1 = nn.BatchNorm2d(out_channels)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = nn.Conv2d(in_channels=out_channels, out_channels=out_channels,stride=stride,kernel_size=3,padding = 1)\n        self.bn2 = nn.BatchNorm2d(out_channels)\n        self.conv3 = nn.Conv2d(in_channels=out_channels,out_channels=out_channels * self.expansion,kernel_size=1)\n        self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)\n\n        if stride != 1 or in_channels != out_channels * self.expansion:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(\n                    in_channels,\n                    out_channels * self.expansion,\n                    kernel_size=1,\n                    stride=stride,\n                    bias=False\n                ),\n                nn.BatchNorm2d(out_channels * self.expansion)\n            )\n        else:\n            self.shortcut = nn.Identity()\n        self.relu = nn.ReLU(inplace=True)\n\n    def forward(self, x):\n        residual = self.shortcut(x)\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n        out += residual\n        out = self.relu(out)\n        return out\n\nclass ResNet(nn.Module):\n    def __init__(self, block, layers, num_classes=20):\n        super().__init__()\n        self.in_channels = 64\n\n        self.stem = nn.Sequential(\n            nn.Conv2d(3,64,kernel_size=3,padding=1,stride=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU(inplace=True)\n        )\n        self.layer1 = self.make_layer(block,64,layers[0],stride = 1)\n        self.layer2 = self.make_layer(block,128,layers[1],stride = 2)\n        self.layer3 = self.make_layer(block,256,layers[2],stride = 2)\n        self.layer4 = self.make_layer(block,512,layers[3],stride = 2)\n        self.avgpool = nn.AdaptiveAvgPool2d(1)\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n    def make_layer(self, block, out_channels, num_blocks, stride = 1):\n        layers = [\n            block(self.in_channels, out_channels, stride = stride)\n        ]\n\n        self.in_channels = out_channels * block.expansion\n\n        for _ in range(1, num_blocks):\n            layers.append(block(self.in_channels, out_channels))\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        x = self.stem(x)\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = torch.flatten(x, 1)\n\n        x = self.fc(x)\n        return x\n\ndef ResNet18(num_classes=20):\n    return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes)\n\ndef ResNet34():\n    return ResNet(BasicBlock, [3, 4, 6, 3])\n\n\ndef ResNet50():\n    return ResNet(Bottleneck, [3, 4, 6, 3])","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:33:54.100374Z","start_time":"2026-09-12T12:33:54.085687Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:38.513067Z","iopub.execute_input":"2026-09-13T08:25:38.513354Z","iopub.status.idle":"2026-09-13T08:25:38.527805Z","shell.execute_reply.started":"2026-09-13T08:25:38.513333Z","shell.execute_reply":"2026-09-13T08:25:38.527211Z"}},"outputs":[],"execution_count":null},{"id":"e53aa704a330316a","cell_type":"code","source":"img,labels = next(iter(val_loader))\n# print(img,labels)\nlen(val_set)","metadata":{"ExecuteTime":{"end_time":"2026-09-12T12:21:59.053411Z","start_time":"2026-09-12T12:21:58.921419Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:25:38.528646Z","iopub.execute_input":"2026-09-13T08:25:38.528965Z","iopub.status.idle":"2026-09-13T08:25:39.301580Z","shell.execute_reply.started":"2026-09-13T08:25:38.528905Z","shell.execute_reply":"2026-09-13T08:25:39.300763Z"}},"outputs":[],"execution_count":null},{"id":"833ae871b64230ba","cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(device)\ndef eval_acc(model,loader):\n    accuracy = 0\n    total = 0\n    with torch.no_grad():\n        model.eval()\n        for img,label in loader:\n            img,label = img.to(device),label.to(device)\n            data = model(img)\n            total += label.size(0)\n            accuracy += (data.argmax(dim=1) == label).float().sum()\n    print(f\"accuracy in test data  {accuracy/total}\")\n\n\ndef train(epochs,model,loader,criterion,optimizer,scheduler = None):\n    for epoch in range(epochs):\n        model.train()\n        running_loss = 0.0\n        correct = 0\n        total = 0\n        for img,label in loader:\n            img,label = img.to(device),label.to(device)\n            data = model(img)\n            optimizer.zero_grad()\n            loss = criterion(data,label)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n            total += label.size(0)\n            correct += (data.argmax(dim=1) == label).float().sum()\n\n        print(f\"epoch {epoch+1}/{epochs}, loss: {running_loss/len(loader)},scheduler:{scheduler}\")\n        print(f\"correct in training data {correct/total}\")\n        eval_acc(model,val_loader)\n        scheduler.step()\n    print(f\"Finished Training\")\n\ncriterion = nn.CrossEntropyLoss()\n# model = CNN().to(device)\n# optimizer = optim.Adam(model.parameters(),lr = 0.1)\nepoch = 50\nresnet18 = torch.nn.DataParallel(ResNet18()).to(device)\noptimizer = torch.optim.AdamW(\n    resnet18.parameters(),\n    lr=3e-4,\n    weight_decay=1e-4\n)\n\nscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(\n    optimizer,\n    T_max=epoch\n)\ntrain(epoch,resnet18,train_loader,criterion,optimizer,scheduler)","metadata":{"jupyter":{"is_executing":true},"ExecuteTime":{"start_time":"2026-09-12T12:35:07.925497Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:29:13.156974Z","iopub.execute_input":"2026-09-13T08:29:13.157302Z"}},"outputs":[],"execution_count":null},{"id":"5ea20f48-ee8f-4039-b1fd-0a9798dcb8a4","cell_type":"code","source":"trained_epochs = 10","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:28:39.732658Z","iopub.status.idle":"2026-09-13T08:28:39.732880Z","shell.execute_reply.started":"2026-09-13T08:28:39.732772Z","shell.execute_reply":"2026-09-13T08:28:39.732784Z"}},"outputs":[],"execution_count":null},{"id":"459d4113-a343-464b-9aaf-cffcc22cfe96","cell_type":"code","source":"trained_epochs+=10\ntrain(10,resnet18,train_loader,criterion,optimizer)\nprint(f'#######################\\n\\n\\nactual epochs:{trained_epochs}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:28:39.734242Z","iopub.status.idle":"2026-09-13T08:28:39.734714Z","shell.execute_reply.started":"2026-09-13T08:28:39.734561Z","shell.execute_reply":"2026-09-13T08:28:39.734584Z"}},"outputs":[],"execution_count":null},{"id":"a53a38f7329d8e57","cell_type":"code","source":"def eval(model,loader):\n    accuracy = 0\n    total = 0\n    with torch.no_grad():\n        model.eval()\n        for img,label in loader:\n            img,label = img.to(device),label.to(device)\n            data = model(img)\n            total += label.size(0)\n            accuracy += (data.argmax(dim=1) == label).float().sum()\n    print(f\"final accuracy is {accuracy/total}\")\n\neval(resnet18,test_loader)","metadata":{"ExecuteTime":{"end_time":"2026-09-09T11:52:27.106526Z","start_time":"2026-09-09T11:52:25.917449Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:28:39.735900Z","iopub.status.idle":"2026-09-13T08:28:39.736285Z","shell.execute_reply.started":"2026-09-13T08:28:39.736101Z","shell.execute_reply":"2026-09-13T08:28:39.736124Z"}},"outputs":[],"execution_count":null},{"id":"cf8f81446a4d8308","cell_type":"code","source":"\ntest_dataset = FoodDataset(test_dir,train = False, set_size = 100,transform=val_transform)\n\n# predict_loader = DataLoader(test_dataset,batch_size = 512,shuffle = False)\npredict_loader = DataLoader(test_dataset,batch_size = 100,shuffle = False)\n\nresnet18.eval()\n\npredictions = []\nimage_ids = []\nn=0\nwith torch.no_grad():\n    for images,ids  in predict_loader:\n        images = images.to(device)\n        outputs = resnet18(images)\n        predicted = outputs.argmax(dim=1)\n\n        predictions.extend(predicted.cpu().tolist())\n        image_ids.extend(ids.tolist())\n\n        n+=images.size(0)\n        if n%(400)==0:\n            print(f'predicted {n} images')\n\n\nprint(\"prediction completed\")\n","metadata":{"ExecuteTime":{"end_time":"2026-09-09T11:52:27.198232Z","start_time":"2026-09-09T11:52:27.184712Z"},"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:28:39.738314Z","iopub.status.idle":"2026-09-13T08:28:39.738706Z","shell.execute_reply.started":"2026-09-13T08:28:39.738579Z","shell.execute_reply":"2026-09-13T08:28:39.738596Z"}},"outputs":[],"execution_count":null},{"id":"92b0c691-df02-40e8-bd9f-2146baeeb1bd","cell_type":"code","source":"import pandas as pd\n\n\npredicted_labels = predictions\nsubmission = pd.DataFrame({\n    'id': image_ids,\n    'label': predicted_labels\n})\n\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-13T08:28:39.740049Z","iopub.status.idle":"2026-09-13T08:28:39.740316Z","shell.execute_reply.started":"2026-09-13T08:28:39.740200Z","shell.execute_reply":"2026-09-13T08:28:39.740221Z"}},"outputs":[],"execution_count":null},{"id":"b51e837c-63e5-4f31-97aa-73dd1fcac5a8","cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}