机器学习实例—手写体识别

文章目录

前言

本文介绍机器学习中的一个实例-手写体识别。

  1. 什么是机器识别手写数字?

输入:数字图片

处理:网络模型

输出:识别结果

即输入一张手写体0-9的数字,计算机自动识别数字并给出结果。

  1. MNIST数据集是什么?

  2. 此数据集为手写体数字。

  3. 该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。
  4. 数据集包含了0-9共10类手写数字图片,每张图片都做了尺寸归一化,都是28×28大小的灰度图。

机器学习实例—手写体识别

; 3. 显示MNIST数据集

可通过加载数据集在TensorBoard界面加载数据集,代码如下:


from torchvision import datasets,transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

pipeline = transforms.Compose([
    transforms.ToTensor(),
])

train_set = datasets.MNIST("data",train=True, download=True, transform=pipeline)

train_loader = DataLoader(train_set, batch_size=1, shuffle=True)
img,target = train_set[0]

print(img.shape)
print(target)

writer = SummaryWriter("dataloader_show")
step = 0
for data in train_loader:
    imgs, targets = data
    writer.add_images("train_data", imgs, step)
    step = step + 1
writer.close()

输出:
torch.Size([1, 28, 28])
5

在pycharm的Terminal通道选择Command Prompt界面
并输入:

 tensorboard --logdir=dataloader_show --port=6007

获得的如下界面,从而展示了图像

机器学习实例—手写体识别
  1. 名词解释

4. 1 图像

图像在计算机中表示方式有多种,图像在计算机中以像素点集合的形式存在,每个像素点由三通道组成,每个通道用0-255数值表示。本文采用的MINIST数据集中的手写体只有一个通道到,像素为28×28。

4. 2 卷积层

机器学习实例—手写体识别

; 4. 3 池化层

机器学习实例—手写体识别
池化层的作用是进行特征选择,降低特征数量,从而减少参数数量。常用池化方法由最大池化和平均池化。

4. 4 线性层

本文为将三维矩阵拉平为一维度向量,也即将卷积或池化层拉平为线性层。、

4. 5 激活函数

含义:激活函数是人工神经网络的神经元上运行的函数。

作用
如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出 都是输入的线性组合,这种情况就是最原始的感知机,这无法模拟某些非线性情况。激活函数的使用给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。

如下图所示,多层感知机+激活函数得到的曲线有可能把三角和圆分开。

机器学习实例—手写体识别
常用的激活函数:Sigmoid函数、Tanh函数、ReLU函数,其中Sigmoid函数可以将较大范围内变化的输入挤压到(0,1)输出。ReLU函数表达式与图像如下图所示。

机器学习实例—手写体识别

机器学习实例—手写体识别
连接层中的激活函数:如下图所示,单神经元中为激活函数f,其使用将连接层中数据非线性化。
机器学习实例—手写体识别

含义:计算实际输出和目标之间的差距

机器学习实例—手写体识别

4.7 正则化

模型出现过拟合时,降低模型复杂度。

4.8 log_softmax函数

机器学习实例—手写体识别

; 4.9 反向传播

机器学习实例—手写体识别
  1. 网络结构

机器学习实例—手写体识别

; 6. 完整的模型训练套路

6.1 加载库

代码如下(示例):

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
from torch.utils.tensorboard import SummaryWriter
from torch.utils.data import DataLoader
import numpy as np

6.2 定义超参数

代码如下(示例):

batch_size = 64
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
epochs = 20
train_loss_record = np.zeros(epochs)
test_loss_record = np.zeros(epochs)
Accuracy_record = np.zeros(epochs)

6.3 构建pipeline对图像做处理

代码如下(示例):


pipeline = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307),(0.3081))
])

6.4 下载、加载数据

代码如下(示例):


train_set = datasets.MNIST("data",train=True, download=True, transform=pipeline)
test_set = datasets.MNIST("data",train=False, download=True, transform=pipeline)

train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_set, batch_size=batch_size, shuffle=True)

6.5 构建网络模型

代码如下(示例):

class Digit(nn.Module):
    def __init__(self):
        super(Digit, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, 5)
        self.conv2 = nn.Conv2d(10, 20, 3)
        self.linear1 = nn.Linear(20*10*10, 500)
        self.linear2 = nn.Linear(500, 10)

    def forward(self,x):
        input_size = x.size(0)
        x = self.conv1(x)
        x = F.relu(x)
        x = F.max_pool2d(x,2,2)

        x = self.conv2(x)
        x = F.relu(x)

        x = x.view(input_size,-1)

        x = self.linear1(x)

        x = F.relu(x)
        x = self.linear2(x)

        output = F.log_softmax(x,dim=1)
        return output

6.6 定义优化器

代码如下(示例):

model = Digit().to(device)
optimizer = optim.Adam(model.parameters())

6.7 定义训练方法

代码如下(示例):

def train_model(model, device, train_loader, optimizer, epoch):

    model.train( )
    for batch_index, (data,target) in enumerate(train_loader):

        data, target = data.to(device),target.to(device)

        optimizer.zero_grad()

        output = model(data)

        loss = F.cross_entropy(output,target)

        pred = output.max(1,keepdim=True)

        loss.backward()

        optimizer.step()
        if batch_index % 3000 == 0:
            print("Train Epoch:{}\t Loss:{:.6f}".format(epoch, loss.item()))
            train_loss_record[epoch]=loss.item()优化器

6.8 定义测试方法

代码如下(示例):

def test_model(model, device, test_loader):

    model.eval( )

    correct = 0.0

    test_loss = 0.0
    with torch.no_grad():
        for data, target in test_loader:

            data, target = data.to(device), target.to(device)

            output = model(data)

            test_loss += F.cross_entropy(output,target).item()

            pred = output.max(1, keepdim=True)[1]

            correct += pred.eq(target.view_as(pred)).sum().item()
        test_loss /= len(test_loader.dataset)
        print("Test---Average loss :{:.4f},Accuracy : {:.3f}\n".format(
            test_loss, 100.0 * correct / len(test_loader.dataset)))
        test_loss_record[epoch] = test_loss
        Accuracy_record[epoch] = 100.0 * correct / len(test_loader.dataset)

6.9 模型训练与保存

调用方法7、8进行模型训练,并对测试集模型进行保存
代码如下(示例):

for epoch in range(0,epochs):

    train_model(model, device, train_loader,optimizer,epoch)
    test_model(model, device, test_loader)

    torch.save(test_model, "D:\\document\\document\\major_study\\Machine-Learning\\实践项目\\model_{}.pth".format(epoch))

    print("模型已保存")

6.10 用TransBoard绘制损失与准确

代码如下(示例):

writer = SummaryWriter("curve")
for i in range(epochs):
    writer.add_scalar("train_loss", train_loss_record[i], i)
    writer.add_scalar("test_loss", test_loss_record[i], i)
    writer.add_scalar("Accuracy", Accuracy_record[i], i)
writer.close()

6.11 输出结果

程序输出20个.pth的model文件;
并在TransBoard界面生成相应的图像。
训练损失:

机器学习实例—手写体识别

准确率:

机器学习实例—手写体识别

机器学习实例—手写体识别

; 7 模型验证

既然我们通过训练获得了手写体模型的特征参数,那我们应该通过输入一张手写体图像来验证其好坏。

在相应文件夹下保存以下图片

机器学习实例—手写体识别
模型验证代码如下:

import torch
from PIL import Image
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
import torch.nn.functional as F

img_path = "D:\\document\\document\\major_study\\Machine-Learning\\实践项目\\digit.jpg"
img = Image.open(img_path)
img = img.convert('RGB')

transform = torchvision.transforms.Compose([
     torchvision.transforms.Resize((28, 28)),
     torchvision.transforms.ToTensor()
     ])
img = transform(img)
img = torch.reshape(img[0], (1, 28, 28))

class Digit(nn.Module):
    def __init__(self):
        super(Digit, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, 5)
        self.conv2 = nn.Conv2d(10, 20, 3)
        self.linear1 = nn.Linear(20*10*10, 500)
        self.linear2 = nn.Linear(500, 10)

    def forward(self,x):
        input_size = x.size(0)
        x = self.conv1(x)
        x = F.relu(x)
        x = F.max_pool2d(x,2,2)

        x = self.conv2(x)
        x = F.relu(x)

        x = x.view(input_size,-1)

        x = self.linear1(x)

        x = F.relu(x)
        x = self.linear2(x)

        output = F.log_softmax(x,dim=1)
        return output

model = torch.load("D:\\document\\document\\major_study\\Machine-Learning\\实践项目\\model_19.pth")
model.eval()
with torch.no_grad():
     output = model(img.cuda())
print(output.argmax(1))

输出:
tensor([7], device='cuda:0') #对应输入数字7

总结

以上就是今天要讲的内容,本文仅仅简单介绍了机器学习最基础的实例-手写体识别。

Original: https://blog.csdn.net/qq_40940944/article/details/127137624
Author: zaiziwamei
Title: 机器学习实例—手写体识别

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/716856/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球