text_plain_output_1.png
from torch.utils.data import Dataset, DataLoader

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd

import seaborn as sns

import torch

import torch.nn as nn

import torch.optim as optim

BATCH_SIZE = 16
LEARNING_RATE = 0.001
N_EPOCHS = 20
LAYER1_SIZE = 256
LAYER2_SIZE = 256
DROPOUT_RATE = 0.3

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device

train_data = pd.read_csv('../input/digit-recognizer/train.csv')
test_data = pd.read_csv('../input/digit-recognizer/test.csv') / 255

# Figure size
plt.figure(figsize=(8,8))

# Subplot
for i in range(9):
    img = np.asarray(train_data.iloc[i+180,1:].values.reshape((28,28))/255)
    ax=plt.subplot(3, 3, i+1)
    ax.grid(False)
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    ax.title.set_text(f'{train_data.iloc[i+18,0]}')
    plt.imshow(img, cmap='gray')
    
plt.show()

class MNIST(Dataset):
    def __init__(self, subset='train'):
        super().__init__()
        self.subset = subset
        if self.subset == 'train':
            self.X = torch.from_numpy(X_train.values.astype(np.float32))
            self.y = torch.from_numpy(y_train.values)
        elif self.subset == 'valid':
            self.X = torch.from_numpy(X_valid.values.astype(np.float32))
            self.y = torch.from_numpy(y_valid.values)
        elif self.subset == 'test':
            self.X = torch.from_numpy(test_data.values.astype(np.float32))
        else:
            raise Exception('subset must be train, valid or test')
    def __getitem__(self, index):
        if self.subset == 'test':
            return self.X[index]
        else:
            return (self.X[index], self.y[index])
    def __len__(self):
        return self.X.shape[0]
train_dataset = MNIST(subset='train')
valid_dataset = MNIST(subset='valid')
test_dataset = MNIST(subset='test')

train_loader = DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True)
valid_loader = DataLoader(dataset=valid_dataset, batch_size=BATCH_SIZE, shuffle=False)
test_loader = DataLoader(dataset=test_dataset, batch_size=BATCH_SIZE, shuffle=False)

class NeuralNet(nn.Module):
    def __init__(self, layer1_size=LAYER1_SIZE, layer2_size=LAYER2_SIZE, dropout_rate=DROPOUT_RATE):
        super().__init__()
        self.lin1 = nn.Linear(in_features=784, out_features=layer1_size)
        self.lin2 = nn.Linear(in_features=layer1_size, out_features=layer2_size)
        self.lin3 = nn.Linear(in_features=layer2_size, out_features=10)
        self.relu = nn.ReLU()
        self.drop = nn.Dropout(p=dropout_rate)
    def forward(self, x):
        out = self.lin1(x)
        out = self.relu(out)
        out = self.drop(out)
        out = self.lin2(out)
        out = self.relu(out)
        out = self.drop(out)
        out = self.lin3(out)
        return out
model = NeuralNet().to(device)

loss = nn.CrossEntropyLoss()
optimiser = optim.Adam(params=model.parameters(), lr=LEARNING_RATE)

loss_hist = []
val_loss_hist = []
for epoch in range(N_EPOCHS):
    loss_acc = 0
    val_loss_acc = 0
    train_count = 0
    valid_count = 0
    for imgs, labels in train_loader:
        imgs = imgs.to(device)
        labels = labels.to(device)
        preds = model(imgs)
        L = loss(preds, labels)
        L.backward()
        optimiser.step()
        optimiser.zero_grad()
        loss_acc += L.detach().item()
        train_count += 1
    with torch.no_grad():
        for val_imgs, val_labels in valid_loader:
            val_imgs = val_imgs.to(device)
            val_labels = val_labels.to(device)
            val_preds = model(val_imgs)
            val_L = loss(val_preds, val_labels)
            val_loss_acc += val_L.item()
            valid_count += 1
    loss_hist.append(loss_acc / train_count)
    val_loss_hist.append(val_loss_acc / valid_count)

plt.figure(figsize=(10, 5))
plt.plot(loss_hist, c='C0', label='loss')
plt.plot(val_loss_hist, c='C1', label='val_loss')
plt.title('Cross entropy loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()