{"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":"!pip install numpy --upgrade\n\nimport numpy as np\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:23.556618Z","iopub.execute_input":"2023-11-04T15:30:23.557342Z","iopub.status.idle":"2023-11-04T15:30:23.562494Z","shell.execute_reply.started":"2023-11-04T15:30:23.557303Z","shell.execute_reply":"2023-11-04T15:30:23.561443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:23.565000Z","iopub.execute_input":"2023-11-04T15:30:23.565346Z","iopub.status.idle":"2023-11-04T15:30:23.576262Z","shell.execute_reply.started":"2023-11-04T15:30:23.565320Z","shell.execute_reply":"2023-11-04T15:30:23.575304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv_path = '/kaggle/input/humpback-whale-identification/train.csv'\ntrain_dir_path = '/kaggle/input/humpback-whale-identification/train/'\ntest_dir_path = '/kaggle/input/humpback-whale-identification/test/'\noutput_dir_path = '/kaggle/working/'","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:23.578090Z","iopub.execute_input":"2023-11-04T15:30:23.578514Z","iopub.status.idle":"2023-11-04T15:30:23.587360Z","shell.execute_reply.started":"2023-11-04T15:30:23.578477Z","shell.execute_reply":"2023-11-04T15:30:23.586576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_label_encoder():\n    dataset = pd.read_csv(train_csv_path)\n    label_dict = {}\n    num_ids = 0\n\n    for i in range(len(dataset)):\n        id = dataset['Id'].iloc[i] \n        if id not in label_dict:\n            label_dict[id] = num_ids\n            num_ids += 1\n\n    return label_dict, num_ids\n\nlabel_encoder, num_ids = get_label_encoder()\nprint(f\"number of special Id's: {num_ids}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:23.601157Z","iopub.execute_input":"2023-11-04T15:30:23.601701Z","iopub.status.idle":"2023-11-04T15:30:24.047802Z","shell.execute_reply.started":"2023-11-04T15:30:23.601676Z","shell.execute_reply":"2023-11-04T15:30:24.046663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose(\n            [lambda image: image.convert('RGB') if image.mode != 'RGB' else image,\n             transforms.PILToTensor(),\n             lambda tensor: tensor.float()/255,\n             transforms.Resize((128, 128), antialias=True)\n             #transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n             ])\n\ndef load_train_images(print_info=False):\n    dataset = pd.read_csv(train_csv_path)\n    data = np.empty(len(dataset), dtype=dict)\n\n    for i in range(len(dataset)):\n        image_path = train_dir_path + dataset['Image'].iloc[i]\n        data[i] = {'image': (transform(Image.open(image_path).copy())),\n                    'label': torch.tensor(label_encoder[dataset['Id'].iloc[i]], dtype=torch.long)}\n\n        if print_info and i % 1000 == 0:\n            print(f\"Loading image: {i+1}\")\n\n    return data","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:24.049473Z","iopub.execute_input":"2023-11-04T15:30:24.049781Z","iopub.status.idle":"2023-11-04T15:30:24.058939Z","shell.execute_reply.started":"2023-11-04T15:30:24.049754Z","shell.execute_reply":"2023-11-04T15:30:24.057908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Preparing the dataset\nclass WhalesDataSet(Dataset):\n    def __init__(self):\n        self.data = load_train_images(print_info=True)\n\n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        sample = self.data[index]\n\n        return sample['image'], sample['label']","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:24.060179Z","iopub.execute_input":"2023-11-04T15:30:24.060471Z","iopub.status.idle":"2023-11-04T15:30:24.073972Z","shell.execute_reply.started":"2023-11-04T15:30:24.060445Z","shell.execute_reply":"2023-11-04T15:30:24.072907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"whalesDataSet = WhalesDataSet() ","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:30:24.076336Z","iopub.execute_input":"2023-11-04T15:30:24.076674Z","iopub.status.idle":"2023-11-04T15:34:33.185697Z","shell.execute_reply.started":"2023-11-04T15:30:24.076646Z","shell.execute_reply":"2023-11-04T15:34:33.184582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64\n\ntrain_loader = DataLoader(whalesDataSet, batch_size, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:34:33.187077Z","iopub.execute_input":"2023-11-04T15:34:33.187406Z","iopub.status.idle":"2023-11-04T15:34:33.192612Z","shell.execute_reply.started":"2023-11-04T15:34:33.187379Z","shell.execute_reply":"2023-11-04T15:34:33.191607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class model(nn.Module):\n    def __init__(self):\n        super(model, self).__init__() # 3x128x128\n        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=7, stride=2, padding=3) # 32x64x64\n        self.bn1 = nn.BatchNorm2d(32)\n        self.pool1 = nn.MaxPool2d(2, 2) # 32x32x32\n        self.conv2 = nn.Conv2d(32, 64, 5, 2, padding=2)   # 64x16x16\n        self.bn2 = nn.BatchNorm2d(64)\n        self.conv31 = nn.Conv2d(64, 128, 3, padding=1) # 128x16x16\n        self.conv32 = nn.Conv2d(128, 64, 5, padding=2) # 64x16x16\n        self.bn3 = nn.BatchNorm2d(64)\n        self.pool_end = nn.MaxPool2d(2, 2)     # 64x8x8\n        self.fc1 = nn.Linear(64*8*8, 4096)\n        self.do = nn.Dropout(0.2)\n        self.fc2 = nn.Linear(4096, num_ids)\n    \n    def forward(self, x):\n        x = self.pool1(self.bn1(F.relu(self.conv1(x))))\n        x = self.bn2(F.relu(self.conv2(x)))\n        x = self.bn3(F.relu(self.conv32(F.relu(self.conv31(x)))))\n        x = self.pool_end(x)\n        x = x.view(-1, 64*8*8)\n        x = self.do((F.relu(self.fc1(x))))\n        x = (self.fc2(x))\n        return x\n    \nwhales_model = model()","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:34:33.193691Z","iopub.execute_input":"2023-11-04T15:34:33.194013Z","iopub.status.idle":"2023-11-04T15:34:33.510175Z","shell.execute_reply.started":"2023-11-04T15:34:33.193984Z","shell.execute_reply":"2023-11-04T15:34:33.509309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_func = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(whales_model.parameters(), lr=0.001)\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.3, patience=2)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:34:33.511589Z","iopub.execute_input":"2023-11-04T15:34:33.512290Z","iopub.status.idle":"2023-11-04T15:34:33.517490Z","shell.execute_reply.started":"2023-11-04T15:34:33.512255Z","shell.execute_reply":"2023-11-04T15:34:33.516605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(train_loader, model, optimizer, scheduler = None, num_epochs=10, print_cost=False, print_stride=1):\n    model = model.to(device)\n    for epoch in range(num_epochs):\n        running_loss = 0.\n        for i, mini_batch in enumerate(train_loader):\n            # get the inputs; data is a list of [inputs, labels]\n            inputs, labels = mini_batch\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n\n            # zero the parameter gradients\n            optimizer.zero_grad()\n\n            # forward + backward + optimize\n            predicts = model(inputs)\n           \n            loss = loss_func(predicts, labels)\n            loss.backward()\n            optimizer.step()\n\n            # Calc loss\n            lloss = loss.item()\n            running_loss += lloss * inputs.size(0)\n\n            #if print_cost and i % print_stride == 0:            \n            #    print(f\"[epoch: {epoch+1} MB: {i+1}] Loss: {lloss}\")\n\n        epoch_loss = running_loss/(len(train_loader)*batch_size)\n        if scheduler:\n            scheduler.step(epoch_loss)\n        if print_cost:\n            print(f\"[epoch: {epoch+1}] Total Loss: {epoch_loss}\")\n        running_loss = 0.","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:34:33.518882Z","iopub.execute_input":"2023-11-04T15:34:33.519215Z","iopub.status.idle":"2023-11-04T15:34:33.529226Z","shell.execute_reply.started":"2023-11-04T15:34:33.519185Z","shell.execute_reply":"2023-11-04T15:34:33.528342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_model(train_loader, whales_model, optimizer, scheduler, num_epochs=40, print_cost=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:34:33.530283Z","iopub.execute_input":"2023-11-04T15:34:33.530523Z","iopub.status.idle":"2023-11-04T15:40:14.987814Z","shell.execute_reply.started":"2023-11-04T15:34:33.530501Z","shell.execute_reply":"2023-11-04T15:40:14.986675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def eval_model(model, set_loader, set_name:str):\n    correct = 0\n    total = 0\n    outs = []\n    with torch.no_grad():\n        model.eval()\n        for i, data in enumerate(set_loader):\n            images, labels = data[0].to(device), data[1].to(device)\n            outputs = model(images)\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n            outs.append(predicted)\n            if i == 10:\n                break\n    print(f\"[{set_name}] ACC: {100*(correct/total)}%\")\n    return outs","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:40:14.990733Z","iopub.execute_input":"2023-11-04T15:40:14.991038Z","iopub.status.idle":"2023-11-04T15:40:14.998189Z","shell.execute_reply.started":"2023-11-04T15:40:14.991012Z","shell.execute_reply":"2023-11-04T15:40:14.997179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"outs = eval_model(whales_model, train_loader, \"train set\")","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:42:55.933188Z","iopub.execute_input":"2023-11-04T15:42:55.933574Z","iopub.status.idle":"2023-11-04T15:42:56.033502Z","shell.execute_reply.started":"2023-11-04T15:42:55.933545Z","shell.execute_reply":"2023-11-04T15:42:56.032290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import pickle\n#model_file_name = '/kaggle/working/personal_trained_whales_model.pkl'\n# with open(model_file_name, 'wb') as file:\n#    pickle.dump(whales_model, file)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:40:15.103727Z","iopub.execute_input":"2023-11-04T15:40:15.104042Z","iopub.status.idle":"2023-11-04T15:40:15.108732Z","shell.execute_reply.started":"2023-11-04T15:40:15.104016Z","shell.execute_reply":"2023-11-04T15:40:15.107884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#with open(model_file_name, 'rb') as file:\n#    saved_model = pickle.load(file).to(device)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:40:15.109793Z","iopub.execute_input":"2023-11-04T15:40:15.110104Z","iopub.status.idle":"2023-11-04T15:40:15.121597Z","shell.execute_reply.started":"2023-11-04T15:40:15.110080Z","shell.execute_reply":"2023-11-04T15:40:15.120651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\ndef load_test_images(print_info=False):\n    test_X = []\n    # Get a list of all files in the directory\n    image_paths = sorted(os.listdir(test_dir_path))\n    for i, image_path in enumerate(image_paths):\n        test_X.append(transform(Image.open(test_dir_path + image_path).copy()))\n            \n        if print_info and i % 1000 == 0:\n            print(f\"Loading image: {i+1}\")\n\n    return torch.stack(test_X), image_paths\n\ntest_X, image_paths = load_test_images(print_info=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:40:15.122749Z","iopub.execute_input":"2023-11-04T15:40:15.123091Z","iopub.status.idle":"2023-11-04T15:41:36.939005Z","shell.execute_reply.started":"2023-11-04T15:40:15.123059Z","shell.execute_reply":"2023-11-04T15:41:36.937905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Using a dictionary comprehension to get the inverse\nlabel_decoder = {value: key for key, value in label_encoder.items()}\n\nnum_guesses = 5\n\ntest_data = {'Image': image_paths, 'Id': []}\n\nwith torch.no_grad():\n    whales_model.eval()\n    for test_image in test_X:\n        test_image = test_image.unsqueeze(0).to(device)\n        outs = whales_model(test_image)\n        best_guesses_vals, best_class = torch.topk(outs.squeeze(), num_guesses)\n        best_ids = ' '.join([label_decoder[int(clas)] for clas in best_class])\n        test_data['Id'].append(best_ids)\n        \nsubmission = pd.DataFrame(test_data)\nsubmission.to_csv(output_dir_path + 'submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:41:36.940967Z","iopub.execute_input":"2023-11-04T15:41:36.941352Z","iopub.status.idle":"2023-11-04T15:41:47.108579Z","shell.execute_reply.started":"2023-11-04T15:41:36.941317Z","shell.execute_reply":"2023-11-04T15:41:47.107769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out_csv = pd.read_csv(output_dir_path + 'submission.csv')\nprint(out_csv)","metadata":{"execution":{"iopub.status.busy":"2023-11-04T15:42:35.522962Z","iopub.execute_input":"2023-11-04T15:42:35.523395Z","iopub.status.idle":"2023-11-04T15:42:35.546575Z","shell.execute_reply.started":"2023-11-04T15:42:35.523350Z","shell.execute_reply":"2023-11-04T15:42:35.545637Z"},"trusted":true},"execution_count":null,"outputs":[]}]}