Skip to content

Instantly share code, notes, and snippets.

@danielpcox
Created August 25, 2018 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielpcox/4ebd65a36bf706a6ab295168d09fc68f to your computer and use it in GitHub Desktop.
Save danielpcox/4ebd65a36bf706a6ab295168d09fc68f to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import torch\n",
"import torchvision\n",
"import torchvision.transforms as transforms"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Just a bit of image adjustment. Not substantially important.\n",
"transform = transforms.Compose(\n",
" [transforms.ToTensor(),\n",
" transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Files already downloaded and verified\n",
"Files already downloaded and verified\n"
]
}
],
"source": [
"# This is just a convenient way to get the CIFAR10 dataset. Not substantially important.\n",
"# You could download your own images and load them into numpy arrays with Pillow to get the same result\n",
"trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)\n",
"testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# This is just a convenient way to get random minibatches of the images. Not substantially important.\n",
"trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)\n",
"testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# the CIFAR10 data has ten classes\n",
"classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ship dog plane ship\n",
"tensor([[[-0.9373, -0.9373, -0.9451, ..., -0.9451, -0.9059, -0.8902],\n",
" [-0.9373, -0.9294, -0.9451, ..., -0.9294, -0.9294, -0.9216],\n",
" [-0.8588, -0.8745, -0.8824, ..., -0.7804, -0.7647, -0.7176],\n",
" ...,\n",
" [-0.7098, -0.7725, -0.7725, ..., -0.5216, -0.5216, -0.5373],\n",
" [-0.7020, -0.7333, -0.7647, ..., -0.5373, -0.5373, -0.5373],\n",
" [-0.7098, -0.7098, -0.7490, ..., -0.5843, -0.5843, -0.5765]],\n",
"\n",
" [[-0.9216, -0.9137, -0.9216, ..., -0.9294, -0.8902, -0.8745],\n",
" [-0.9216, -0.9059, -0.9216, ..., -0.9216, -0.9216, -0.9137],\n",
" [-0.7882, -0.7961, -0.8039, ..., -0.7176, -0.7098, -0.6627],\n",
" ...,\n",
" [-0.5765, -0.6627, -0.6706, ..., -0.3882, -0.3882, -0.4039],\n",
" [-0.5686, -0.6235, -0.6627, ..., -0.4039, -0.4039, -0.4039],\n",
" [-0.5686, -0.5922, -0.6392, ..., -0.4510, -0.4510, -0.4353]],\n",
"\n",
" [[-0.8980, -0.9216, -0.9451, ..., -0.9294, -0.9059, -0.9216],\n",
" [-0.9137, -0.9294, -0.9608, ..., -0.9451, -0.9451, -0.9451],\n",
" [-0.7569, -0.7961, -0.8196, ..., -0.7804, -0.7569, -0.6863],\n",
" ...,\n",
" [-0.6549, -0.7882, -0.8353, ..., -0.5137, -0.5137, -0.5294],\n",
" [-0.6549, -0.7490, -0.8196, ..., -0.5294, -0.5294, -0.5294],\n",
" [-0.6627, -0.7255, -0.8039, ..., -0.5765, -0.5765, -0.5608]]])\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Process Process-2:\n",
"Process Process-1:\n",
"Traceback (most recent call last):\n",
"Traceback (most recent call last):\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
" self.run()\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
" self.run()\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
" self._target(*self._args, **self._kwargs)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
" self._target(*self._args, **self._kwargs)\n",
" File \"/usr/local/anaconda3/lib/python3.6/site-packages/torch/utils/data/dataloader.py\", line 52, in _worker_loop\n",
" r = index_queue.get()\n",
" File \"/usr/local/anaconda3/lib/python3.6/site-packages/torch/utils/data/dataloader.py\", line 52, in _worker_loop\n",
" r = index_queue.get()\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/queues.py\", line 335, in get\n",
" res = self._reader.recv_bytes()\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/queues.py\", line 335, in get\n",
" res = self._reader.recv_bytes()\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 216, in recv_bytes\n",
" buf = self._recv_bytes(maxlength)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 216, in recv_bytes\n",
" buf = self._recv_bytes(maxlength)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 407, in _recv_bytes\n",
" buf = self._recv(4)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 407, in _recv_bytes\n",
" buf = self._recv(4)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 379, in _recv\n",
" chunk = read(handle, remaining)\n",
" File \"/usr/local/anaconda3/lib/python3.6/multiprocessing/connection.py\", line 379, in _recv\n",
" chunk = read(handle, remaining)\n",
"KeyboardInterrupt\n",
"KeyboardInterrupt\n"
]
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"# Let's have a look at these images we supposedly just downloaded.\n",
"\n",
"# function to show an image, given that we've got pytorch-shaped,\n",
"# normalized images, and matplotlib needs something different\n",
"def imshow(img):\n",
" img = img / 2 + 0.5 # unnormalize\n",
" npimg = img.numpy() # convert to numpy ndarray\n",
" reordered = np.transpose(npimg, (1, 2, 0)) # PyTorch uses CHW, matplotlib expects HWC\n",
" plt.imshow(reordered)\n",
"\n",
"\n",
"# get some random training images\n",
"dataiter = iter(trainloader)\n",
"images, labels = dataiter.next() # get yourself a minibatch of four images\n",
"\n",
"# show those images\n",
"grid = torchvision.utils.make_grid(images) # put a minibatch of images into a single image for easier viewing\n",
"imshow(grid) # show it\n",
"# print labels\n",
"print(' '.join('%5s' % classes[labels[j]] for j in range(4)))\n",
"print(images[0])"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"import torch.nn as nn\n",
"import torch.nn.functional as F\n",
"\n",
"\n",
"# holy macaroni, we're defining a neural net\n",
"class Net(nn.Module):\n",
" def __init__(self):\n",
" super(Net, self).__init__()\n",
" self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5) # stride=1 by default\n",
" self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n",
" self.conv2 = nn.Conv2d(6, 16, 5)\n",
" self.fc1 = nn.Linear(in_features=16 * 5 * 5, out_features=120)\n",
" self.fc2 = nn.Linear(120, 84)\n",
" self.fc3 = nn.Linear(84, 10) # ten output neurons, one for each of our ten classes\n",
"\n",
" def forward(self, x):\n",
" x = self.pool(F.relu(self.conv1(x))) # convolutional layer -> relu non-linearity -> max pooling ->\n",
" x = self.pool(F.relu(self.conv2(x))) # convolutional layer -> relu non-linearity -> max pooling ->\n",
" x = x.view(-1, 16 * 5 * 5) # reshape the output of the convolutional layers to fit ->\n",
" x = F.relu(self.fc1(x)) # fully-connected layer -> relu ->\n",
" x = F.relu(self.fc2(x)) # fully-connected layer -> relu ->\n",
" x = self.fc3(x) # fully-connected layer ->\n",
" return x # output!\n",
"\n",
"\n",
"net = Net()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import torch.optim as optim\n",
"\n",
"# This is going to do \"stochastic gradient descent\" for us to get good weights in our neural network.\n",
"# We pass it the neural net's parameters to be adjusted according to the gradients we'll accumulate by\n",
"# running images forward through the neural net.\n",
"optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2000] loss: 0.090\n",
"[1, 4000] loss: 0.088\n",
"[1, 6000] loss: 0.086\n",
"[1, 8000] loss: 0.085\n",
"[1, 10000] loss: 0.083\n",
"[1, 12000] loss: 0.082\n",
"[2, 2000] loss: 0.081\n",
"[2, 4000] loss: 0.080\n",
"[2, 6000] loss: 0.079\n",
"[2, 8000] loss: 0.079\n",
"[2, 10000] loss: 0.078\n",
"[2, 12000] loss: 0.077\n",
"[3, 2000] loss: 0.076\n",
"[3, 4000] loss: 0.076\n",
"[3, 6000] loss: 0.075\n",
"[3, 8000] loss: 0.075\n",
"[3, 10000] loss: 0.074\n",
"[3, 12000] loss: 0.074\n",
"[4, 2000] loss: 0.074\n",
"[4, 4000] loss: 0.073\n",
"[4, 6000] loss: 0.073\n",
"[4, 8000] loss: 0.072\n",
"[4, 10000] loss: 0.072\n",
"[4, 12000] loss: 0.072\n",
"[5, 2000] loss: 0.071\n",
"[5, 4000] loss: 0.071\n",
"[5, 6000] loss: 0.071\n",
"[5, 8000] loss: 0.069\n",
"[5, 10000] loss: 0.069\n",
"[5, 12000] loss: 0.069\n",
"[6, 2000] loss: 0.069\n",
"[6, 4000] loss: 0.068\n",
"[6, 6000] loss: 0.068\n",
"[6, 8000] loss: 0.067\n",
"[6, 10000] loss: 0.068\n",
"[6, 12000] loss: 0.067\n",
"[7, 2000] loss: 0.067\n",
"[7, 4000] loss: 0.066\n",
"[7, 6000] loss: 0.067\n",
"[7, 8000] loss: 0.066\n",
"[7, 10000] loss: 0.066\n",
"[7, 12000] loss: 0.065\n",
"[8, 2000] loss: 0.065\n",
"[8, 4000] loss: 0.065\n",
"[8, 6000] loss: 0.065\n",
"[8, 8000] loss: 0.064\n",
"[8, 10000] loss: 0.064\n",
"[8, 12000] loss: 0.063\n",
"[9, 2000] loss: 0.063\n",
"[9, 4000] loss: 0.062\n",
"[9, 6000] loss: 0.063\n",
"[9, 8000] loss: 0.063\n",
"[9, 10000] loss: 0.063\n",
"[9, 12000] loss: 0.062\n",
"[10, 2000] loss: 0.062\n",
"[10, 4000] loss: 0.062\n",
"[10, 6000] loss: 0.062\n",
"[10, 8000] loss: 0.061\n",
"[10, 10000] loss: 0.061\n",
"[10, 12000] loss: 0.060\n",
"Finished Training\n"
]
}
],
"source": [
"for epoch in range(10): # loop over the dataset multiple times\n",
"\n",
" running_loss = 0.0\n",
" for i, data in enumerate(trainloader, 0):\n",
" # get the inputs\n",
" inputs, labels = data # grab four images and their correct labels\n",
"\n",
" # zero the parameter gradients\n",
" optimizer.zero_grad()\n",
"\n",
" ## forward + backward + optimize, rinse and repeat\n",
" \n",
" # run the inputs through the neural net to get the outputs\n",
" outputs = net(inputs)\n",
" \n",
" # The correct labels are indexes into that classes list, but we need them as one-hot vectors\n",
" onehot_labels = torch.eye(10).index([labels.data])\n",
" \n",
" loss = ((outputs-onehot_labels)**2).mean() # mean squared error loss\n",
" \n",
" # Now that we've got the current value of the loss function, tell PyTorch to go backwards\n",
" # and compute the gradients of the neural net weights.\n",
" loss.backward()\n",
" \n",
" # Finally, actually change the weights using those computed gradients.\n",
" optimizer.step()\n",
"\n",
" # print statistics\n",
" running_loss += loss.item()\n",
" if i % 2000 == 1999: # print every 2000 mini-batches\n",
" print('[%d, %5d] loss: %.3f' %\n",
" (epoch + 1, i + 1, running_loss / 2000))\n",
" running_loss = 0.0\n",
"\n",
"print('Finished Training')"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy of the network on the 10000 test images: 54 %\n"
]
}
],
"source": [
"correct = 0\n",
"total = 0\n",
"with torch.no_grad():\n",
" for data in testloader:\n",
" images, labels = data\n",
" outputs = net(images)\n",
" _, predicted = torch.max(outputs.data, 1)\n",
" total += labels.size(0)\n",
" correct += (predicted == labels).sum().item()\n",
"\n",
"print('Accuracy of the network on the 10000 test images: %d %%' % (\n",
" 100 * correct / total))"
]
},
{
"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.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment