Manual implementation of handwritten digit recognition + implementation based on Pytorch

Manual implementation using datasets in sklearn:

import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
import warnings
import random
warnings.filterwarnings('ignore')
random.seed(1)

digits=load_digits()

X=digits.data
Y=digits.target

VV=np.random.random((64,100))*2-1
WW=np.random.random((100,10))*2-1

X_train,X_test,Y_train,Y_test=train_test_split(X,Y)
print(Y_train)
#one hot
labels_train=LabelBinarizer().fit_transform(Y_train)

def sigmod(x):
    return 1/(1+np.exp(-x))

def derivation_sigmod(x):
    return np.exp(-x)/((1+np.exp(-x))*(1+np.exp(-x)))

def predict(X,Y,V,W):
    res=0
    for flag in range(X.shape[0]):#SGG
        x=X[flag]
        y=Y[flag]
        x=np.atleast_2d(x)
        x=x.reshape(64,1)

        h_in=np.matmul(V.T,x)
        h_out=sigmod(h_in)
        y_in=np.matmul(W.T,h_out)
        y_out=sigmod(y_in)

        if np.argmax(y_out)==y:
            res+=1
    return res/X.shape[0]

def train(X,Y,V,W,steps=10000,learning_rate=0.1):
    for n in range(steps+1):#SGD
        flag=np.random.randint(X.shape[0])
        x=X[flag]
        y=Y[flag]
        x=np.atleast_2d(x)
        x=x.reshape(64,1)
        y=y.reshape(10,1)

        h_in=np.matmul(V.T,x)
        h_out=sigmod(h_in)
        y_in=np.matmul(W.T,h_out)
        y_out=sigmod(y_in)

        delta_y_in=derivation_sigmod(y_in)*(y_out-y)
        delta_h_in=derivation_sigmod(h_in)*np.matmul(W,delta_y_in)

        delta_W=np.matmul(h_out,delta_y_in.T)
        delta_V=np.matmul(x,delta_h_in.T)

        W-=learning_rate*delta_W
        V-=learning_rate*delta_V

        #if(n<3):
        #    print(W[:3][:3])

        # train 1000 times to get a prediction
        if n%1000==0:
            acc=predict(X_test,Y_test,V,W)
            print('steps:',n,'accuracy:',acc)

train(X_train,labels_train,VV,WW,30000)

Using the dataset in Pytorch to implement based on Pytorch:

(First normal feedforward neural network, followed by convolutional neural network in annotations)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import optim
from torch.utils.data import DataLoader
from torch.utils.data import TensorDataset
import torchvision
import warnings
warnings.filterwarnings('ignore')

LR=0.01
EPOCH=100
BATCH_SIZE=50

class Mnist_CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1)
        self.conv3 = nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1)
    def forward(self, xb):
        xb = xb.view(-1, 1, 28, 28)
        xb = F.relu(self.conv1(xb))
        xb = F.relu(self.conv2(xb))
        xb = F.relu(self.conv3(xb))
        xb = F.avg_pool2d(xb, 4)
        return xb.view(-1, xb.size(1))

def get_data():
    train_data = torchvision.datasets.MNIST(root='./mnist/', train=True, transform=torchvision.transforms.ToTensor())
    test_data = torchvision.datasets.MNIST(root='./mnist/', train=False, transform=torchvision.transforms.ToTensor())
    x_train, y_train, x_test, y_test = map(
        torch.tensor, (train_data.train_data/255.0, train_data.train_labels, test_data.test_data/255.0, test_data.test_labels)
    )
    train_ds = TensorDataset(x_train, y_train)
    train_dl = DataLoader(train_ds, batch_size=BATCH_SIZE)
    test_ds = TensorDataset(x_test, y_test)
    test_dl = DataLoader(test_ds, batch_size=BATCH_SIZE)
    return train_dl, test_dl

def get_model():
    model = Mnist_CNN()
    optimizer = optim.SGD(model.parameters(),lr=LR)
    loss_func = F.cross_entropy
    return model, optimizer, loss_func

def loss_batch(model, loss_func, xb, yb, optimizer=None):
    pred = model(xb)
    loss = loss_func(pred, yb)
    pred = torch.argmax(pred, dim=1)
    match = sum(pred == yb)
    if optimizer is not None:
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
    return loss.item(), match, len(xb)

def fit(epochs, model, optimizer, loss_func, train_dl, test_dl):
    for epoch in range(epochs):
        model.train()
        for xb, yb in train_dl:
            loss_batch(model, loss_func, xb, yb, optimizer)

        model.eval()
        with torch.no_grad():
            losses, match, nums = zip(
                *[loss_batch(model, loss_func, xb, yb) for xb, yb in test_dl]
            )
        val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)
        accuracy = np.sum(match) / np.sum(nums)
        print(epoch, val_loss, accuracy)

train_dl, test_dl = get_data()
model,optimizer,loss_func = get_model()
fit(EPOCH,model,optimizer,loss_func,train_dl,test_dl)

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325419290&siteId=291194637