pytorch-stuff/CNN - MNIST.ipynb

490 lines
71 KiB
Plaintext
Executable File

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import torch.nn as nn\n",
"import torchvision.transforms as transforms\n",
"import torchvision.datasets as datasets"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"mean_gray = 0.1307\n",
"stddev_gray = 0.3081\n",
"\n",
"# input[channel] = (input[channel]-meaan[channel]) / std[channel]\n",
"\n",
"transforms = transforms.Compose([transforms.ToTensor(),\n",
" transforms.Normalize((mean_gray,),(stddev_gray,))])\n",
"\n",
"train_dataset = datasets.MNIST(root='./data', \n",
" train=True, \n",
" transform=transforms, \n",
" download=True)\n",
"\n",
"test_dataset = datasets.MNIST(root='./data', \n",
" train=False, \n",
" transform=transforms)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fd7823b2f10>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"random_img = train_dataset[20][0].numpy() * stddev_gray + mean_gray\n",
"plt.imshow(random_img.reshape(28,28), cmap='gray')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
}
],
"source": [
"print(train_dataset[20][1])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"batch_size = 100\n",
"\n",
"train_load = torch.utils.data.DataLoader(dataset=train_dataset,\n",
" batch_size=batch_size,\n",
" shuffle=True)\n",
"\n",
"test_load = torch.utils.data.DataLoader(dataset=test_dataset,\n",
" batch_size=batch_size,\n",
" shuffle=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"100"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(test_load)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class CNN(nn.Module):\n",
" def __init__(self):\n",
" super(CNN,self).__init__()\n",
" # Same padding means that input_size = output_size\n",
" # same_padding = (filter_size - 1) / 2\n",
" self.cnn1 = nn.Conv2d(in_channels=1, out_channels=8, kernel_size=(3,3), stride=1, padding=1)\n",
" # The output from this layer has size:\n",
" # [(input_size - filter_size + 2*(padding)) / stride] + 1\n",
" self.batchnorm1 = nn.BatchNorm2d(8)\n",
" self.relu = nn.ReLU()\n",
" self.maxpool = nn.MaxPool2d(kernel_size=(2,2))\n",
" # Pooling output size is 28/2 = 14 (downsampling)\n",
" # Same padding size is (5 - 1)/2 = 2\n",
" self.cnn2 = nn.Conv2d(in_channels=8, out_channels=32, kernel_size=(5,5), stride=1, padding=2)\n",
" self.batchnorm2 = nn.BatchNorm2d(32)\n",
" # Pooling output size is 14/2 = 7 (downsampling)\n",
" # We have to flatten the output channels 32*7*7 = 1568\n",
" self.fc1 = nn.Linear(1568,600)\n",
" self.dropout = nn.Dropout(p=0.5)\n",
" self.fc2 = nn.Linear(600,10)\n",
" \n",
" def forward(self,x):\n",
" out = self.cnn1(x)\n",
" out = self.batchnorm1(out)\n",
" out = self.relu(out)\n",
" out = self.maxpool(out)\n",
" out = self.cnn2(out)\n",
" out = self.batchnorm2(out)\n",
" out = self.relu(out)\n",
" out = self.maxpool(out)\n",
" # we have to flatten the 32 feature maps, output of our last maxpool (100, 1568)\n",
" out = out.view(-1, 1568) # <- setting the number of rows to -1 is important, because \n",
" out = self.fc1(out) # when we try to predict we would require to use a size 100 (batch size)\n",
" out = self.relu(out) # tensor but -1 infers the size.\n",
" out = self.dropout(out)\n",
" out = self.fc2(out)\n",
" \n",
" return out\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"model = CNN()\n",
"\n",
"CUDA = torch.cuda.is_available()\n",
"\n",
"if CUDA:\n",
" model = model.cuda()\n",
" \n",
"loss_fn = nn.CrossEntropyLoss()\n",
"optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"For one iteration this is what happens:\n",
"Input shape: torch.Size([100, 1, 28, 28])\n",
"Labels shape: torch.Size([100])\n",
"Output shape: torch.Size([100, 10])\n",
"Predicted shape: torch.Size([100, 1, 28, 28])\n",
"Predicted tensor: \n",
"tensor([7, 9, 6, 3, 4, 9, 7, 6, 9, 9, 3, 3, 3, 5, 4, 2, 3, 9, 9, 3, 4, 6, 4, 4,\n",
" 3, 2, 9, 2, 2, 4, 9, 6, 9, 2, 4, 3, 9, 2, 4, 5, 6, 4, 9, 2, 2, 9, 2, 9,\n",
" 7, 9, 9, 6, 9, 6, 2, 6, 3, 4, 4, 2, 6, 2, 4, 6, 4, 7, 7, 4, 9, 7, 8, 9,\n",
" 6, 6, 4, 4, 8, 6, 2, 4, 8, 2, 3, 6, 4, 3, 2, 2, 8, 9, 4, 9, 3, 4, 6, 4,\n",
" 3, 4, 3, 6])\n"
]
}
],
"source": [
"# Understand what is happening\n",
"iteration = 0\n",
"correct = 0\n",
"\n",
"for i,(inputs, labels) in enumerate(train_load):\n",
" \n",
" if CUDA:\n",
" inputs = inputs.cuda()\n",
" labels = labels.cuda()\n",
" \n",
" print('For one iteration this is what happens:')\n",
" print('Input shape: ', inputs.shape)\n",
" print('Labels shape: ', labels.shape)\n",
" output = model(inputs)\n",
" print('Output shape: ', output.shape)\n",
" _, predicted = torch.max(output, dim=1)\n",
" print('Predicted shape: ', inputs.shape)\n",
" print('Predicted tensor: ')\n",
" print(predicted)\n",
" correct += (predicted==labels).sum()\n",
" break\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/10, Training loss: 1.153, Training accuracy: 0.626, Testing loss: 6.920, Testing accuracy: 0.969\n",
"Epoch 2/10, Training loss: 0.341, Training accuracy: 0.885, Testing loss: 2.045, Testing accuracy: 0.981\n",
"Epoch 3/10, Training loss: 0.156, Training accuracy: 0.954, Testing loss: 0.937, Testing accuracy: 0.985\n",
"Epoch 4/10, Training loss: 0.106, Training accuracy: 0.970, Testing loss: 0.635, Testing accuracy: 0.987\n",
"Epoch 5/10, Training loss: 0.090, Training accuracy: 0.974, Testing loss: 0.539, Testing accuracy: 0.988\n",
"Epoch 6/10, Training loss: 0.077, Training accuracy: 0.978, Testing loss: 0.461, Testing accuracy: 0.989\n",
"Epoch 7/10, Training loss: 0.071, Training accuracy: 0.980, Testing loss: 0.428, Testing accuracy: 0.988\n",
"Epoch 8/10, Training loss: 0.068, Training accuracy: 0.980, Testing loss: 0.411, Testing accuracy: 0.990\n",
"Epoch 9/10, Training loss: 0.060, Training accuracy: 0.983, Testing loss: 0.361, Testing accuracy: 0.989\n",
"Epoch 10/10, Training loss: 0.062, Training accuracy: 0.982, Testing loss: 0.372, Testing accuracy: 0.990\n"
]
},
{
"data": {
"text/plain": [
"\"\\n\\n#Training the CNN\\nnum_epochs = 10\\n\\n#Define the lists to store the results of loss and accuracy\\ntrain_loss = []\\ntest_loss = []\\ntrain_accuracy = []\\ntest_accuracy = []\\n\\n#Training\\nfor epoch in range(num_epochs): \\n #Reset these below variables to 0 at the begining of every epoch\\n correct = 0\\n iterations = 0\\n iter_loss = 0.0\\n \\n model.train() # Put the network into training mode\\n \\n for i, (inputs, labels) in enumerate(train_load):\\n \\n if CUDA:\\n inputs = inputs.cuda()\\n labels = labels.cuda()\\n \\n outputs = model(inputs) \\n loss = loss_fn(outputs, labels) \\n iter_loss += loss.item() # Accumulate the loss\\n optimizer.zero_grad() # Clear off the gradient in (w = w - gradient)\\n loss.backward() # Backpropagation \\n optimizer.step() # Update the weights\\n \\n # Record the correct predictions for training data \\n _, predicted = torch.max(outputs, 1)\\n correct += (predicted == labels).sum()\\n iterations += 1\\n \\n # Record the training loss\\n train_loss.append(iter_loss/iterations)\\n # Record the training accuracy\\n train_accuracy.append((100 * correct / len(train_dataset)))\\n \\n #Testing\\n testing_loss = 0.0\\n correct = 0\\n iterations = 0\\n\\n model.eval() # Put the network into evaluation mode\\n \\n for i, (inputs, labels) in enumerate(test_load):\\n\\n if CUDA:\\n inputs = inputs.cuda()\\n labels = labels.cuda()\\n \\n outputs = model(inputs) \\n loss = loss_fn(outputs, labels) # Calculate the loss\\n testing_loss += loss.item()\\n # Record the correct predictions for training data\\n _, predicted = torch.max(outputs, 1)\\n correct += (predicted == labels).sum()\\n \\n iterations += 1\\n\\n # Record the Testing loss\\n test_loss.append(testing_loss/iterations)\\n # Record the Testing accuracy\\n test_accuracy.append((100 * correct / len(test_dataset)))\\n \\n print ('Epoch {}/{}, Training Loss: {:.3f}, Training Accuracy: {:.3f}, Testing Loss: {:.3f}, Testing Acc: {:.3f}'\\n .format(epoch+1, num_epochs, train_loss[-1], train_accuracy[-1], \\n test_loss[-1], test_accuracy[-1]))\\n\""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Training of the CNN\n",
"num_epochs = 10\n",
"train_loss = list()\n",
"train_accuracy = list()\n",
"test_loss = list()\n",
"test_accuracy = list()\n",
"\n",
"\n",
"for epoch in range(num_epochs):\n",
" correct = 0\n",
" iterations = 0\n",
" iter_loss = 0.0\n",
" \n",
" # When batch normalization and dropout are used\n",
" # we have to specify our model that we are training\n",
" model.train()\n",
" \n",
" for i,(inputs, labels) in enumerate(train_load):\n",
" \n",
" if CUDA:\n",
" inputs = inputs.cuda()\n",
" labels = labels.cuda()\n",
" \n",
" outputs = model(inputs)\n",
" loss = loss_fn(outputs,labels)\n",
" iter_loss += loss.item()\n",
" \n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" \n",
" _, predicted = torch.max(outputs, dim=1)\n",
" correct += (predicted==labels).sum().item()\n",
" iterations += 1\n",
" \n",
" train_loss.append(iter_loss/iterations)\n",
" train_accuracy.append(correct/len(train_dataset))\n",
" \n",
" # Testing phase\n",
" testing_loss = 0.0\n",
" correct = 0\n",
" iterations = 0\n",
" \n",
" model.eval()\n",
" \n",
" for i,(inputs, labels) in enumerate(test_load):\n",
" \n",
" if CUDA:\n",
" inputs = inputs.cuda()\n",
" labels = labels.cuda()\n",
" \n",
" outputs = model(inputs)\n",
" loss = loss_fn(outputs,labels)\n",
" testing_loss += loss.item()\n",
" \n",
" _, predicted = torch.max(outputs, dim=1)\n",
" correct += (predicted==labels).sum().item()\n",
" iterations += 1\n",
" \n",
" test_loss.append(iter_loss/iterations)\n",
" test_accuracy.append(correct/len(test_dataset))\n",
" \n",
" print('Epoch {}/{}, Training loss: {:.3f}, Training accuracy: {:.3f}, Testing loss: {:.3f}, Testing accuracy: {:.3f}'.format(\n",
" epoch+1,num_epochs,train_loss[-1],train_accuracy[-1],test_loss[-1],test_accuracy[-1]))\n",
"\n",
"\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Plotting the loss\n",
"\n",
"f = plt.figure(figsize=(10,10))\n",
"plt.plot(train_loss, label='Training loss')\n",
"plt.plot(test_loss, label='Testing loss')\n",
"plt.legend()\n",
"plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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+tSnPjXhZ1xwwQW5KrfklGxP1p5wl1Y3VfOvDwBAwWpoaNCzzz4rSbrllltUU1Ojz372s0Pb4/G4/P6xv+pbWlrU0tIy4Wc88cQTuSl2FiUSCfl8Pq/LKN2RrFCY6RsAAMXnAx/4gD7+8Y/r/PPP1+c+9zk99dRTev3rX6+NGzfqggsu0EsvvSRJ2rFjh97+9rdLSgW0D33oQ9q6datWrVql22+/fej9ampqhvbfunWrrrrqKp111ll6z3veI+ecJOmBBx7QWWedpc2bN+tTn/rU0Ptm2rdvn97whjdo06ZN2rRp04jw9o//+I8699xztX79et1www2SpFAopDe/+c1av369Nm3apLa2thE1S9L111+vu+++W5K0YsUKff7zn9emTZt077336tvf/rZe+9rXav369fqzP/sz9fT0SJKOHDmiK6+8UuvXr9f69ev1xBNP6KabbtLXvva1off94he/qK9//evT/rMoyZGszr6YjnT2048FAMipL/9kl3Yf7Mzpe65bVKeb33HOpI5pb2/XE088IZ/Pp87OTj3++OPy+/16+OGH9bd/+7f6r//6r1OOefHFF/XYY4+pq6tLZ555pv7yL//ylOkKnnnmGe3atUuLFi3ShRdeqN/85jdqaWnRxz72Mf3qV7/SypUrde21145ZU3Nzsx566CFVVFRoz549uvbaa9Xa2qqf//zn+vGPf6zf/e53qqqq0rFjxyRJ73nPe3TDDTfoyiuvVF9fn5LJpPbv33/an7uhoUG///3vJaVOpX70ox+VJN144436zne+o09+8pP61Kc+pYsuukg/+tGPlEgkFI1GtWjRIr3rXe/SX//1XyuZTOqee+7RU089Nanf+VhKMmS1cTsdAEARe/e73z10uuzkyZN6//vfrz179sjMFIvFxjzm8ssvVzAYVDAYVHNzs44cOaIlS5aM2GfLli1D6zZs2KB9+/appqZGq1atGpra4Nprr9Wdd955yvvHYjFdf/31evbZZ+Xz+fTyyy9Lkh5++GF98IMfVFVVlSRp3rx56urq0oEDB3TllVdKSs1RlY0///M/H1p+/vnndeONN+rEiROKRqO67LLLJEmPPvqovv/970uSfD6f6uvrVV9fr4aGBj3zzDM6cuSINm7cqIaGhqw+83RKMmRxY2gAwEyY7IjTTKmurh5a/tKXvqSLL75YP/rRj7Rv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\n",
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Plotting the accuracy\n",
"\n",
"f = plt.figure(figsize=(10,10))\n",
"plt.plot(train_accuracy, label='Training accuracy')\n",
"plt.plot(test_accuracy, label='Testing accuracy')\n",
"plt.legend()\n",
"plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Prediction is: 1\n",
"Actual label is: 1\n"
]
}
],
"source": [
"img = test_dataset[31][0].resize_((1,1,28,28))\n",
"label = test_dataset[31][1]\n",
"\n",
"model.eval()\n",
"\n",
"if CUDA:\n",
" model = model.cuda()\n",
" img = img.cuda()\n",
" \n",
"output = model(img)\n",
"_, predicted = torch.max(output, dim=1)\n",
"print('Prediction is: {}'.format(predicted.item()))\n",
"print('Actual label is: {}'.format(label))\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fd77db5b250>"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"random_img = test_dataset[31][0].numpy() * stddev_gray + mean_gray\n",
"plt.imshow(random_img.reshape(28,28), cmap='gray')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}