<jupyter_start><jupyter_text>[![Open In Studio Lab](https://studiolab.sagemaker.aws/studiolab.svg)](https://studiolab.sagemaker.aws/import/github/aws/studio-lab-examples/blob/main/computer-vision/kmnist/cv-kminst.ipynb) Train an image classification model with PyTorch  BackgroundVision is responsible for 80-85 percent of our world perception. As human beings, we trivially perform classification daily on whatever data we encounter. Our brains process this visual information by firing neurons that learn through repetition.Computers can emulate this biological process using a neural network! One of the first applications of this technique was image classification.Image classification (or Image recognition) is a subdomain of computer vision. These algorithms examine an image and map predefined tags or categories to it. It learns those mappings through a model training process.   Pytorch[PyTorch](https://pytorch.org/) is an open-source machine learning library based on the Torch library, used for computer vision and natural language processing applications, primarily developed by [Facebook's AI Research lab (FAIR)](https://ai.facebook.com/research/). It is free and open-source software released under the [Modified BSD license](https://github.com/pytorch/pytorch/blob/master/LICENSE). KMINST datasetIn this notebook, we will use the KMINST dataset.https://pytorch.org/vision/stable/datasets.htmltorchvision-datasets     Steps in this notebookThe main steps are:1. Install packages1. Load dataset, what's train and test loader1. Print out one image from the KMINST dataset, with which library, 1. Initiate the neural network (NN) model1. Train a model with config1. Test a model 1. Print a figure with train and test lossFor more information on neural networks and machine learning, see [AWS Machine Learning University](https://aws.amazon.com/machine-learning/mlu/). ![KMIST dataset picture](https://raw.githubusercontent.com/rois-codh/kmnist/master/images/kmnist_examples.png) - Install Python packages for later use    - [**torch**](https://pytorch.org/) is a package that provides two high-level capabilities: Tensor computation (like NumPy) using CPU/GPU acceleration, and a strong development community.    - [**torchvision**](https://pytorch.org/vision/stable/index.html) is a package consists of popular datasets, model architectures, and common image transforms for computer vision.    - [**torchsummary**](https://pypi.org/project/torch-summary/) is a package provides "pretty print" functionality for models.    - [**matplotlib**](https://matplotlib.org/) is a package for visualizing information    Before running this notebook, you need to install the required Python packages by opening a terminal window (click on File/New/Terminal). Next, navigate to the folder containing the `env_cv.yml` file. Then execute the following commands.- `conda env create -f env_cv.yml`- `conda activate cv`After that you need to switch the notebook kernel to **.conda-cv:Python** by clicking **Kernel/Change Kernel**..<jupyter_code># Uncomment these lines if you do not want to use the env_cv.yml file
#%pip install torch 
#%pip install torchvision
#%pip install torchsummary
#%pip install matplotlib
#%pip install ipywidgets
import torch
import torchvision
if torch.cuda.is_available():  
    device = "cuda:0" 
else:  
    device = "cpu" 
import os
results_dir='results'
if not os.path.isdir(results_dir):
    !mkdir -p {results_dir}
## Create dataloader, in PyTorch, we feed the trainer data with use of dataloader
## We create dataloader with dataset from torchvision, 
## and we dont have to download it seperately, all automatically done

# Define batch size, batch size is how much data you feed for training in one iteration
batch_size_train = 64 # We use a small batch size here for training
batch_size_test = 1024 #

# define how image transformed
image_transform = torchvision.transforms.Compose([
                               torchvision.transforms.ToTensor(),
                               torchvision.transforms.Normalize(
                                 (0.1307,), (0.3081,))
                             ])
#image datasets
train_dataset = torchvision.datasets.KMNIST('dataset/', 
                                           train=True, 
                                           download=True,
                                           transform=image_transform)
test_dataset = torchvision.datasets.KMNIST('dataset/', 
                                          train=False, 
                                          download=True,
                                          transform=image_transform)
#data loaders
train_loader = torch.utils.data.DataLoader(train_dataset,
                                           batch_size=batch_size_train, 
                                           shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset,
                                          batch_size=batch_size_test, 
                                          shuffle=True)
# import library

import matplotlib.pyplot as plt
# We can check the dataloader
_, (example_datas, labels) = next(enumerate(test_loader))
sample = example_datas[0][0]
# show the data
plt.imshow(sample, cmap='gray', interpolation='none')
print("Label: "+ str(labels[0]))
## Now we can start to build our CNN model
## We first import the pytorch nn module and optimizer
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
## Then define the model class
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #input channel 1, output channel 10
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5, stride=1)
        #input channel 10, output channel 20
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5, stride=1)
        #dropout layer
        self.conv2_drop = nn.Dropout2d()
        #fully connected layer
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)
    def forward(self, x):
        x = self.conv1(x)
        x = F.max_pool2d(x, 2)
        x = F.relu(x)
        x = self.conv2(x)
        x = self.conv2_drop(x)
        x = F.max_pool2d(x, 2)
        x = F.relu(x)
        x = x.view(-1, 320)
        x = self.fc1(x)
        x = F.relu(x)
        x = F.dropout(x)
        x = self.fc2(x)
        return F.log_softmax(x)
## create model and optimizer
learning_rate = 0.01
momentum = 0.5
model = CNN().to(device) #using cpu here
optimizer = optim.SGD(model.parameters(), lr=learning_rate,
                      momentum=momentum)

from torchsummary import summary
summary(model, (1, 28, 28))
n_epochs = 3
log_interval = 100
train_losses = []
train_counter = []
test_losses = []
test_counter = [i*len(train_loader.dataset) for i in range(n_epochs + 1)]
def train(epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        if torch.cuda.is_available():  
            output = model(data.cuda())
            loss = F.nll_loss(output, target.cuda())
        else:
            output = model(data)
            loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
        epoch, batch_idx * len(data), len(train_loader.dataset),
        100. * batch_idx / len(train_loader), loss.item()))
    train_losses.append(loss.item())
    train_counter.append(
        (batch_idx*64) + ((epoch-1)*len(train_loader.dataset)))
    torch.save(model.state_dict(), './results/model.pth')
    torch.save(optimizer.state_dict(), './results/optimizer.pth')
def test():
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            if torch.cuda.is_available(): 
                output = model(data.cuda())
                test_loss += F.nll_loss(output, target.cuda(), size_average=False).item()
                pred = output.data.max(1, keepdim=True)[1]
                correct += pred.eq(target.cuda().data.view_as(pred)).sum()
            else:
                output = model(data)
                test_loss += F.nll_loss(output, target, size_average=False).item()
                pred = output.data.max(1, keepdim=True)[1]
                correct += pred.eq(target.data.view_as(pred)).sum()                
    test_loss /= len(test_loader.dataset)
    test_losses.append(test_loss)
    print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))
test()
for epoch in range(1, n_epochs + 1):
    train(epoch)
    test()
fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.scatter(test_counter, test_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')
#fig<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10704787234042554, 'fraction_numerical': 0.012854609929078014, 'mean_word_length': 2.8306451612903225, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 25, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '419759', 'license': 'Apache-2.0', 'n_tokens_mistral': 2676, 'n_tokens_neox': 2560, 'n_words': 782, 'path': 'computer-vision/kmnist/cv-kminst.ipynb', 'repo_name': 'dr-natetorious/studio-lab-examples', 'size': '9024'}