{"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        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-05-17T09:28:06.192749Z","iopub.execute_input":"2023-05-17T09:28:06.194243Z","iopub.status.idle":"2023-05-17T09:28:18.535466Z","shell.execute_reply.started":"2023-05-17T09:28:06.194200Z","shell.execute_reply":"2023-05-17T09:28:18.534355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Imports","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport torch\nimport torch.nn as nn\n\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\n\nimport torchvision.transforms as trans\n\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\n\nfrom pathlib import Path\nfrom PIL import Image\n\nfrom collections import defaultdict\nfrom tqdm.notebook import tqdm","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:18.541764Z","iopub.execute_input":"2023-05-17T09:28:18.544764Z","iopub.status.idle":"2023-05-17T09:28:22.232181Z","shell.execute_reply.started":"2023-05-17T09:28:18.544725Z","shell.execute_reply":"2023-05-17T09:28:22.231249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.models import vgg19_bn, VGG19_BN_Weights","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.238417Z","iopub.execute_input":"2023-05-17T09:28:22.238984Z","iopub.status.idle":"2023-05-17T09:28:22.243436Z","shell.execute_reply.started":"2023-05-17T09:28:22.238949Z","shell.execute_reply":"2023-05-17T09:28:22.242606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## hyperparams","metadata":{}},{"cell_type":"code","source":"DATA_TRAIN_PATH = \"/kaggle/input/dog-breed-identification/train\"\nDATA_TEST_PATH = \"/kaggle/input/dog-breed-identification/test\"\n\nBATCH_SIZE = 64\nLR = 1e-3\nNUM_EPOCHS = 5\nSEED = 177013\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.244703Z","iopub.execute_input":"2023-05-17T09:28:22.245394Z","iopub.status.idle":"2023-05-17T09:28:22.283394Z","shell.execute_reply.started":"2023-05-17T09:28:22.245355Z","shell.execute_reply":"2023-05-17T09:28:22.282453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_df = pd.read_csv(\"/kaggle/input/dog-breed-identification/labels.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.286914Z","iopub.execute_input":"2023-05-17T09:28:22.287666Z","iopub.status.idle":"2023-05-17T09:28:22.332681Z","shell.execute_reply.started":"2023-05-17T09:28:22.287635Z","shell.execute_reply":"2023-05-17T09:28:22.331827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DogBreedDataset(Dataset):\n    def __init__(self, image_path, label_df, transforms = None):\n        \n        self.image_path = image_path\n        self.label_df = label_df\n        \n        self.idx_to_classes = {index: name for index, name in enumerate(label_df[\"breed\"].unique())}\n        self.classes_to_idx = {v: k for k, v in self.idx_to_classes.items()}\n        self.num_classes = len(self.classes_to_idx.keys())\n        \n        if transforms is None:\n            self.transforms = trans.ToTensor()\n        else:\n            self.transforms = transforms\n        \n    \n    def __getitem__(self, index):\n        image_id = label_df.iloc[index, 0]\n        label = label_df.iloc[index, 1]\n        \n        curr_image_path = self.image_path + f\"/{image_id}.jpg\"\n        image = Image.open(curr_image_path)\n        label_en = self.classes_to_idx[label]\n        \n        image_processed = self.transforms(image)\n        \n        return image_processed, label_en\n    \n    def __len__(self):\n        return list(Path(DATA_TRAIN_PATH).iterdir()).__len__()\n    \n    def __repr__(self):\n        return f\"Dataset with {self.__len__()} images and {self.num_classes} classes.\"\n        ","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.334038Z","iopub.execute_input":"2023-05-17T09:28:22.334364Z","iopub.status.idle":"2023-05-17T09:28:22.344836Z","shell.execute_reply.started":"2023-05-17T09:28:22.334334Z","shell.execute_reply":"2023-05-17T09:28:22.343805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transform = VGG19_BN_Weights.DEFAULT.transforms()\ntrain_transforms = trans.Compose([\n    trans.TrivialAugmentWide(),\n    train_transform\n])","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.346335Z","iopub.execute_input":"2023-05-17T09:28:22.346894Z","iopub.status.idle":"2023-05-17T09:28:22.360737Z","shell.execute_reply.started":"2023-05-17T09:28:22.346863Z","shell.execute_reply":"2023-05-17T09:28:22.359631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = DogBreedDataset(DATA_TRAIN_PATH, label_df, transforms = train_transforms)\n\ntrain_split = int(len(train_data) * 0.2)\nvalid_split = int(len(train_data) * 0.1)\ntrain_data_20_percent, valid_data_10_percent,  _ = torch.utils.data.random_split(train_data, \n                                                         [train_split, valid_split, len(train_data) - (train_split + valid_split)],\n                                                         generator = torch.manual_seed(SEED))\n","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.362126Z","iopub.execute_input":"2023-05-17T09:28:22.362448Z","iopub.status.idle":"2023-05-17T09:28:22.624671Z","shell.execute_reply.started":"2023-05-17T09:28:22.362415Z","shell.execute_reply":"2023-05-17T09:28:22.623773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader = DataLoader(train_data_20_percent, batch_size = BATCH_SIZE, shuffle = True)\nvalid_loader = DataLoader(valid_data_10_percent, batch_size = BATCH_SIZE, shuffle = False)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.628536Z","iopub.execute_input":"2023-05-17T09:28:22.629151Z","iopub.status.idle":"2023-05-17T09:28:22.634430Z","shell.execute_reply.started":"2023-05-17T09:28:22.629119Z","shell.execute_reply":"2023-05-17T09:28:22.633594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## pretrained Vgg19","metadata":{}},{"cell_type":"code","source":"model = vgg19_bn(weights = VGG19_BN_Weights.DEFAULT)\n\nfor params in model.features.parameters():\n    params.requires_grad = False\n    \nmodel.classifier = nn.Sequential(\n    nn.Linear(in_features = 25088, out_features = 4096, bias = True),\n    nn.ReLU(inplace = True),\n    nn.Dropout(p = 0.5, inplace = False),\n    nn.Linear(in_features = 4096, out_features = 4096, bias = True),\n    nn.ReLU(inplace = True),\n    nn.Dropout(p = 0.5, inplace = False),\n    nn.Linear(in_features = 4096, out_features = train_data.num_classes, bias = True),\n)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:22.636165Z","iopub.execute_input":"2023-05-17T09:28:22.636782Z","iopub.status.idle":"2023-05-17T09:28:31.919078Z","shell.execute_reply.started":"2023-05-17T09:28:22.636752Z","shell.execute_reply":"2023-05-17T09:28:31.918104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_fn = nn.CrossEntropyLoss(label_smoothing = 0.1)\noptimizer = torch.optim.Adam(model.parameters(), lr = LR)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:31.920532Z","iopub.execute_input":"2023-05-17T09:28:31.920905Z","iopub.status.idle":"2023-05-17T09:28:31.929346Z","shell.execute_reply.started":"2023-05-17T09:28:31.920868Z","shell.execute_reply":"2023-05-17T09:28:31.925829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def check_acc(y_pred, y_test):\n    return (y_pred == y_test).sum().item() / len(y_pred)\n\ndef train_step(model, train_loader, loss_fn, optimizer, device):\n    model.train()\n    model = model.to(device)\n    running_loss, running_acc = 0.0, 0.0\n    \n    for x, y in tqdm(train_loader, desc = \"train_step\"):\n        x, y = x.to(device), y.to(device)\n        \n        y_logits = model(x)\n        y_probs = torch.softmax(y_logits, dim = 0)\n        y_prob_bin = torch.argmax(y_probs, dim = 1)\n        \n        loss = loss_fn(y_logits, y)\n        \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        \n        running_loss += loss.item()\n        running_acc += check_acc(y_prob_bin, y)\n        \n    running_loss /= len(train_loader)\n    running_acc /= len(train_loader)\n    \n    return running_loss, running_acc\n\ndef test_step(model, test_loader, loss_fn, device):\n    model.eval()\n    model = model.to(device)\n    \n    running_loss, running_acc = 0.0, 0.0\n    with torch.inference_mode():\n        for x, y in tqdm(test_loader, desc = \"eval_step\"):\n            x, y = x.to(device), y.to(device)\n            \n            y_logits = model(x)\n            y_probs = torch.softmax(y_logits, dim = 0)\n            y_prob_bin = torch.argmax(y_probs, dim = 1)\n            \n            loss = loss_fn(y_logits, y)\n            \n            running_loss += loss.item()\n            running_acc += check_acc(y_prob_bin, y)\n            \n        running_loss /= len(test_loader)\n        running_acc /= len(test_loader)\n        \n    return running_loss, running_acc\n\ndef fit(model, train_loader, test_loader, loss_fn, optimizer, device, num_epochs):\n    history_train = defaultdict(list)\n    history_test = defaultdict(list)\n    for epoch in tqdm(range(num_epochs)):\n        epoch_loss_train, epoch_acc_train = train_step(model, train_loader, loss_fn, optimizer, device)\n        epoch_loss_test, epoch_acc_test = test_step(model, test_loader, loss_fn, device)\n        \n        print(f\"epoch: {epoch}/{num_epochs}, loss_train: {epoch_loss_train}, acc_train: {epoch_acc_train}, loss_test: {epoch_loss_test}, acc_test: {epoch_acc_test}\")\n        \n        history_train[\"acc\"].append(epoch_acc_train)\n        history_train[\"loss\"].append(epoch_loss_train)\n        history_test[\"acc\"].append(epoch_acc_test)\n        history_test[\"loss\"].append(epoch_loss_test)\n        \n    return history_train, history_test","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:31.931128Z","iopub.execute_input":"2023-05-17T09:28:31.932011Z","iopub.status.idle":"2023-05-17T09:28:32.024831Z","shell.execute_reply.started":"2023-05-17T09:28:31.931981Z","shell.execute_reply":"2023-05-17T09:28:32.023992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"his_train, his_test = fit(model, train_loader, valid_loader, loss_fn, optimizer, device, NUM_EPOCHS)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:28:32.026113Z","iopub.execute_input":"2023-05-17T09:28:32.027049Z","iopub.status.idle":"2023-05-17T09:31:43.606030Z","shell.execute_reply.started":"2023-05-17T09:28:32.027017Z","shell.execute_reply":"2023-05-17T09:31:43.604970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = make_subplots(rows = 1, cols = 2, subplot_titles = (\"loss\", \"accuracy\"))\n\nfig.add_trace(go.Scatter(x = [*range(len(his_train[\"loss\"]))], y = his_train[\"loss\"], name = \"loss_train\"), row = 1, col = 1)\nfig.add_trace(go.Scatter(x = [*range(len(his_test[\"loss\"]))], y = his_test[\"loss\"], name = \"loss_test\"), row = 1, col = 1)\n\nfig.add_trace(go.Scatter(x = [*range(len(his_train[\"acc\"]))], y = his_train[\"acc\"], name = \"acc_train\"), row = 1, col = 2)\nfig.add_trace(go.Scatter(x = [*range(len(his_test[\"acc\"]))], y = his_test[\"acc\"], name = \"acc_test\"), row = 1, col = 2)\nfig.update_layout(title = \"loss Vs Accuray\")\nfig.update_xaxes(title = \"epochs\")\nfig.update_yaxes(title = \"val\")\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-05-17T10:07:25.260486Z","iopub.execute_input":"2023-05-17T10:07:25.261106Z","iopub.status.idle":"2023-05-17T10:07:25.319825Z","shell.execute_reply.started":"2023-05-17T10:07:25.261070Z","shell.execute_reply":"2023-05-17T10:07:25.318930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(\"/kaggle/input/dog-breed-identification/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:31:43.607746Z","iopub.execute_input":"2023-05-17T09:31:43.608525Z","iopub.status.idle":"2023-05-17T09:31:44.068323Z","shell.execute_reply.started":"2023-05-17T09:31:43.608486Z","shell.execute_reply":"2023-05-17T09:31:44.067248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:31:44.069842Z","iopub.execute_input":"2023-05-17T09:31:44.070195Z","iopub.status.idle":"2023-05-17T09:31:44.109454Z","shell.execute_reply.started":"2023-05-17T09:31:44.070164Z","shell.execute_reply":"2023-05-17T09:31:44.108415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(model, sample_sub, test_path, transform, classes_to_idx):\n    sub = pd.DataFrame(columns = sample_sub.columns)\n    for index, rows in sample_sub.iterrows():\n        image_id = rows[\"id\"]\n        image = Image.open(test_path + f\"/{image_id}.jpg\")\n        image_processed = transform(image).unsqueeze(dim = 0).to(device)\n        \n        y_logits = model(image_processed).squeeze()\n        y_probs = torch.softmax(y_logits, dim = 0)\n        \n        sub_classes = {classes_to_idx[index]: [prob] for index, prob in enumerate(y_probs.detach().cpu().numpy())}\n        sub_classes[\"id\"] = image_id\n        \n        sub = pd.concat([sub, pd.DataFrame(sub_classes)])\n    return sub","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:41:03.781485Z","iopub.execute_input":"2023-05-17T09:41:03.782257Z","iopub.status.idle":"2023-05-17T09:41:03.791142Z","shell.execute_reply.started":"2023-05-17T09:41:03.782212Z","shell.execute_reply":"2023-05-17T09:41:03.790006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_sub = predict(model, sample_sub, DATA_TEST_PATH, train_transform, train_data.idx_to_classes)\nmy_sub = my_sub.reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:41:20.046705Z","iopub.execute_input":"2023-05-17T09:41:20.047090Z","iopub.status.idle":"2023-05-17T09:46:53.510637Z","shell.execute_reply.started":"2023-05-17T09:41:20.047058Z","shell.execute_reply":"2023-05-17T09:46:53.509689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_sub.to_csv(\"sub_1.csv\", index = False)","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:55:39.845793Z","iopub.execute_input":"2023-05-17T09:55:39.846489Z","iopub.status.idle":"2023-05-17T09:55:41.499924Z","shell.execute_reply.started":"2023-05-17T09:55:39.846454Z","shell.execute_reply":"2023-05-17T09:55:41.498929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:51:25.316007Z","iopub.execute_input":"2023-05-17T09:51:25.316769Z","iopub.status.idle":"2023-05-17T09:51:25.351773Z","shell.execute_reply.started":"2023-05-17T09:51:25.316713Z","shell.execute_reply":"2023-05-17T09:51:25.350661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_sub","metadata":{"execution":{"iopub.status.busy":"2023-05-17T09:51:32.807653Z","iopub.execute_input":"2023-05-17T09:51:32.808028Z","iopub.status.idle":"2023-05-17T09:51:32.848731Z","shell.execute_reply.started":"2023-05-17T09:51:32.807995Z","shell.execute_reply":"2023-05-17T09:51:32.847834Z"},"trusted":true},"execution_count":null,"outputs":[]}]}