{"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-04-24T19:18:32.491970Z","iopub.execute_input":"2023-04-24T19:18:32.493403Z","iopub.status.idle":"2023-04-24T19:18:32.503529Z","shell.execute_reply.started":"2023-04-24T19:18:32.493354Z","shell.execute_reply":"2023-04-24T19:18:32.502244Z"},"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-04-24T19:18:32.505769Z","iopub.execute_input":"2023-04-24T19:18:32.506845Z","iopub.status.idle":"2023-04-24T19:18:34.771800Z","shell.execute_reply.started":"2023-04-24T19:18:32.506796Z","shell.execute_reply":"2023-04-24T19:18:34.769313Z"},"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-04-24T19:18:34.773177Z","iopub.execute_input":"2023-04-24T19:18:34.774175Z","iopub.status.idle":"2023-04-24T19:18:35.148813Z","shell.execute_reply.started":"2023-04-24T19:18:34.774134Z","shell.execute_reply":"2023-04-24T19:18:35.147658Z"},"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-04-24T19:18:35.152285Z","iopub.execute_input":"2023-04-24T19:18:35.152704Z","iopub.status.idle":"2023-04-24T19:18:35.161025Z","shell.execute_reply.started":"2023-04-24T19:18:35.152662Z","shell.execute_reply":"2023-04-24T19:18:35.159847Z"},"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-04-24T19:18:35.163051Z","iopub.execute_input":"2023-04-24T19:18:35.163467Z","iopub.status.idle":"2023-04-24T19:18:35.175089Z","shell.execute_reply.started":"2023-04-24T19:18:35.163427Z","shell.execute_reply":"2023-04-24T19:18:35.173886Z"},"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-04-24T19:18:35.176781Z","iopub.execute_input":"2023-04-24T19:18:35.178051Z","iopub.status.idle":"2023-04-24T19:18:35.189273Z","shell.execute_reply.started":"2023-04-24T19:18:35.178020Z","shell.execute_reply":"2023-04-24T19:18:35.188044Z"},"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-04-24T19:18:35.190901Z","iopub.execute_input":"2023-04-24T19:18:35.191506Z","iopub.status.idle":"2023-04-24T19:18:35.454893Z","shell.execute_reply.started":"2023-04-24T19:18:35.191464Z","shell.execute_reply":"2023-04-24T19:18:35.453861Z"},"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-04-24T19:18:35.456417Z","iopub.execute_input":"2023-04-24T19:18:35.456884Z","iopub.status.idle":"2023-04-24T19:18:35.466821Z","shell.execute_reply.started":"2023-04-24T19:18:35.456844Z","shell.execute_reply":"2023-04-24T19:18:35.465337Z"},"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-04-24T19:18:35.468408Z","iopub.execute_input":"2023-04-24T19:18:35.468847Z","iopub.status.idle":"2023-04-24T19:18:35.948141Z","shell.execute_reply.started":"2023-04-24T19:18:35.468810Z","shell.execute_reply":"2023-04-24T19:18:35.946972Z"},"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-04-24T19:18:35.952532Z","iopub.execute_input":"2023-04-24T19:18:35.952915Z","iopub.status.idle":"2023-04-24T19:18:35.959646Z","shell.execute_reply.started":"2023-04-24T19:18:35.952877Z","shell.execute_reply":"2023-04-24T19:18:35.958524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loss function\ncriterion = nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:18:35.961115Z","iopub.execute_input":"2023-04-24T19:18:35.962058Z","iopub.status.idle":"2023-04-24T19:18:35.970886Z","shell.execute_reply.started":"2023-04-24T19:18:35.962020Z","shell.execute_reply":"2023-04-24T19:18:35.969463Z"},"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-04-24T19:18:35.972248Z","iopub.execute_input":"2023-04-24T19:18:35.973127Z","iopub.status.idle":"2023-04-24T19:18:35.984946Z","shell.execute_reply.started":"2023-04-24T19:18:35.973091Z","shell.execute_reply":"2023-04-24T19:18:35.983782Z"},"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-04-24T19:18:35.986299Z","iopub.execute_input":"2023-04-24T19:18:35.986890Z","iopub.status.idle":"2023-04-24T19:18:35.997173Z","shell.execute_reply.started":"2023-04-24T19:18:35.986852Z","shell.execute_reply":"2023-04-24T19:18:35.995959Z"},"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_dataloader.sampler)))\n    return loss_total / len(valid_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:18:35.998984Z","iopub.execute_input":"2023-04-24T19:18:35.999932Z","iopub.status.idle":"2023-04-24T19:18:36.009459Z","shell.execute_reply.started":"2023-04-24T19:18:35.999903Z","shell.execute_reply":"2023-04-24T19:18:36.008283Z"},"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(labels.keys()))], ignore_index=True)\n            \n            \n        return predictions","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:18:36.011280Z","iopub.execute_input":"2023-04-24T19:18:36.012026Z","iopub.status.idle":"2023-04-24T19:18:36.021546Z","shell.execute_reply.started":"2023-04-24T19:18:36.011988Z","shell.execute_reply":"2023-04-24T19:18:36.020469Z"},"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-04-24T19:18:36.023382Z","iopub.execute_input":"2023-04-24T19:18:36.023765Z","iopub.status.idle":"2023-04-24T19:27:19.995562Z","shell.execute_reply.started":"2023-04-24T19:18:36.023732Z","shell.execute_reply":"2023-04-24T19:27:19.994072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a = validation(model, device, valid_dataloader, criterion)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:27:19.997406Z","iopub.execute_input":"2023-04-24T19:27:19.999520Z","iopub.status.idle":"2023-04-24T19:27:46.433051Z","shell.execute_reply.started":"2023-04-24T19:27:19.999474Z","shell.execute_reply":"2023-04-24T19:27:46.430952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = test(device, model, test_dataloader, criterion)\npredictions","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:27:46.435897Z","iopub.execute_input":"2023-04-24T19:27:46.436809Z","iopub.status.idle":"2023-04-24T19:29:53.632918Z","shell.execute_reply.started":"2023-04-24T19:27:46.436754Z","shell.execute_reply":"2023-04-24T19:29:53.631835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n#import pandas as pd\n\n# 读取 sample.csv 文件\n#sample_df = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv', index_col='id')\n\n# 将 sample_df 和 predictions 变量合并起来\n#result_df = pd.concat([sample_df, predictions], axis=1)\n\n# 将合并后的结果保存为 CSV 文件\n#result_df.to_csv('predictions.csv', index=True)\n\n","metadata":{"execution":{"iopub.status.busy":"2023-04-24T19:56:29.432840Z","iopub.execute_input":"2023-04-24T19:56:29.433714Z","iopub.status.idle":"2023-04-24T19:56:32.649949Z","shell.execute_reply.started":"2023-04-24T19:56:29.433673Z","shell.execute_reply":"2023-04-24T19:56:32.648781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\n\n# 读取 sample_submission.csv 文件中的 id\nsample_df = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv')\n# 读取 sample.csv 文件\n#sample_df = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv', index_col='id')\n\n# 将 sample_df 和 predictions 变量合并起来\n#result_df = pd.concat([sample_df, predictions], axis=1)\nimage_ids = sample_df['id']\n\n# 在 predictions 前面添加一列图片 ID\npredictions.insert(0, 'id', image_ids)\n\n# 将结果保存为 CSV 文件\npredictions.to_csv('predictions2.csv', index=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-24T20:03:30.384630Z","iopub.execute_input":"2023-04-24T20:03:30.385021Z","iopub.status.idle":"2023-04-24T20:03:30.700631Z","shell.execute_reply.started":"2023-04-24T20:03:30.384986Z","shell.execute_reply":"2023-04-24T20:03:30.698977Z"},"trusted":true},"execution_count":null,"outputs":[]}]}