PyTorch 识别 MNIST 手写数字

深度学习识别手写数字,用PyTorch实现,对象是有标号的手写数字数据集MNIST(Modified National Institute of Standards and Technology)

一般download MNIST数据集用以下command:

mnist = fetch_mldata('MNIST original')

但是因为在本机上总是出现timeout的错误,更改为以下command:

from sklearn.datasets import fetch_openml

mnist = fetch_openml('mnist_784')

PyTorch处理的流程:

  1. data预处理
  2. 创建DataLoader
  3. Nerual Network
  4. Loss Function
  5. Learning and Predicting
1. Data预处理

获取图片和label

X=mnist.data / 255   #normalization
y=mnist.target

试着显示一张图片和标号:

import matplotlib.pyplot as plt
%matplotlib inline

plt.imshow(X[0].reshape(28, 28), cmap='gray')
print("label is {}".format(y[0]))

pic and label

2. 创建DataLoader

把MNIST data转化为PyTorch可以用的DataLoader形式
处理流程如下:

  1. split training data and testing data
  2. convert numpy data to Tensor
  3. create Dataset
  4. convert Dataset to DataLoader
import torch
from torch.utils.data import TensorDataset, DataLoader
from sklearn.model_selection import train_test_split
import numpy as np
#1. split training data and testing data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1/7, random_state=0) #random seed is 0

#2. Convert data to torch.Tensor
X_train = torch.Tensor(X_train)  #Tensor default to FloatTensor
X_test = torch.Tensor(X_test)
y_train= np.vstack(y_object_train[:].astype(np.int64)) #convert np.object to int64, or cannot convert to Tensor format #Test
y_train = torch.LongTensor(y_train)
y_test= np.vstack(y_test[:].astype(np.int64)) #convert np.object to int64, or cannot convert to Tensor format #Test
y_test = torch.LongTensor(y_test)

#3. Create Dataset by data and label pair
ds_train = TensorDataset(X_train, y_train)
ds_test = TensorDataset(X_test, y_test)

#4. decide the batch size and create DataLoader
loader_train = DataLoader(ds_train, batch_size=64, shuffle=True) #default is ascending order from 0~9
loader_test = DataLoader(ds_test, batch_size=64, shuffle=False)
3. Create Nerual Network

用简单的fc和relu layer进行测试:

from torch import nn

model = nn.Sequential()
model.add_module('fc1', nn.Linear(28*28*1, 100))  #linear transformation, y = xA^T+b
model.add_module('relu1', nn.ReLU())
model.add_module('fc2', nn.Linear(100, 100))
model.add_module('relu2', nn.ReLU())
model.add_module('fc3', nn.Linear(100, 10))

print(model)

output:

Sequential(
  (fc1): Linear(in_features=784, out_features=100, bias=True)
  (relu1): ReLU()
  (fc2): Linear(in_features=100, out_features=100, bias=True)
  (relu2): ReLU()
  (fc3): Linear(in_features=100, out_features=10, bias=True)
)
4. Decide the loss function

optimizer选择Adam算法,loss function选cross entropy loss

from torch import optim

loss_fn = nn.CrossEntropyLoss() #-[ylogy^ + (1-y)log(1-y^)]  #loss function
optimizer = optim.Adam(model.parameters(), lr=0.01)   #learning rate=0.01

training函数:

# for 1 epoch
def train(epoch):
    model.train()
    
    for data, targets in loader_train:   #mini batch from loader
        optimizer.zero_grad()   #set gradient to 0
        outputs = model(data)  #input: data
        loss = loss_fn(outputs, targets.squeeze()) #add squeeze() function #Test
        
        loss.backward()  #backward propagation
        optimizer.step()  #update the parameters
        
    print ("epoch {} : terminated".format(epoch))

testing函数:

# for 1 epoch
def test():
    model.eval()
    correct = 0
    
    with torch.no_grad():  #do not calculate the gradient to save memory
        for data, targets in loader_test:
            outputs = model(data)
            
            _, predicted = torch.max(outputs.data, 1)
            correct += predicted.eq(targets.data.view_as(predicted)).sum()
            
    data_num = len(loader_test.dataset)
    print('\n testing correctness: {}/{} ({:.0f}%)\n'.format(correct, data_num, 100. * correct / data_num))

运行一次test(),可以看到未经训练的网络准确率在10%左右

testing correctness: 1082/10000 (10%)

训练3次后predict,可以看到准确率提高到了95%

for epoch in range(3):
    train(epoch)
    
test()

output:

epoch 0 : terminated
epoch 1 : terminated
epoch 2 : terminated

 testing correctness: 9543/10000 (95%)

测试一张图片,index可以自己定义

index = 2019

model.eval()  #predict
data = X_test[index]
output = model(data)
_, predicted = torch.max(output.data, 0)
print(predicted)

print("predicted result: {}".format(predicted))

X_test_show = (X_test[index]).numpy()
plt.imshow(X_test_show.reshape(28, 28), cmap='gray')
print("correct label is: {}".format(y_test[index]))

在这里插入图片描述

另一种Define by Run的模型写法:

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    
    def __init__(self, n_in, n_mid, n_out):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(n_in, n_mid)
        self.fc2 = nn.Linear(n_mid, n_mid)
        self.fc3 = nn.Linear(n_mid, n_out)
        
    def forward(self, x):
        h1 = F.relu(self, fc1(x))
        h2 = F.relu(self.fc2(x))
        output = self.fc3(h2)
        return output
    
model = Net(n_in=28*28*1, n_mid=100, n_out=10)
print(model)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值