{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"dockerImageVersionId":29956,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"In this notebook I am using the Cifar10 dataset to classify various images. \nI have coded the traditional LeNet model with some hyper parameter tuning for this purpose.\nAs seen I got 71% accuracy for this model and te model performed well on images it had never seen before. It correctly classified a random image from the internet.\nPlease find the code below","metadata":{}},{"cell_type":"code","source":"import torch\nimport numpy as np\n\ntrain_on_gpu=torch.cuda.is_available()\n","metadata":{"id":"JukxQHA5Ezs3","execution":{"iopub.status.busy":"2023-11-30T03:22:57.66546Z","iopub.execute_input":"2023-11-30T03:22:57.665772Z","iopub.status.idle":"2023-11-30T03:22:58.953801Z","shell.execute_reply.started":"2023-11-30T03:22:57.665744Z","shell.execute_reply":"2023-11-30T03:22:58.953011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Initializing GPU Usage","metadata":{"id":"nurRYLvFFhO-"}},{"cell_type":"code","source":"from torchvision import datasets\nfrom torchvision.transforms import transforms\nfrom torch.utils.data.sampler import SubsetRandomSampler\n\nnumber_of_workers = 0\nbatch_size= 10\nvalid_size= 0.2\n\n#  Converting Data into a Normalized Tensor format\ntransform = transforms.Compose([\n                                transforms.RandomHorizontalFlip(),\n                                transforms.RandomRotation(10),\n                                transforms.ToTensor(),\n                                transforms.Normalize(mean=(0.5, 0.5, 0.5), std= (0.5, 0.5, 0.5))\n])","metadata":{"id":"11C_r_YRFUGa","execution":{"iopub.status.busy":"2023-11-30T03:23:01.997533Z","iopub.execute_input":"2023-11-30T03:23:01.997863Z","iopub.status.idle":"2023-11-30T03:23:02.353569Z","shell.execute_reply.started":"2023-11-30T03:23:01.997826Z","shell.execute_reply":"2023-11-30T03:23:02.352893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Transformations and Data Augmentation","metadata":{"id":"CJvLY35DFtAq"}},{"cell_type":"code","source":"# Downloading training and testing Datasets\ntrain_data= datasets.CIFAR10('data', train= True,\n                             download= True, transform = transform)\ntest_data = datasets.CIFAR10('data', train = False,\n                             download = True, transform= transform)","metadata":{"id":"xJ32chBeFoWd","outputId":"0ad7c337-165a-437b-ca4a-78c89009582e","execution":{"iopub.status.busy":"2023-11-30T03:23:07.277451Z","iopub.execute_input":"2023-11-30T03:23:07.277784Z","iopub.status.idle":"2023-11-30T03:23:14.345262Z","shell.execute_reply.started":"2023-11-30T03:23:07.277754Z","shell.execute_reply":"2023-11-30T03:23:14.344536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Converting the Input images to plot using plt","metadata":{"id":"JWetPW3AMkF9"}},{"cell_type":"code","source":"# Obtaining training Indices that we are going to use for Validation Set\nnum_train= len(train_data)\nindices = list(range(num_train))\nnp.random.shuffle(indices)\n# 打乱索引顺序\nsplit = int(np.floor(valid_size * num_train))\n# 划分训练和验证\ntrain_idx, valid_idx = indices[split:] , indices[:split]","metadata":{"id":"bTtyjj2OI5KS","execution":{"iopub.status.busy":"2023-11-30T03:23:16.707748Z","iopub.execute_input":"2023-11-30T03:23:16.708156Z","iopub.status.idle":"2023-11-30T03:23:16.719571Z","shell.execute_reply.started":"2023-11-30T03:23:16.70812Z","shell.execute_reply":"2023-11-30T03:23:16.718612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Defining samplers for training and validation Bathces\ntrain_sampler = SubsetRandomSampler(train_idx)\nvalid_sampler = SubsetRandomSampler(valid_idx)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T03:23:25.306593Z","iopub.execute_input":"2023-11-30T03:23:25.306925Z","iopub.status.idle":"2023-11-30T03:23:25.311144Z","shell.execute_reply.started":"2023-11-30T03:23:25.306894Z","shell.execute_reply":"2023-11-30T03:23:25.310085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Preparing Data Loader for all three sets (combining datasets and samplers)\ntrain_loader = torch.utils.data.DataLoader(train_data, batch_size = batch_size ,\n                                           sampler= train_sampler , num_workers = number_of_workers)\nvalid_loader= torch.utils.data.DataLoader(train_data , batch_size= batch_size,\n                                          sampler = valid_sampler, num_workers = number_of_workers)\ntest_loader= torch.utils.data.DataLoader(test_data, batch_size= batch_size, \n                                         num_workers= number_of_workers)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T03:23:27.662209Z","iopub.execute_input":"2023-11-30T03:23:27.662581Z","iopub.status.idle":"2023-11-30T03:23:27.668888Z","shell.execute_reply.started":"2023-11-30T03:23:27.662545Z","shell.execute_reply":"2023-11-30T03:23:27.667909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# After preparing Data, we have to unnormalize it to visullize it.\n# Lets create a helper function which will un-normalize all the images\nimport matplotlib.pyplot as plt\n\ndef imshow(img):\n  # Will take numpy array as input\n  img = img / 2 + 0.5 # Unnormalize image\n  plt.imshow(np.transpose(img, (1, 2, 0))) # img array , axis in tuple(numbers indicates the location of new image shape.) Converting from tensor image \n\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T03:23:31.099934Z","iopub.execute_input":"2023-11-30T03:23:31.100309Z","iopub.status.idle":"2023-11-30T03:23:31.105607Z","shell.execute_reply.started":"2023-11-30T03:23:31.100277Z","shell.execute_reply":"2023-11-30T03:23:31.104687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names =['airplane', 'automobile', 'bird', 'cat', 'deer',\n           'dog', 'frog', 'horse', 'ship', 'truck']","metadata":{"id":"eidAN_9OJitC","execution":{"iopub.status.busy":"2023-11-30T03:24:49.135087Z","iopub.execute_input":"2023-11-30T03:24:49.13545Z","iopub.status.idle":"2023-11-30T03:24:49.14031Z","shell.execute_reply.started":"2023-11-30T03:24:49.135417Z","shell.execute_reply":"2023-11-30T03:24:49.139352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataiter = iter(train_loader)\nimages, labels = next(dataiter)\nimages = images.numpy()\n\nfig = plt.figure(figsize=(25, 4))\nfor idx in range(10):\n  ax= fig.add_subplot(2 , 10 , idx+1 , xticks=[], yticks=[])\n  imshow(images[idx])\n  ax.set_title(class_names[labels[idx]])","metadata":{"id":"64Ev5i6FJxxW","outputId":"9356a284-39ba-48e6-da1c-eab1c811fb01","execution":{"iopub.status.busy":"2023-11-30T03:24:54.4771Z","iopub.execute_input":"2023-11-30T03:24:54.47743Z","iopub.status.idle":"2023-11-30T03:24:54.913372Z","shell.execute_reply.started":"2023-11-30T03:24:54.4774Z","shell.execute_reply":"2023-11-30T03:24:54.91227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rgb_img = np.squeeze(images[3])\nchannels = ['red channel', 'green channel', 'blue channel']\n\nfig = plt.figure(figsize = (36, 36)) \nfor idx in np.arange(rgb_img.shape[0]):\n    ax = fig.add_subplot(1, 3, idx + 1)\n    img = rgb_img[idx]\n    ax.imshow(img, cmap='gray')\n    ax.set_title(channels[idx])\n    width, height = img.shape\n    thresh = img.max()/2.5\n    for x in range(width):\n        for y in range(height):\n            val = round(img[x][y],2) if img[x][y] !=0 else 0\n            ax.annotate(str(val), xy=(y,x),\n                    horizontalalignment='center',\n                    verticalalignment='center', size=8,\n                    color='white' if img[x][y]<thresh else 'black')","metadata":{"execution":{"iopub.status.busy":"2023-11-29T13:29:37.952756Z","iopub.execute_input":"2023-11-29T13:29:37.953151Z","iopub.status.idle":"2023-11-29T13:29:51.592321Z","shell.execute_reply.started":"2023-11-29T13:29:37.953108Z","shell.execute_reply":"2023-11-29T13:29:51.591341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F\n\n# define the CNN architecture\nclass Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n    \n        self.conv1 = nn.Conv2d(3, 6, 2 , padding=1, stride= 1) # (32 - 5+ 2(0) / 1) + 1 = 28\n        self.pool1 = nn.MaxPool2d(2, 2) # (28 - 2 + 2(0)/ 2) + 1 = 14\n        self.conv2 = nn.Conv2d(6, 16, 2, padding=1, stride= 1) # (14 - 5 + 2(0)/ 1) + 1 = 10\n        self.pool2 = nn.MaxPool2d(2, 2) # (10 - 2 + 2(0)/ 2) + 1 = 5\n        self.conv3 = nn.Conv2d(16, 32, 2)# (5 - 2 + 2(0)/ 1) + 1 = 4\n        self.pool3 = nn.MaxPool2d(2, 2)# (4 - 2 + 2(0)/ 2) + 1 = 2\n        self.fc1 = nn.Linear(32* 3**2, 120)\n        self.fc2 = nn.Linear(120, 84)\n        self.fc3 = nn.Linear(84, 10)\n\n    def forward(self, x):\n        # add sequence of convolutional and max pooling layers\n        x = self.pool1( F.relu(self.conv1(x)))\n        x= self.pool2( F.relu(self.conv2(x)))\n        x= self.pool3(F.relu(self.conv3(x)))\n        # Flatten it\n        x= torch.flatten(x, 1)\n        # x = x.view(x.size(0), -1)\n        x= F.relu(self.fc1(x))\n        x= F.relu(self.fc2(x))\n        x= self.fc3(x)\n        return x\n\n# create a complete CNN\nmodel = Net()\nprint(model)\n\n# move tensors to GPU if CUDA is available\nif train_on_gpu:\n    model.cuda()","metadata":{"execution":{"iopub.status.busy":"2023-11-30T03:25:01.153778Z","iopub.execute_input":"2023-11-30T03:25:01.154234Z","iopub.status.idle":"2023-11-30T03:25:05.27808Z","shell.execute_reply.started":"2023-11-30T03:25:01.154197Z","shell.execute_reply":"2023-11-30T03:25:05.277211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Defining our Model","metadata":{"id":"sTh5PVEfMtn4"}},{"cell_type":"code","source":"def feature_calc(num_channels, k_size, stride , pad):\n  calc_result=( ((num_channels - k_size + 2*pad ) / stride) + 1)\n  return calc_result","metadata":{"id":"jxIIxm1aK2At","execution":{"iopub.status.busy":"2023-11-30T03:25:10.213419Z","iopub.execute_input":"2023-11-30T03:25:10.213783Z","iopub.status.idle":"2023-11-30T03:25:10.219113Z","shell.execute_reply.started":"2023-11-30T03:25:10.213746Z","shell.execute_reply":"2023-11-30T03:25:10.217911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a1=feature_calc(32, 2, 1, 1)\na2=feature_calc(np.floor(a1), 2, 2, 0)\na3=feature_calc(np.floor(a2), 2, 1, 1)\na4= feature_calc(np.floor(a3), 2, 2, 0)\na5= feature_calc(np.floor(a4), 2, 1, 0)\na6= feature_calc(np.floor(a5), 2, 2, 0)\n\nprint(a1, a2, a3, a4, a5, a6)","metadata":{"execution":{"iopub.status.busy":"2023-11-29T14:44:47.830015Z","iopub.execute_input":"2023-11-29T14:44:47.830352Z","iopub.status.idle":"2023-11-29T14:44:47.839031Z","shell.execute_reply.started":"2023-11-29T14:44:47.830322Z","shell.execute_reply":"2023-11-29T14:44:47.838032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.optim as optim\n\n# specify loss function\ncriterion = nn.CrossEntropyLoss()\n\n# specify optimizer\noptimizer = optim.SGD(model.parameters(), lr= 0.0001, momentum= 0.9)","metadata":{"id":"Qa1M7e7vOre5","outputId":"4742bd2d-f356-44df-98cc-3ce48e473d1a","execution":{"iopub.status.busy":"2023-11-30T03:25:13.887437Z","iopub.execute_input":"2023-11-30T03:25:13.887758Z","iopub.status.idle":"2023-11-30T03:25:13.893136Z","shell.execute_reply.started":"2023-11-30T03:25:13.88773Z","shell.execute_reply":"2023-11-30T03:25:13.892014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* 直接训练","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"train_loss_history = []\nvalid_loss_history = []\ntrain_accuracy_history = []\nvalid_accuracy_history = []\n\n# number of epochs to train the model\nn_epochs = 300\n\nvalid_loss_min = np.Inf # track change in validation loss\n\nfor epoch in range(1, n_epochs+1):\n\n    # keep track of training and validation loss\n    train_loss = 0.0\n    valid_loss = 0.0\n    train_correct = 0\n    valid_correct = 0\n    total_train = 0\n    total_valid = 0\n\n    ###################\n    # train the model #\n    ###################\n    model.train()\n    for data, target in train_loader:\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\n            data, target = data.cuda(), target.cuda()\n\n        # clear the gradients of all optimized variables\n        optimizer.zero_grad()\n\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model(data)\n\n        # calculate the batch loss\n        loss = criterion(output, target)\n\n        # backward pass: compute gradient of the loss with respect to model parameters\n        loss.backward()\n\n        # perform a single optimization step (parameter update)\n        optimizer.step()\n\n        # update training loss\n        train_loss += loss.item() * data.size(0)\n\n        # calculate accuracy\n        _, predicted = torch.max(output.data, 1)\n        total_train += target.size(0)\n        train_correct += (predicted == target).sum().item()\n\n    ######################\n    # validate the model #\n    ######################\n    model.eval()\n    for data, target in valid_loader:\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\n            data, target = data.cuda(), target.cuda()\n\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model(data)\n\n        # calculate the batch loss\n        loss = criterion(output, target)\n\n        # update average validation loss\n        valid_loss += loss.item() * data.size(0)\n\n        # calculate accuracy\n        _, predicted = torch.max(output.data, 1)\n        total_valid += target.size(0)\n        valid_correct += (predicted == target).sum().item()\n\n    # calculate average losses\n    train_loss = train_loss / len(train_loader.dataset)\n    valid_loss = valid_loss / len(valid_loader.dataset)\n\n    # calculate accuracy\n    train_accuracy = 100 * train_correct / total_train\n    valid_accuracy = 100 * valid_correct / total_valid\n\n    \n    train_loss_history.append(train_loss)\n    valid_loss_history.append(valid_loss)\n    train_accuracy_history.append(train_accuracy)\n    valid_accuracy_history.append(valid_accuracy)\n    \n    # print training/validation statistics\n    print(f'Epoch: {epoch} \\tTraining Loss: {train_loss:.6f} \\tValidation Loss: {valid_loss:.6f} \\tTraining Accuracy: {train_accuracy:.2f}% \\tValidation Accuracy: {valid_accuracy:.2f}%')\n\n\n    # save model if validation loss has decreased\n    if valid_loss <= valid_loss_min:\n        print(f'Validation loss decreased ({valid_loss_min:.6f} --> {valid_loss:.6f}).  Saving model ...')\n        torch.save(model.state_dict(), 'model_cifar.pt')\n        valid_loss_min = valid_loss\n\n\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T03:25:33.19895Z","iopub.execute_input":"2023-11-30T03:25:33.199311Z","iopub.status.idle":"2023-11-30T05:28:38.204312Z","shell.execute_reply.started":"2023-11-30T03:25:33.199263Z","shell.execute_reply":"2023-11-30T05:28:38.203442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **余弦退火学习率**","metadata":{"id":"ZEhqeE2QPWz3"}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"import torch.optim.lr_scheduler as lr_scheduler\n\ntrain_loss_history = []\nvalid_loss_history = []\ntrain_accuracy_history = []\nvalid_accuracy_history = []\n\n# number of epochs to train the model\nn_epochs = 10\n\nvalid_loss_min = np.Inf # track change in validation loss\n\n# Learning rate scheduler\nscheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=n_epochs)\n\nfor epoch in range(1, n_epochs+1):\n\n    # keep track of training and validation loss\n    train_loss = 0.0\n    valid_loss = 0.0\n    train_correct = 0\n    valid_correct = 0\n    total_train = 0\n    total_valid = 0\n\n    ###################\n    # train the model #\n    ###################\n    model.train()\n    for data, target in train_loader:\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\n            data, target = data.cuda(), target.cuda()\n\n        # clear the gradients of all optimized variables\n        optimizer.zero_grad()\n\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model(data)\n\n        # calculate the batch loss\n        loss = criterion(output, target)\n\n        # backward pass: compute gradient of the loss with respect to model parameters\n        loss.backward()\n\n        # perform a single optimization step (parameter update)\n        optimizer.step()\n\n        # update training loss\n        train_loss += loss.item() * data.size(0)\n\n        # calculate accuracy\n        _, predicted = torch.max(output.data, 1)\n        total_train += target.size(0)\n        train_correct += (predicted == target).sum().item()\n\n    ######################\n    # validate the model #\n    ######################\n    model.eval()\n    for data, target in valid_loader:\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\n            data, target = data.cuda(), target.cuda()\n\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model(data)\n\n        # calculate the batch loss\n        loss = criterion(output, target)\n\n        # update average validation loss\n        valid_loss += loss.item() * data.size(0)\n\n        # calculate accuracy\n        _, predicted = torch.max(output.data, 1)\n        total_valid += target.size(0)\n        valid_correct += (predicted == target).sum().item()\n\n    # calculate average losses\n    train_loss = train_loss / len(train_loader.dataset)\n    valid_loss = valid_loss / len(valid_loader.dataset)\n\n    # calculate accuracy\n    train_accuracy = 100 * train_correct / total_train\n    valid_accuracy = 100 * valid_correct / total_valid\n\n    \n    train_loss_history.append(train_loss)\n    valid_loss_history.append(valid_loss)\n    train_accuracy_history.append(train_accuracy)\n    valid_accuracy_history.append(valid_accuracy)\n    \n    # print training/validation statistics\n    print(f'Epoch: {epoch} \\tTraining Loss: {train_loss:.6f} \\tValidation Loss: {valid_loss:.6f} \\tTraining Accuracy: {train_accuracy:.2f}% \\tValidation Accuracy: {valid_accuracy:.2f}%')\n\n    # update learning rate\n    scheduler.step()\n\n    # save model if validation loss has decreased\n    if valid_loss <= valid_loss_min:\n        print(f'Validation loss decreased ({valid_loss_min:.6f} --> {valid_loss:.6f}).  Saving model ...')\n        torch.save(model.state_dict(), 'model_cifar.pt')\n        valid_loss_min = valid_loss\n\n\n    ","metadata":{"execution":{"iopub.status.busy":"2023-11-29T15:00:38.649771Z","iopub.execute_input":"2023-11-29T15:00:38.650195Z","iopub.status.idle":"2023-11-29T15:04:46.816793Z","shell.execute_reply.started":"2023-11-29T15:00:38.650157Z","shell.execute_reply":"2023-11-29T15:04:46.81551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('ggplot')\nplt.plot(train_loss_history, label='training loss')\nplt.plot(valid_loss_history, label='validation loss')\nplt.legend()","metadata":{"id":"SkdvnviRSGib","outputId":"c2d47421-0d5f-4e5d-9bb8-a193c372b340","execution":{"iopub.status.busy":"2023-11-30T05:44:47.847862Z","iopub.execute_input":"2023-11-30T05:44:47.848256Z","iopub.status.idle":"2023-11-30T05:44:48.030265Z","shell.execute_reply.started":"2023-11-30T05:44:47.848221Z","shell.execute_reply":"2023-11-30T05:44:48.029331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('ggplot')\nplt.plot(train_accuracy_history, label='training accuracy')\nplt.plot(valid_accuracy_history, label='validation accuracy')\nplt.legend()","metadata":{"id":"Tita9-UqUaXb","outputId":"b732e53d-a6e5-482e-edb4-0e22b8878ebe","execution":{"iopub.status.busy":"2023-11-30T05:45:04.872881Z","iopub.execute_input":"2023-11-30T05:45:04.873252Z","iopub.status.idle":"2023-11-30T05:45:05.057441Z","shell.execute_reply.started":"2023-11-30T05:45:04.873218Z","shell.execute_reply":"2023-11-30T05:45:05.056656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track test loss\ntest_loss = 0.0\nclass_correct = list(0. for i in range(10))\nclass_total = list(0. for i in range(10))\n\nmodel.eval()\n# iterate over test data\nfor data, target in test_loader:\n    # move tensors to GPU if CUDA is available\n    if train_on_gpu:\n        data, target = data.cuda(), target.cuda()\n    # forward pass: compute predicted outputs by passing inputs to the model\n    output = model(data)\n    # calculate the batch loss\n    loss = criterion(output, target)\n    # update test loss \n    test_loss += loss.item()*data.size(0)\n    # convert output probabilities to predicted class\n    _, pred = torch.max(output, 1)    \n    # compare predictions to true label\n    correct_tensor = pred.eq(target.data.view_as(pred))\n    correct = np.squeeze(correct_tensor.numpy()) if not train_on_gpu else np.squeeze(correct_tensor.cpu().numpy())\n    # calculate test accuracy for each object class\n\n\n    for i in range(data.size(0)):###  使用实际batch_size\n        label = target.data[i]\n        class_correct[label] += correct[i].item()\n        class_total[label] += 1\n\n# average test loss\ntest_loss = test_loss/len(test_loader.dataset)\nprint('Test Loss: {:.6f}\\n'.format(test_loss))\n\nfor i in range(10):\n    if class_total[i] > 0:\n        print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (\n            class_names[i], 100 * class_correct[i] / class_total[i],\n            np.sum(class_correct[i]), np.sum(class_total[i])))\n    else:\n        print('Test Accuracy of %5s: N/A (no training examples)' % (class_names[i]))\n\nprint('\\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (\n    100. * np.sum(class_correct) / np.sum(class_total),\n    np.sum(class_correct), np.sum(class_total)))","metadata":{"execution":{"iopub.status.busy":"2023-11-30T05:45:33.441258Z","iopub.execute_input":"2023-11-30T05:45:33.441604Z","iopub.status.idle":"2023-11-30T05:45:37.836168Z","shell.execute_reply.started":"2023-11-30T05:45:33.441573Z","shell.execute_reply":"2023-11-30T05:45:37.835171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport torch\nimport numpy as np\n\n# Function to display an image\ndef imshow(img):\n    img = img / 2 + 0.5  # unnormalize\n    plt.imshow(np.transpose(img, (1, 2, 0)))  # convert from Tensor image\n\n# obtain one batch of test images\ndataiter = iter(test_loader)\nimages, labels = next(dataiter)\n\n# move model inputs to cuda, if GPU available\nif train_on_gpu:\n    images = images.cuda()\n\n# get sample outputs\noutput = model(images)\n# convert output probabilities to predicted class\n_, preds_tensor = torch.max(output, 1)\npreds = np.squeeze(preds_tensor.numpy()) if not train_on_gpu else np.squeeze(preds_tensor.cpu().numpy())\n\n# calculate the class probabilities (softmax) for img\nsoftmax = torch.nn.Softmax(dim=1)\nprobs = softmax(output)\nconfidences = probs.max(dim=1)[0]\n\n# move images to cpu for displaying\nif train_on_gpu:\n    images = images.cpu()\n\n# plot the images in the batch, along with predicted and true labels and confidence\nfig = plt.figure(figsize=(25, 4))\nfor idx in np.arange(10):\n    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])\n    imshow(images[idx])\n    ax.set_title(f\"Pred: {class_names[preds[idx]]}\\nTrue: {class_names[labels[idx]]}\\nConf: {confidences[idx].item():.2f}\",\n                 color=(\"green\" if preds[idx] == labels[idx].item() else \"red\"))\n","metadata":{"execution":{"iopub.status.busy":"2023-11-30T05:47:03.939627Z","iopub.execute_input":"2023-11-30T05:47:03.939955Z","iopub.status.idle":"2023-11-30T05:47:04.348481Z","shell.execute_reply.started":"2023-11-30T05:47:03.939923Z","shell.execute_reply":"2023-11-30T05:47:04.347659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL.ImageOps","metadata":{"id":"M-kfhdeRUqAU","execution":{"iopub.status.busy":"2023-11-30T06:08:21.445185Z","iopub.execute_input":"2023-11-30T06:08:21.445561Z","iopub.status.idle":"2023-11-30T06:08:21.449634Z","shell.execute_reply.started":"2023-11-30T06:08:21.445526Z","shell.execute_reply":"2023-11-30T06:08:21.448703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import requests\nfrom PIL import Image\n\nurl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcT76mSMtKQWGstcqGi-0kPWJyVBqz8RCp8SuplMipkidRY0z9Mc&usqp=CAU'\nresponse = requests.get(url, stream = True)\nimg = Image.open(response.raw)\nplt.imshow(img)","metadata":{"id":"i6OmihC2WREM","outputId":"571c3beb-cbe4-4f6d-af96-698eba8829da","execution":{"iopub.status.busy":"2023-11-30T06:08:23.029051Z","iopub.execute_input":"2023-11-30T06:08:23.029414Z","iopub.status.idle":"2023-11-30T06:08:23.242319Z","shell.execute_reply.started":"2023-11-30T06:08:23.029381Z","shell.execute_reply":"2023-11-30T06:08:23.241481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([transforms.Resize((32,32)),\n                               transforms.ToTensor(),\n                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n                               ])","metadata":{"execution":{"iopub.status.busy":"2023-11-30T06:10:37.265204Z","iopub.execute_input":"2023-11-30T06:10:37.265543Z","iopub.status.idle":"2023-11-30T06:10:37.270562Z","shell.execute_reply.started":"2023-11-30T06:10:37.265512Z","shell.execute_reply":"2023-11-30T06:10:37.269719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2023-11-30T06:05:55.445486Z","iopub.execute_input":"2023-11-30T06:05:55.445852Z","iopub.status.idle":"2023-11-30T06:05:55.450347Z","shell.execute_reply.started":"2023-11-30T06:05:55.445815Z","shell.execute_reply":"2023-11-30T06:05:55.449247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image = img.to(device).unsqueeze(0) # put inputs in device as our model is running there\noutput = model(image)\n_, pred = torch.max(output, 1)\n\n# calculate the class probabilities (softmax) for img\nsoftmax = torch.nn.Softmax(dim=1)\nprobs = softmax(output)\nconfidences = probs.max(dim=1)[0]\n\nprint(\"Pred:\"+class_names[pred.item()],\", True:dog\", \", Confidence value:\", confidences.item())","metadata":{"id":"VpThBSTAYFb8","outputId":"037d6082-5faf-4e59-ca02-b07f101780ea","execution":{"iopub.status.busy":"2023-11-30T06:27:42.054775Z","iopub.execute_input":"2023-11-30T06:27:42.055165Z","iopub.status.idle":"2023-11-30T06:27:42.066318Z","shell.execute_reply.started":"2023-11-30T06:27:42.055126Z","shell.execute_reply":"2023-11-30T06:27:42.064903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"jupyter":{"source_hidden":true}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Use the images from our validation dataset to check the precdictions","metadata":{"id":"5bpivp0QYpKI"}},{"cell_type":"code","source":"\ndataiter = iter(validation_loader)\nimages, labels = dataiter.next()\nimages = images.to(device)\nlabels = labels.to(device)\noutput = model(images)\n_, preds = torch.max(output, 1)\n\nfig = plt.figure(figsize=(25, 4))\n\nfor idx in np.arange(20):\n  ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])\n  plt.imshow(im_convert(images[idx]))\n  ax.set_title(\"{} ({})\".format(str(classes[preds[idx].item()]), str(classes[labels[idx].item()])), color=(\"green\" if preds[idx]==labels[idx] else \"red\"))","metadata":{"id":"HazD4SzhYcTV","outputId":"206d94da-2b12-4687-a721-e962ed3ecc5c","execution":{"iopub.status.busy":"2023-11-30T06:25:00.471648Z","iopub.execute_input":"2023-11-30T06:25:00.472019Z","iopub.status.idle":"2023-11-30T06:25:00.493024Z","shell.execute_reply.started":"2023-11-30T06:25:00.471981Z","shell.execute_reply":"2023-11-30T06:25:00.491817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**As seen the predictions on new images are really good. Maybe by running more epochs I can get better accuracy or some more hyper parameter tuning will help. Additionally I am sure that Transfer learning will yield much better accuracy, if I use Vgg16 for suppose. But for this case I wanted to code my own model. Even though LeNet is a old it is still a very good model to start with.**\n> I have build this on PyTorch but personally I like Tensorflow Keras more. Thats my opinion.\nLet me know the suggestions for hyper parameter tunning for the same model.","metadata":{"id":"4V4Sf-B-YzP4"}},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}