+

Identifying handwritten digits with logistic regression in PyTorch

We will now see how to classify handwritten numbers from the MNIST dataset using logistic regression in PyTorch. First, you will need to install PyTorch in your Python environment. The easiest way to do this is — use the pip or conda tool. Visit pytorch.org and install the version of your Python interpreter and package manager you would like to use.

With PyTorch installed, let`s now see to the code. Write the three lines below to import the library functions and objects you want.

import torch

import torch.nn as nn

import torchvision.datasets as dsets

import torchvision.transforms as transforms

from torch.autograd import Variable

Here the torch.nn module contains the code needed for the model, and torchvision.datasets contains the MNIST dataset. It contains a set of handwritten numbers that we will be using here. The torchvision.transforms module contains various methods for converting objects to others. Here we will use it to convert images to PyTorch tensors. In addition, the torch.autograd module contains, among other things, a Variable class that we will use to define our tensors.

Next, we will load and load the dataset into memory.

# MNIST Dataset (images and tags)

train_dataset = dsets.MNIST (root = `. / data`

train = True

transform = transforms.ToTensor ( ),

download = True )

 

test_dataset = dsets.MNIST (root = `. / data`

train = False

transform = transforms.ToTensor ())

 
# Dataset loader (input pipeline)

train_loader = torch.utils.data.DataLoader (dataset = train_dataset, 

  batch_size = batch_size, 

shuffle = True )

 

test_loader = torch.utils.data.DataLoader (dataset = test_dataset , 

batch_size = batch_size, 

shuffle = False )

We will now define our hyperparameters.

# Hyperparameters

input_size = 784

num_classes = 10

num_epochs = 5

batch_size = 100

learning_rate = 0.001

In our dataset, the image size is 28 * 28. So our input size is 784. In addition, there are 10 digits in it, and therefore we can have 10 different outputs. So we set num_classes to 10. We will also train five times over the entire dataset. Finally, we will train in small batches of 100 images to prevent the program from crashing due to memory overflow.

After that, we will define our model as shown below. Here we initialize our model as a subclass of torch.nn.Module, and then define a forward pass. In the code we write, the softmax is internally calculated during each forward pass, and therefore we do not need to specify it inside the forward () function.

class LogisticRegression (nn.Module):

def __ init __ ( self , input_size, num_classes):

super (LogisticRegression, self ) .__ init __ ()

self . linear = nn.Linear (input_size, num_classes)

  

  def forward ( self , x):

out = self .linear (x)

return out

Having defined our class, now we create an object for it .

model = LogisticRegression (input_size, num_classes )

Next, we set up our loss function and optimizer. Here we will use cross entropy loss, and for the optimizer we will use a stochastic gradient descent algorithm with a learning rate of 0.001 as defined in the hyperparameter above.

criterion = nn.CrossEntropyLoss ()

optimizer = torch.optim.SGD (model.parameters (), lr = learning_rate)

Now we start learning. Here we will be doing the following tasks:

  1. Reset all gradients to 0.
  2. Make a straight pass.
  3. Calculate loss.
  4. Backpropagate.
  5. Update all weights.

# Train the model

for epoch in range (num_epochs):

for i, (images, labels) in enumerate (train_loader):

images = Variable (images.view ( - 1 , 28 * 28 ))

labels = Variable (labels)

 

# Forward + Backward + Optimize

optimizer.zero_grad ()

outputs = model (images)

loss = criterion (outputs, labels)

loss.backward ()

  optimizer.step ()

  

if (i + 1 ) % 100 = = 0 :

print ( `Epoch: [% d /% d], Step: [% d /% d], Loss:% .4f`

% (epoch + 1 , num_epochs, i + 1 ,

  len (train_dataset) / / batch_size, loss.data [ 0 ]))

Finally, we will test the model using the following code.

# Check the model

correct = 0

total = 0

for images, labels in test_loader:

images = Variable (images.view ( - 1 , 28 * 28 ))

outputs = model (images)

  _, predicted = torch. max (outputs.data, 1 )

total + = labels.size ( 0 )

corre ct + = (predicted = = labels). sum ()

 

print ( `Accuracy of the model on the 10000 test images:% d %%` % (

  100 * correct / total))

Assuming you followed all the steps correctly, you will get an accuracy of 82%, which is far from the current modern model that uses a special type of neural network architecture. For reference, you can find the complete code for this article below:

import torch

import torch.nn as nn

import torchvision.datasets as dsets

import torchvision.transforms as transforms

from torch.autograd import Variable

  

 
# MNIST Dataset (images and tags)

train_dataset = dsets.MNIST (root = `. / data` ,

  train = True ,

  transform = transforms.ToTensor (),

download = True )

 

test_dataset = dsets.MNIST (root = `. / data` ,

train = False ,

transform = transforms.ToTensor ())

 
# Dataset loader (input pipeline)

train_loader = torch.utils.data.DataLoader (dataset = train_dataset,

batch_size = batch_size,

  shuffle = True )

  

test_loader = torch .utils.data.DataLoader (dataset = test_dataset,

batch_size = batch_size,

shuffle = False )

  
# Hyperparameters

input_size = 784

num_classes = 10

num_epochs = 5

batch_size = 100

learning_rate = 0.001

 
# Model

class LogisticRegression (nn.Module):

  def __ init __ ( self , input_size, num_classes):

super (LogisticRegression, self ) .__ init __ ()

self . linear = nn.Linear (input_size, num_classes)

 

def forward ( self , x):

out = self . linear (x)

return out

 

  

model = LogisticRegression (input_size, num_classes)

 
Loss and Optimizer
# Softmax is calculated internally.
# Set parameters for updating.

criterion = nn.CrossEntropyLoss ()

optimizer = torch.optim.SGD (model.parameters (), lr = learning_rate)

 
# Train the model

for epoch in range (num_epochs):

for i, (images, labels) in enumerate (train_loader):

  images = Variable (images.view ( - 1 , 28 * 28 ))

labels = Variable (labels)

 

# Forward + Backward + Optimize

  optimizer.zero_grad ()

outputs = model (images)

loss = criterion (outputs, labels)

loss.backward ()

  optimizer.step ()

 

  if (i + 1 ) % 100 = = 0 :

print ( `Epoch: [% d /% d], Step: [% d /% d], Loss:% .4f`

  % (epoch + 1 , num_epochs, i + 1 ,

len (train_dataset) / / batch_size, loss.data [ 0 ]))

 
# Check the model

correct = 0

total = 0

for images, labels in test_loader:

images = Variable (images.view ( - 1 , 28 * 28 ))

  outputs = model (images)

_, predicted = torch . max (outputs.data, 1 )

total + = labels.size ( 0 )

correct + = (predicted = = labels). sum ()

  

print ( ` Accuracy of the model on the 10000 test images:% d %% ` % (

100 * correct / total))

Recommendations :

Get Solution for free from DataCamp guru