|
10 | 10 | " <td align=\"center\"><a target=\"_blank\" href=\"http://introtodeeplearning.com\">\n", |
11 | 11 | " <img src=\"https://i.ibb.co/Jr88sn2/mit.png\" style=\"padding-bottom:5px;\" />\n", |
12 | 12 | " Visit MIT Deep Learning</a></td>\n", |
13 | | - " <td align=\"center\"><a target=\"_blank\" href=\"https://colab.research.google.com/github/aamini/introtodeeplearning/blob/master/lab2/solutions/PT_Part1_MNIST_Solution.ipynb\">\n", |
| 13 | + " <td align=\"center\"><a target=\"_blank\" href=\"https://colab.research.google.com/github/MITDeepLearning/introtodeeplearning/blob/master/lab2/PT_Part1_MNIST.ipynb\">\n", |
14 | 14 | " <img src=\"https://i.ibb.co/2P3SLwK/colab.png\" style=\"padding-bottom:5px;\" />Run in Google Colab</a></td>\n", |
15 | | - " <td align=\"center\"><a target=\"_blank\" href=\"https://github.com/aamini/introtodeeplearning/blob/master/lab2/solutions/PT_Part1_MNIST_Solution.ipynb\">\n", |
| 15 | + " <td align=\"center\"><a target=\"_blank\" href=\"https://github.com/MITDeepLearning/introtodeeplearning/blob/master/lab2/PT_Part1_MNIST.ipynb\">\n", |
16 | 16 | " <img src=\"https://i.ibb.co/xfJbPmL/github.png\" height=\"70px\" style=\"padding-bottom:5px;\" />View Source on GitHub</a></td>\n", |
17 | 17 | "</table>\n", |
18 | 18 | "\n", |
|
252 | 252 | "\n", |
253 | 253 | " # '''TODO: Define the activation function for the first fully connected (Dense/Linear) layer.'''\n", |
254 | 254 | " nn.Linear(28 * 28, 128),\n", |
255 | | - " nn.ReLU(),\n", |
256 | | - " # activation function = '''TODO'''\n", |
| 255 | + " '''TODO'''\n", |
257 | 256 | "\n", |
258 | | - " # '''TODO: Define the second Linear layer to output the classification probabilities'''\n", |
259 | | - " nn.Linear(128, 10),\n", |
260 | | - " nn.Softmax(dim=1) # Softmax activation for probabilities\n", |
261 | | - " # '''TODO: Linear layer and activation to output classification probabilities'''\n", |
| 257 | + " '''TODO: Define the second Linear layer to output the classification probabilities'''\n", |
262 | 258 | " )\n", |
263 | 259 | " return fc_model\n", |
264 | 260 | "\n", |
|
321 | 317 | " self.fc1 = nn.Linear(28 * 28, 128)\n", |
322 | 318 | "\n", |
323 | 319 | " # '''TODO: Define the activation function for the first fully connected layer'''\n", |
324 | | - " self.relu = nn.ReLU()\n", |
| 320 | + " self.relu = # TODO\n", |
325 | 321 | "\n", |
326 | 322 | " # '''TODO: Define the second Linear layer to output the classification probabilities'''\n", |
327 | | - " self.fc2 = nn.Linear(128, 10)\n", |
328 | | - " self.softmax = nn.Softmax(dim=1)\n", |
329 | | - " # self.fc2 = # TODO\n", |
330 | | - " # self.softmax = # TODO\n", |
| 323 | + " self.fc2 = # TODO\n", |
331 | 324 | "\n", |
332 | 325 | " def forward(self, x):\n", |
333 | 326 | " x = self.flatten(x)\n", |
334 | 327 | " x = self.fc1(x)\n", |
335 | 328 | "\n", |
336 | 329 | " # '''TODO: Implement the rest of forward pass of the model using the layers you have defined above'''\n", |
337 | | - " x = self.relu(x)\n", |
338 | | - " x = self.fc2(x)\n", |
339 | | - " # '''TODO'''\n", |
340 | | - "\n", |
341 | | - " '''NOTE: In Pytorch, softmax is omitted in training since CrossEntropyLoss includes\n", |
342 | | - " LogSoftmax; using both would result in incorrect loss values.\n", |
343 | | - " Since we will train with CrossEntropyLoss, we do not need something like:\n", |
344 | | - " x = self.softmax(x) '''\n", |
| 330 | + " '''TODO'''\n", |
345 | 331 | "\n", |
346 | 332 | " return x\n", |
347 | 333 | "\n", |
|
430 | 416 | " for images, labels in trainset_loader:\n", |
431 | 417 | " # Move tensors to GPU so compatible with model\n", |
432 | 418 | " images, labels = images.to(device), labels.to(device)\n", |
433 | | - " # Clear gradients before performing backward pass\n", |
434 | | - " optimizer.zero_grad()\n", |
| 419 | + "\n", |
435 | 420 | " # Forward pass\n", |
436 | 421 | " outputs = fc_model(images)\n", |
| 422 | + "\n", |
| 423 | + " # Clear gradients before performing backward pass\n", |
| 424 | + " optimizer.zero_grad()\n", |
437 | 425 | " # Calculate loss based on model predictions\n", |
438 | 426 | " loss = loss_function(outputs, labels)\n", |
439 | 427 | " # Backpropagate and update model parameters\n", |
440 | 428 | " loss.backward()\n", |
441 | 429 | " optimizer.step()\n", |
| 430 | + "\n", |
442 | 431 | " # multiply loss by total nos. of samples in batch\n", |
443 | 432 | " total_loss += loss.item()*images.size(0)\n", |
444 | 433 | "\n", |
|
463 | 452 | "source": [ |
464 | 453 | "# TODO: Train the model by calling the function appropriately\n", |
465 | 454 | "EPOCHS = 5\n", |
466 | | - "train(fc_model, trainset_loader, loss_function, optimizer, EPOCHS)\n", |
467 | | - "# train('''TODO''') # TODO\n", |
| 455 | + "train('''TODO''') # TODO\n", |
468 | 456 | "\n", |
469 | 457 | "comet_model_1.end()" |
470 | 458 | ] |
|
512 | 500 | " with torch.no_grad():\n", |
513 | 501 | " for images, labels in testset_loader:\n", |
514 | 502 | " # TODO: ensure evalaution happens on the GPU\n", |
515 | | - " images, labels = images.to(device), labels.to(device)\n", |
516 | | - " # images, labels = # TODO\n", |
| 503 | + " images, labels = # TODO\n", |
517 | 504 | "\n", |
518 | 505 | " # TODO: feed the images into the model and obtain the predictions (forward pass)\n", |
519 | | - " outputs = model(images)\n", |
520 | | - " # outputs = # TODO\n", |
| 506 | + " outputs = # TODO\n", |
521 | 507 | "\n", |
522 | 508 | " loss = loss_function(outputs, labels)\n", |
523 | 509 | "\n", |
524 | 510 | " # TODO: Calculate test loss\n", |
525 | | - " test_loss += loss.item() * images.size(0)\n", |
526 | | - " # test_loss += # TODO\n", |
| 511 | + " test_loss += # TODO\n", |
527 | 512 | "\n", |
528 | 513 | " '''TODO: make a prediction and determine whether it is correct!'''\n", |
529 | 514 | " # TODO: identify the digit with the highest probability prediction for the images in the test dataset.\n", |
530 | | - " predicted = torch.argmax(outputs, dim=1)\n", |
531 | | - " # predicted = # TODO\n", |
| 515 | + " predicted = # torch.argmax('''TODO''')\n", |
532 | 516 | "\n", |
533 | 517 | " # TODO: tally the number of correct predictions\n", |
534 | | - " correct_pred += (predicted == labels).sum().item()\n", |
535 | | - " # correct_pred += TODO\n", |
| 518 | + " correct_pred += TODO\n", |
| 519 | + "\n", |
536 | 520 | " # TODO: tally the total number of predictions\n", |
537 | | - " total_pred += labels.size(0)\n", |
538 | | - " # total_pred += TODO\n", |
| 521 | + " total_pred += TODO\n", |
539 | 522 | "\n", |
540 | 523 | " # Compute average loss and accuracy\n", |
541 | 524 | " test_loss /= total_pred\n", |
542 | 525 | " test_acc = correct_pred / total_pred\n", |
543 | 526 | " return test_loss, test_acc\n", |
544 | 527 | "\n", |
545 | 528 | "# TODO: call the evaluate function to evaluate the trained model!!\n", |
546 | | - "test_loss, test_acc = evaluate(fc_model, trainset_loader, loss_function)\n", |
547 | | - "# test_loss, test_acc = # TODO\n", |
| 529 | + "test_loss, test_acc = # TODO\n", |
548 | 530 | "\n", |
549 | 531 | "print('Test accuracy:', test_acc)" |
550 | 532 | ] |
|
607 | 589 | " def __init__(self):\n", |
608 | 590 | " super(CNN, self).__init__()\n", |
609 | 591 | " # TODO: Define the first convolutional layer\n", |
610 | | - " self.conv1 = nn.Conv2d(1, 24, kernel_size=3)\n", |
611 | | - " # self.conv1 = # TODO\n", |
| 592 | + " self.conv1 = # TODO\n", |
612 | 593 | "\n", |
613 | 594 | " # TODO: Define the first max pooling layer\n", |
614 | | - " self.pool1 = nn.MaxPool2d(kernel_size=2)\n", |
615 | | - " # self.pool1 = # TODO\n", |
| 595 | + " self.pool1 = # TODO\n", |
616 | 596 | "\n", |
617 | 597 | " # TODO: Define the second convolutional layer\n", |
618 | | - " self.conv2 = nn.Conv2d(24, 36, kernel_size=3)\n", |
619 | | - " # self.conv2 = # TODO\n", |
| 598 | + " self.conv2 = # TODO\n", |
620 | 599 | "\n", |
621 | 600 | " # TODO: Define the second max pooling layer\n", |
622 | | - " self.pool2 = nn.MaxPool2d(kernel_size=2)\n", |
623 | | - " # self.pool2 = # TODO\n", |
| 601 | + " self.pool2 = # TODO\n", |
624 | 602 | "\n", |
625 | 603 | " self.flatten = nn.Flatten()\n", |
626 | 604 | " self.fc1 = nn.Linear(36 * 5 * 5, 128)\n", |
627 | 605 | " self.relu = nn.ReLU()\n", |
628 | 606 | "\n", |
629 | 607 | " # TODO: Define the Linear layer that outputs the classification\n", |
630 | 608 | " # logits over class labels. Remember that CrossEntropyLoss operates over logits.\n", |
631 | | - " self.fc2 = nn.Linear(128, 10)\n", |
632 | | - " # self.fc2 = # TODO\n", |
| 609 | + " self.fc2 = # TODO\n", |
633 | 610 | "\n", |
634 | 611 | "\n", |
635 | 612 | " def forward(self, x):\n", |
|
640 | 617 | "\n", |
641 | 618 | " # '''TODO: Implement the rest of forward pass of the model using the layers you have defined above'''\n", |
642 | 619 | " # '''hint: this will involve another set of convolutional/pooling layers and then the linear layers'''\n", |
643 | | - " x = self.conv2(x)\n", |
644 | | - " x = self.relu(x)\n", |
645 | | - " x = self.pool2(x)\n", |
646 | | - "\n", |
647 | | - " x = self.flatten(x)\n", |
648 | | - " x = self.fc1(x)\n", |
649 | | - " x = self.relu(x)\n", |
650 | | - " x = self.fc2(x)\n", |
651 | | - "\n", |
652 | | - " '''NOTE: Remember that we do not need to define/execute softmax (self.softmax(x))\n", |
653 | | - " in the forward pass since we will use CrossEntropyLoss for training,\n", |
654 | | - " which operates directly on logits'''\n", |
| 620 | + " '''TODO'''\n", |
655 | 621 | "\n", |
656 | 622 | " return x\n", |
657 | 623 | "\n", |
|
697 | 663 | "optimizer = optim.SGD(cnn_model.parameters(), lr=1e-2)\n", |
698 | 664 | "\n", |
699 | 665 | "# TODO: instantiate the cross entropy loss function\n", |
700 | | - "loss_function = nn.CrossEntropyLoss()\n", |
701 | | - "# loss_function = # TODO\n", |
| 666 | + "loss_function = # TODO\n", |
702 | 667 | "\n", |
703 | 668 | "# Redefine trainloader with new batch size parameter (tweak as see fit if optimizing)\n", |
704 | 669 | "trainset_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n", |
|
735 | 700 | " images, labels = images.to(device), labels.to(device)\n", |
736 | 701 | "\n", |
737 | 702 | " # Forward pass\n", |
738 | | - " #'''TODO: feed the images into the model and obtain the predictions'''\n", |
739 | | - " logits = cnn_model(images)\n", |
740 | | - " # logits = # TODO\n", |
| 703 | + " # TODO: feed the images into the model and obtain the predictions\n", |
| 704 | + " logits = # TODO\n", |
| 705 | + "\n", |
| 706 | + " # TODO: compute the categorical cross entropy loss using the predicted logits\n", |
| 707 | + " loss = # TODO\n", |
741 | 708 | "\n", |
742 | | - " #'''TODO: compute the categorical cross entropy loss\n", |
743 | | - " loss = loss_function(logits, labels)\n", |
744 | | - " # loss = # TODO\n", |
745 | 709 | " # Get the loss and log it to comet and the loss_history record\n", |
746 | 710 | " loss_value = loss.item()\n", |
747 | 711 | " comet_model_2.log_metric(\"loss\", loss_value, step=idx)\n", |
|
751 | 715 | " # Backpropagation/backward pass\n", |
752 | 716 | " '''TODO: Compute gradients for all model parameters and propagate backwads\n", |
753 | 717 | " to update model parameters. remember to reset your optimizer!'''\n", |
754 | | - " optimizer.zero_grad()\n", |
755 | | - " loss.backward()\n", |
756 | | - " optimizer.step()\n", |
| 718 | + " # TODO: reset optimizer\n", |
| 719 | + " # TODO: compute gradients\n", |
| 720 | + " # TODO: update model parameters\n", |
757 | 721 | "\n", |
758 | 722 | " # Get the prediction and tally metrics\n", |
759 | 723 | " predicted = torch.argmax(logits, dim=1)\n", |
|
788 | 752 | "outputs": [], |
789 | 753 | "source": [ |
790 | 754 | "'''TODO: Evaluate the CNN model!'''\n", |
791 | | - "\n", |
792 | | - "test_loss, test_acc = evaluate(cnn_model, trainset_loader, loss_function)\n", |
793 | | - "# test_loss, test_acc = # TODO\n", |
| 755 | + "test_loss, test_acc = evaluate('''TODO''')\n", |
794 | 756 | "\n", |
795 | 757 | "print('Test accuracy:', test_acc)" |
796 | 758 | ] |
|
850 | 812 | }, |
851 | 813 | "outputs": [], |
852 | 814 | "source": [ |
853 | | - "predictions_test_image" |
| 815 | + "print(predictions_test_image)" |
854 | 816 | ] |
855 | 817 | }, |
856 | 818 | { |
|
875 | 837 | "'''TODO: identify the digit with the highest likelihood prediction for the first\n", |
876 | 838 | " image in the test dataset. '''\n", |
877 | 839 | "predictions_value = predictions_test_image.cpu().detach().numpy() #.cpu() to copy tensor to memory first\n", |
878 | | - "prediction = np.argmax(predictions_value)\n", |
879 | | - "# prediction = # TODO\n", |
| 840 | + "prediction = # TODO\n", |
880 | 841 | "print(prediction)" |
881 | 842 | ] |
882 | 843 | }, |
|
935 | 896 | " probabilities = torch.nn.functional.softmax(outputs, dim=1)\n", |
936 | 897 | "\n", |
937 | 898 | " # Get predicted classes\n", |
938 | | - " predicted = torch.argmax(outputs, dim=1)\n", |
| 899 | + " predicted = torch.argmax(probabilities, dim=1)\n", |
939 | 900 | "\n", |
940 | 901 | " all_predictions.append(probabilities)\n", |
941 | 902 | " all_labels.append(labels)\n", |
|
1018 | 979 | "collapsed_sections": [ |
1019 | 980 | "Xmf_JRJa_N8C" |
1020 | 981 | ], |
1021 | | - "name": "PT_Part1_MNIST_Solution.ipynb", |
| 982 | + "name": "PT_Part1_MNIST.ipynb", |
1022 | 983 | "provenance": [] |
1023 | 984 | }, |
1024 | 985 | "kernelspec": { |
|
0 commit comments