文章目录
- 前言
- 1. 什么是机器识别手写数字?
- 2. MNIST数据集是什么?
- 3. 显示MNIST数据集
- 4. 名词解释
* - 4. 1 图像
- 4. 2 卷积层
- 4. 3 池化层
- 4. 4 线性层
- 4. 5 激活函数
- 4. 6 [损失函数](https://blog.csdn.net/bestrivern/article/details/101755218)
- 4.7 正则化
- 4.8 log_softmax函数
- 4.9 反向传播
- 5. 网络结构
- 6. 完整的模型训练套路
* - 6.1 加载库
- 6.2 定义超参数
- 6.3 构建pipeline对图像做处理
- 6.4 下载、加载数据
- 6.5 构建网络模型
- 6.6 定义优化器
- 6.7 定义训练方法
- 6.8 定义测试方法
- 6.9 模型训练与保存
- 6.10 用TransBoard绘制损失与准确
- 6.11 输出结果
- 7 模型验证
- 总结
前言
本文介绍机器学习中的一个实例-手写体识别。
- 什么是机器识别手写数字?
输入:数字图片
处理:网络模型
输出:识别结果
即输入一张手写体0-9的数字,计算机自动识别数字并给出结果。
-
MNIST数据集是什么?
-
此数据集为手写体数字。
- 该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。
- 数据集包含了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
获得的如下界面,从而展示了图像
- 名词解释
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 反向传播
- 网络结构
; 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/
转载文章受原作者版权保护。转载请注明原作者出处!