{"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":"# import libraries\n# from pytorch tutorials in class\nimport torch\nimport torchvision\nimport torchvision.transforms as transforms\nimport matplotlib.pyplot as plt\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport os\nimport cv2\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage import io\n# necessary imports to be able to load the datasets\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision.datasets as dataset\nfrom torchvision import models\n\n\n# check to make sure we are using GPU\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nscaler = torch.cuda.amp.GradScaler()","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:48.531359Z","iopub.execute_input":"2023-03-12T06:01:48.531914Z","iopub.status.idle":"2023-03-12T06:01:52.132816Z","shell.execute_reply.started":"2023-03-12T06:01:48.531865Z","shell.execute_reply":"2023-03-12T06:01:52.131752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# trying to understand what the data looks like\ndef plot_images(rows, columns, images):\n    fig, x= plt.subplots(rows, columns, constrained_layout=True,figsize=(15,8))\n    plt.setp(x, xticks=[], yticks=[])\n    for i in range (len(x)):\n        for j in range (len(x[0])):\n            index = i*columns+j\n            img = cv2.imread('../input/dog-breed-identification/train/' + images[index])\n            x[i,j].imshow(cv2.resize(img, (224, 224)))\n            \nnum_columns = 5\ntrain_data = os.listdir('../input/dog-breed-identification/train')[:100]\nplot_images(num_columns, num_columns, train_data)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:52.137617Z","iopub.execute_input":"2023-03-12T06:01:52.138052Z","iopub.status.idle":"2023-03-12T06:01:54.406732Z","shell.execute_reply.started":"2023-03-12T06:01:52.138023Z","shell.execute_reply":"2023-03-12T06:01:54.405393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# need to get the ids from the sample_submission csv so we can match it up \nlabels = dict()\nfor index, value in enumerate(pd.read_csv('../input/dog-breed-identification/sample_submission.csv').columns[1:]):\n    labels[value] = index","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:54.408083Z","iopub.execute_input":"2023-03-12T06:01:54.408465Z","iopub.status.idle":"2023-03-12T06:01:54.895195Z","shell.execute_reply.started":"2023-03-12T06:01:54.408431Z","shell.execute_reply":"2023-03-12T06:01:54.894157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define dataset class for training data\nclass load_train(Dataset):\n    def __init__(self, csv_file, root_dir, transform=None):\n        self.labels = pd.read_csv(csv_file)\n        self.root_dir = root_dir\n        self.transform = transform['train']\n        \n    def __len__(self):\n        return self.labels.shape[0]\n    \n    # iloc() funciton helps us select a specific row or column in the dataset\n    # need to get the image path so we can load the actual image\n    def __getitem__(self, index):\n        path = os.path.join(self.root_dir, self.labels.iloc[index, 0]) + '.jpg'\n        image = io.imread(path\n                         )\n        # torch.tensor -> multidimensional matrix containing elements of a single data type\n        y_label = torch.tensor(int(labels[self.labels.iloc[index, 1]]))\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        return (image, y_label)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:54.898752Z","iopub.execute_input":"2023-03-12T06:01:54.899443Z","iopub.status.idle":"2023-03-12T06:01:54.907372Z","shell.execute_reply.started":"2023-03-12T06:01:54.899403Z","shell.execute_reply":"2023-03-12T06:01:54.906307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define dataset class for testing data\nclass load_test(Dataset):\n    def __init__(self, csv_file, root_dir, transform=None):\n        self.labels = pd.read_csv(csv_file)['id'].values\n        self.root_dir = root_dir\n        self.transform = transform['test']\n        \n    def __len__(self):\n        return len(self.labels)\n    \n    # iloc() funciton helps us select a specific row or column in the dataset\n    # need to get the image path so we can load the actual image\n    def __getitem__(self, index):\n        path = os.path.join(self.root_dir, self.labels[index]) + '.jpg'\n        image = io.imread(path)\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        return (image)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:54.910230Z","iopub.execute_input":"2023-03-12T06:01:54.910552Z","iopub.status.idle":"2023-03-12T06:01:54.920318Z","shell.execute_reply.started":"2023-03-12T06:01:54.910493Z","shell.execute_reply":"2023-03-12T06:01:54.919306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# set the hyperparameters which we will need to use for transforming data & then the model\nin_channel = 3\nbatch = 256\nrate = 0.0001\nnum_classes = 120\nepochs = 10","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:54.921943Z","iopub.execute_input":"2023-03-12T06:01:54.922451Z","iopub.status.idle":"2023-03-12T06:01:54.929542Z","shell.execute_reply.started":"2023-03-12T06:01:54.922416Z","shell.execute_reply":"2023-03-12T06:01:54.928638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# preprocess the images (taken from pytorch tutorials from class and modified for this dataset by looking at examples)\n# chain together transformations for train and for test using .Compose\n# normalize them so they are all standard\ntransform ={'train': transforms.Compose([\n        transforms.ToPILImage(),\n        transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n        transforms.RandomRotation(degrees=15),\n        transforms.ColorJitter(),\n        transforms.RandomHorizontalFlip(),\n        transforms.CenterCrop(size=224),  \n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406],\n                             [0.229, 0.224, 0.225])]),  \n    'test': transforms.Compose([transforms.ToPILImage(),\n                                      transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n                                      transforms.CenterCrop(size=224),\n                                      transforms.ToTensor(),\n                                     transforms.Normalize([0.485, 0.456, 0.406],\n                                                          [0.229, 0.224, 0.225])])}\n\n    \n# load in the training data and then split it up so we can use some for training and some for validation\ndataset = load_train('../input/dog-breed-identification/labels.csv', '../input/dog-breed-identification/train', transform)\n# use random split to split up the data into training and validation (we'll do a 70/30 split)\ntrain_size = int(len(dataset) * 0.7)\nvalid_size = len(dataset) - train_size\n# create the sets of the right size and split up\ntrain_set, valid_set = torch.utils.data.random_split(dataset, [train_size, valid_size])\n# utilize pytorch dataloader (python iterable over a dataset)\ntrain_dataloader = DataLoader(dataset=train_set, batch_size=batch, num_workers=4, shuffle=True)\nvalid_dataloader = DataLoader(dataset=valid_set, batch_size=batch, num_workers=4, shuffle=True)\n\n# load in the testing data\ndataset_test = load_test('../input/dog-breed-identification/sample_submission.csv', '../input/dog-breed-identification/test', transform=transform)\ntest_dataloader = DataLoader(dataset=dataset_test, batch_size=batch)\n","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:54.931273Z","iopub.execute_input":"2023-03-12T06:01:54.931693Z","iopub.status.idle":"2023-03-12T06:01:55.234138Z","shell.execute_reply.started":"2023-03-12T06:01:54.931658Z","shell.execute_reply":"2023-03-12T06:01:55.233142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create checkpoint methods of model \n# important to have intermediate versions of our model during training to make sure we don't lose anything\n# (modeled from pytorch tutorial)\n# save and load checkpoints\n\ndef save_checkpoint(state, filename=\"checkpoint.pth.tar\"):\n    print(\"saving checkpoint...\")\n    torch.save(state, filename)\n    \ndef load_checkpoint(checkpoint, model, optimizer):\n    print(\"loading checkpoint...\")\n    model.load_state_dict(checkpoint[\"state_dict\"])\n    optimizer.load_state_dict(checkpoint[\"optimizer\"])","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:55.235857Z","iopub.execute_input":"2023-03-12T06:01:55.236228Z","iopub.status.idle":"2023-03-12T06:01:55.242455Z","shell.execute_reply.started":"2023-03-12T06:01:55.236188Z","shell.execute_reply":"2023-03-12T06:01:55.241282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# utilizing resnet-50 a convolutional neural network which is 50 layers deep\n# (talked about in class)\nmodel = models.resnet50(pretrained=True)\n\n# freeze layers to avoid destroying any information they contain during future training rounds\nfor param in model.parameters():\n    param.requires_grad = False\n    \n# stripping off last layer and replacing from 1000 classes to num_classes (120)\nmodel.fc = nn.Linear(2048, num_classes)\nmodel = model.to(device = device)\nmodel","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:01:55.244249Z","iopub.execute_input":"2023-03-12T06:01:55.244636Z","iopub.status.idle":"2023-03-12T06:02:00.800201Z","shell.execute_reply.started":"2023-03-12T06:01:55.244585Z","shell.execute_reply":"2023-03-12T06:02:00.797898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# optimizer (utilizing Adam)\noptimizer = optim.Adam(model.parameters(), lr = rate)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.804594Z","iopub.execute_input":"2023-03-12T06:02:00.805296Z","iopub.status.idle":"2023-03-12T06:02:00.810951Z","shell.execute_reply.started":"2023-03-12T06:02:00.805265Z","shell.execute_reply":"2023-03-12T06:02:00.809816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loss function\ncriterion = nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.812579Z","iopub.execute_input":"2023-03-12T06:02:00.813373Z","iopub.status.idle":"2023-03-12T06:02:00.828072Z","shell.execute_reply.started":"2023-03-12T06:02:00.813333Z","shell.execute_reply":"2023-03-12T06:02:00.827014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save and load checkpoint\ncheckpoint = {\"state_dict\": model.state_dict(), \"optimizer\": optimizer.state_dict()}","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.831053Z","iopub.execute_input":"2023-03-12T06:02:00.831721Z","iopub.status.idle":"2023-03-12T06:02:00.839450Z","shell.execute_reply.started":"2023-03-12T06:02:00.831681Z","shell.execute_reply":"2023-03-12T06:02:00.838538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the data\ndef train_data(device, model, epochs, optimizer, criterion, train_dataloader, valid_dataloader):\n    losses = []\n    # do this range for ease of printing it out later\n    for epoch in range(1, epochs + 1):\n        model.train()\n        correct = 0\n        loss_total = 0\n        for data in train_dataloader:\n            with torch.autocast(device_type='cuda', dtype=torch.float16):\n                input = data[0].to(device)\n                label = data[1].to(device)\n\n                # beginning of training loop (zero the gradients)\n                optimizer.zero_grad()\n\n                # forward & backward propagation\n                output = model(input)\n                _, predicted = output.max(1)\n                loss = criterion(output, label)\n                losses.append(loss.item())\n                loss_total += loss.item()\n                correct += (predicted==label).sum()\n            scaler.scale(loss).backward()\n            scaler.step(optimizer)\n            scaler.update()\n            optimizer.zero_grad()\n            \n        print('epoch number: {}'.format(epoch))\n        print('Training Accuracy: {} Training loss: {}'.format(correct/len(train_dataloader.sampler), loss_total/len(train_dataloader)))\n            \n    return model\n            ","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.841002Z","iopub.execute_input":"2023-03-12T06:02:00.841366Z","iopub.status.idle":"2023-03-12T06:02:00.852007Z","shell.execute_reply.started":"2023-03-12T06:02:00.841327Z","shell.execute_reply":"2023-03-12T06:02:00.850400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validation(model, device, valid_dataloader, criterion):\n    model.eval()\n    loss_total = 0\n    correct = 0\n    \n    with torch.no_grad():\n        for data in valid_dataloader:\n            input = data[0].to(device)\n            label = data[1].to(device)\n            \n            output = model(input)\n            _, predicted = output.max(1)\n            loss = criterion(output, label)\n            loss_total += loss.item()\n            correct += (predicted==label).sum()\n            \n        print('Validation Accuracy: {}'.format(correct/len(valid_loader.sampler)))\n    return loss_total / len(valid_loader)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.853230Z","iopub.execute_input":"2023-03-12T06:02:00.853540Z","iopub.status.idle":"2023-03-12T06:02:00.866247Z","shell.execute_reply.started":"2023-03-12T06:02:00.853487Z","shell.execute_reply":"2023-03-12T06:02:00.865245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test(device, model, test_dataloader, criterion):\n    model.eval()\n    predictions = pd.DataFrame()\n    with torch.no_grad():\n        for data in test_dataloader:\n            data = torch.from_numpy(np.asarray(data))\n            input = data.to(device)\n            output = model(input)\n            m = nn.Softmax(dim=1)\n            result = m(output)\n            \n            predictions = pd.concat([predictions, pd.DataFrame(torch.Tensor.cpu(result).numpy(), columns = list(map_labels.keys()))], ignore_index=True)\n            \n            \n        return predictions","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:05:47.308942Z","iopub.execute_input":"2023-03-12T06:05:47.309898Z","iopub.status.idle":"2023-03-12T06:05:47.317837Z","shell.execute_reply.started":"2023-03-12T06:05:47.309833Z","shell.execute_reply":"2023-03-12T06:05:47.316853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = train_data(device, model, epochs, optimizer, criterion, train_dataloader, valid_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-03-12T06:02:00.878447Z","iopub.execute_input":"2023-03-12T06:02:00.878965Z","iopub.status.idle":"2023-03-12T06:02:34.327188Z","shell.execute_reply.started":"2023-03-12T06:02:00.878925Z","shell.execute_reply":"2023-03-12T06:02:34.325485Z"},"trusted":true},"execution_count":null,"outputs":[]}]}