我使用nn定义训练好了一个手写数字识别模型,但不知道怎么使用,怎么样才能将手机拍摄的白底黑字数字进行识别,并输出预测值
训练好的 PyTorch MNIST 模型可以通过以下步骤使用:
在训练模型的计算机上安装 PyTorch。
使用 torch.load() 函数加载训练好的模型。
定义一个函数来处理输入图像,将其转换为模型能够处理的格式。
使用模型对输入图像进行预测,并使用 torch.argmax() 函数获取预测的类别。
下面是一个示例代码,该代码假设您已将训练好的模型保存在文件 "mnist_model.pth" 中:
import torch
import torchvision
# 加载训练好的模型
model = torch.load("mnist_model.pth")
# 定义一个函数来处理输入图像
def preprocess_image(image_path):
# 使用 torchvision 加载和转换图像
image = torchvision.transforms.ToTensor()(image_path)
# 增加批次维度
image = image.unsqueeze(0)
return image
# 加载要识别的图像
image = Image.open("image.jpg")
# 将图像转换为模型能够处理的格式
input_image = preprocess_image(image)
# 使用模型进行预测
output = model(input_image)
# 获取预测的类别
prediction = torch.argmax(output)
print("Predicted class: ", prediction)
在上面的代码中,您需要使用 Python 的 PIL 库或类似的库来加载要识别的图像。然后,使用 preprocess_image() 函数将其转换
望采纳!!点击该回答右侧的“采纳”按钮即可采纳!!
手机拍的照片先要上传到你运行模型预测的环境
如果你使用了nn库来训练手写数字识别模型,那么可以使用以下步骤来进行数字识别:
将要识别的图像转换成模型训练时使用的同样的图像大小和格式。这通常需要将图像转换为灰度图像并将其缩放到合适的大小。
使用nn库的nn.Sequential()函数创建一个新的神经网络模型,并将训练好的模型参数加载到模型中。
使用nn库的nn.Module.eval()函数将模型设置为评估模式,以便可以对模型进行预测。
使用nn库的nn.Module.forward()函数将图像作为输入传递给模型,并获取预测结果。
从预测结果中获取最高的概率值对应的数字,并输出该数字作为预测值。
以下是使用Python语言编写的示例代码:
import torch
import torch.nn as nn
import numpy as np
# 加载训练好的模型参数
model = nn.Sequential(...)
model.load_state_dict(torch.load("model.pth"))
# 将模型设置为评估模式
model.eval()
# 读取要识别的图像并转换为模型输入的格式
image = ...
image = image.astype(np.float32) / 255.0
image = torch.from_numpy(image)
image = image.unsqueeze(0)
# 进行预测获取预测结果
output = model(image)
获取最高概率值对应的数字
_, predicted = output.max(dim=1)
输出预测结果
print("Predicted:", predicted.item())
1、准备数据:将手机拍摄的白底黑字数字图片转化为模型能够处理的输入数据。这通常需要将图像转化为灰度图,并将其调整为模型期望的尺寸。
2、导入模型:使用 Python 的 import 语句导入模型。
3、预测:使用模型的 predict 方法将准备好的数据作为输入,并使用模型对数据进行预测。
4、输出预测值:将模型的预测结果输出即可。
以下是一个示例代码,该代码假设已经准备好了图像数据 image_data 并将其转化为了模型能够处理的输入数据:
import nn
# 导入模型
model = nn.load_model("model.h5")
# 使用模型进行预测
prediction = model.predict(image_data)
# 输出预测值
print(prediction)
仅供参考,望采纳。
import torch
from torch import nn
from torch import optim
import torch.nn.functional as F
import torchvision
train_batch_size = 64
test_batch_size = 1000
img_size = 28
def get_dataloader(train=True):
assert isinstance(train,bool) # "train 必须是bool类型"
#准备数据集,其中0.1307,0.3081为MNIST数据的均值和标准差,这样操作能够对其进行标准化
#因为MNIST只有一个通道(黑白图片),所以元组中只有一个值
dataset = torchvision.datasets.MNIST('/data', train=train, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize((0.1307,), (0.3081,)),]))
#准备数据迭代器
batch_size = train_batch_size if train else test_batch_size
dataloader = torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True)
# 关于dataloader.dataset的长度:训练时为60000,而测试时为10000
return dataloader
class MnistNet(nn.Module):
def __init__(self):
super(MnistNet,self).__init__()
self.fc1 = nn.Linear(28*28*1,28)
self.fc2 = nn.Linear(28,10)
def forward(self,x):
x = x.view(-1,28*28*1)
x = self.fc1(x) #[batch_size,28]
x = F.relu(x) #[batch_size,28]
x = self.fc2(x) #[batch_size,10]
# return x
# 计算softmax和取对数,为计算损失做准备,dim=-1表示取对数的方向(x.shape:[batch_size, 10],对应上面第二种计算损失的方法
return F.log_softmax(x,dim=-1)
mnist_net = MnistNet()
optimizer = optim.Adam(mnist_net.parameters(),lr= 0.001)
# criterion = nn.NLLLoss()
# criterion = nn.CrossEntropyLoss()
train_loss_list = []
# 暂时不知道有啥用
train_count_list = []
def train(epoch):
mode = True
mnist_net.train(mode=mode)
train_dataloader = get_dataloader(train=mode)
# 数据的总数:60000
print(len(train_dataloader.dataset))
# 每批64,那么一共有60000/64,向上取整一共有938
print(len(train_dataloader))
for idx,(data,target) in enumerate(train_dataloader):
optimizer.zero_grad()
output = mnist_net(data)
loss = F.nll_loss(output,target) #对数似然损失
loss.backward()
optimizer.step()
# epoch:训练的批次
# len(data):由train_batch_size决定,这里是64,因此每次输出都是10*64=640
# len(train_dataloader.dataset):60000
# idx / len(train_dataloader):train_dataloader是938(如上),而idx每整10取一次,因此差不多每输出一次就增加百分之一的进度
if idx % 10 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, idx * len(data), len(train_dataloader.dataset),
100. * idx / len(train_dataloader), loss.item()))
train_loss_list.append(loss.item())
# 10 * 64 + (5 - 1)*938
train_count_list.append(idx*train_batch_size+(epoch-1)*len(train_dataloader))
torch.save(mnist_net.state_dict(),"model/mnist_net.pkl")
torch.save(optimizer.state_dict(), 'results/mnist_optimizer.pkl')
def test():
# 测试集的总数据量是10000,而不是60000,而test_batch_size的数值决定了for循环执行的次数,而不决定取出数据量的大小
test_loss = 0
correct = 0
# 评估模式
mnist_net.eval()
# 10000/1000=10
test_dataloader = get_dataloader(train=False)
with torch.no_grad():
for data, target in test_dataloader:
# data.shape:torch.Size([1000, 1, 28, 28])
# target.shape:torch.Size([1000])
output = mnist_net(data)
# reduction默认值是mean,这里取的是sum,相当于每一次都对一个循环内的数据做累加操作(也就是1000个target的损失),所以所有的循环结束后,一共累加了10000个结果的损失,所以后续需要/=len(test_dataloader.dataset)来计算平均损失。这里取默认值mean也是可以的,只是后续除的时候应该除以的是len(test_dataloader)的大小,也就是10000/1000=10。因为用mean的话已经取了一个批次的平均值了。
test_loss += F.nll_loss(output, target, reduction='sum').item()
# 也可以是:pred = output.max(dim = -1)[-1] 两个-1都跟1的意思相同
pred = output.data.max(1, keepdim=True)[1] #获取最大值的位置,形状是[batch_size,1]
# 将预测的目标值和实际的目标值转换为同个形状,方便进行比较,eq的结果如果相同,那么则是True,否则为False,最后用sum方法统计正确的个数,将其累加到correct中
correct += pred.eq(target.data.view_as(pred)).sum()
test_loss /= len(test_dataloader.dataset)
print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(
test_loss, correct, len(test_dataloader.dataset),
100. * correct / len(test_dataloader.dataset)))
if __name__ == '__main__':
test() # 没有训练过的准确率,与后面的形成对比
for i in range(5): #模型训练5轮
train(i)
test()
提供参考实例【用PyTorch实现MNIST手写数字识别(最新,非常详细)】,链接:https://huaweicloud.csdn.net/63a571adb878a54545947794.html?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~activity-13-120935828-blog-115693919.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~activity-13-120935828-blog-115693919.pc_relevant_recovery_v2&utm_relevant_index=19#_304?login=from_csdn
【推荐理由:该实例系统全面的讲解了如何实现MNIST手写数字识别过程,步骤清晰明了,注解详细】
使用训练好的 PyTorch MNIST 模型来识别单张手机拍摄图片的步骤如下:
1、准备输入图片。将手机拍摄的图片保存到电脑上,然后使用图像处理库(如 Pillow 或 OpenCV)将图片转换为 PyTorch 可以处理的格式。通常,这意味着将图像转换为三维张量,其中第一维表示图像批次(batch)大小,第二维和第三维分别表示图像的高度和宽度。
2、加载模型。使用 PyTorch 的 torch.load 函数加载训练好的 MNIST 模型。这将返回一个 torch.nn.Module 子类的实例,该实例封装了模型的所有权重和偏差项。
3、进行推理。将准备好的输入图像传递给加载的模型,然后使用模型的 forward 方法进行推理。这将返回一个包含模型输出的张量。
4、解码输出。模型的输出是一个包含每个类别概率的张量,因此需要找到最高概率的类别。可以使用 PyTorch 的 torch.argmax 函数来实现这一点。
以下是一个使用 PyTorch 实现上述步骤的示例代码:
import torch
import torchvision
import PIL
# 加载模型
model = torch.load("mnist_model.pt")
# 准备输入图像
image = PIL.Image.open("image.jpg") # 使用 Pillow 库打开图像
image = torchvision.transforms.ToTensor()(image) # 将图像转换为张量
image = image.unsqueeze(0) # 增加批次维度
# 进行推理
output = model(image)
# 解码输出
prediction = output.argmax().item()
print(f"模型预测的数字是:{prediction}")
在这段代码中,使用了 Pillow 库打开图像并将其转换为张量,然后使用 PyTorch 的 unsqueeze 函数在第一维(批次维度)上增加了一个维度。最后,使用 PyTorch 的 argmax 函数找到了模型输出中最高概率的类别。
望采纳。
采用Adam优化算法+交叉熵损失函数,并用visdom进行可视化操作。
########################### training & testing #################################
optimizer = torch.optim.Adam(myLeNet.parameters(), lr = LR) # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss() # 交叉熵 loss the target label is not one-hotted
if VISDOM:
vis = visdom.Visdom(env=u'MNIST for leNet')
vis.line(X=torch.Tensor([1]),Y=torch.Tensor([0]),win='trainAcc', \
opts=dict(title = 'acc rate(%) for train data', ytickmin = 0, ytickmax = 100))
vis.line(X=torch.Tensor([1]),Y=torch.Tensor([0]),win='trainLoss', \
opts=dict(title = 'train loss', ytickmin = 0, ytickmax = 2.5))
vis.line(X=torch.Tensor([1]),Y=torch.Tensor([0]),win='testAcc', \
opts=dict(title = 'acc rate(%) for test data', ytickmin = 0, ytickmax = 100))
vis.line(X=torch.Tensor([1]),Y=torch.Tensor([0]),win='testLoss', \
opts=dict(title = 'test loss', ytickmin = 0, ytickmax = 2.5))
mini-batch梯度下降法,并对每个epoch记录并更新loss值和准确度。
for epoch in range(EPOCH):
for step, (x, y) in enumerate(train_loader):
# gives batch data, normalize x when iterate train_loader
if torch.cuda.is_available():
batch_x = Variable(x).cuda()
batch_y = Variable(y).cuda()
else:
batch_x = Variable(x)
batch_y = Variable(y)
output, last_layer = myLeNet(batch_x) # LeNet output
loss = loss_func(output, batch_y) # cross entropy loss
optimizer.zero_grad() # clear gradients for this training step
loss.backward() # backpropagation, compute gradients
optimizer.step() # apply gradients
_, correct_label = torch.max(output, 1) # 输出预测概率的label
# print('label', correct_label)
correct_num = (correct_label == batch_y).sum()
trainAcc = correct_num.item() / float(batch_y.size(0))
print('train: Epoch [%d/%d], Iter [%2d/%d] Loss: %.4f, Acc: %.4f' % \
(epoch + 1, EPOCH, step + 1, len(MNISTtrainData) // BATCH_SIZE + 1, \
loss.item(), trainAcc))
if VISDOM:
vis.line(X=torch.Tensor([epoch + 1]), \
Y=torch.Tensor([trainAcc * 100]), win='trainAcc', update='append')
vis.line(X=torch.Tensor([epoch + 1]),\
Y=torch.Tensor([loss]), win='trainLoss', update='append')
testAcc = 0
for _, (x, y) in enumerate(test_loader):
# gives batch data, normalize x when iterate train_loader
if torch.cuda.is_available():
batch_x = Variable(x).cuda()
batch_y = Variable(y).cuda()
else:
batch_x = Variable(x)
batch_y = Variable(y)
output, last_layer = myLeNet(batch_x) # LeNet output
loss = loss_func(output, batch_y) # cross entropy loss
_, correct_label = torch.max(output, 1) # 输出预测概率最大的值和标签
# print('label', correct_label)
correct_num = (correct_label == batch_y).sum()
testAcc += correct_num.item()
testAcc = testAcc / float(MNISTtestData.test_labels.size(0))
print('----------------test: Epoch [%d/%d] Acc: %.4f' % (epoch + 1, EPOCH, testAcc))
if VISDOM:
vis.line(X=torch.Tensor([epoch + 1]), \
Y=torch.Tensor([testAcc * 100]), win='testAcc', update='append')
vis.line(X=torch.Tensor([epoch + 1]),\
Y=torch.Tensor([loss]), win='testLoss', update='append')
torch.save(myLeNet, './ModelBackup/MNIST_lenet_model_%d_%f.pkl'%(epoch, testAcc))
最后保存模型(建议每隔几个epoch保存备用):
torch.save(myLeNet, './ModelBackup/MNIST_lenet_model_%d_%f.pkl'%(epoch, testAcc))
这样,你就有一个专门处理手写数字的简单模型了。
可以试一下:
import torch
import torchvision
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
import time
import matplotlib.pyplot as plt
import random
from numpy import argmax
#Basic Params-----------------------------
epoch = 1
learning_rate = 0.01
batch_size_train = 64
batch_size_test = 1000
gpu = torch.cuda.is_available()
momentum = 0.5
#Define Model----------------------------
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Flatten(),
nn.Linear(in_features=3136, out_features=128),
nn.Linear(in_features=128, out_features=10),
)
def forward(self, x):
return self.model(x)
if gpu:
net = Net().cuda()
else:
net = Net()
#Define Loss and Optimizer----------------
if gpu:
loss_fn = nn.CrossEntropyLoss().cuda()
else:
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
#Define Tensorboard-------------------
writer = SummaryWriter(log_dir='logs/{}'.format(time.strftime('%Y%m%d-%H%M%S')))
#Train---------------------------------
total_train_step = 0
def train(epoch):
global total_train_step
total_train_step = 0
for data in train_loader:
imgs,targets = data
if gpu:
imgs,targets = imgs.cuda(),targets.cuda()
optimizer.zero_grad()
outputs = net(imgs)
loss = loss_fn(outputs,targets)
loss.backward()
optimizer.step()
if total_train_step % 200 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, total_train_step, train_data_size,
100. * total_train_step / train_data_size, loss.item()))
writer.add_scalar('loss', loss.item(), total_train_step)
total_train_step += 1
#Test---------------------------------
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
imgs,targets = data
if gpu:
imgs,targets = imgs.cuda(),targets.cuda()
outputs = net(imgs)
_,predicted = torch.max(outputs.data,1)
total += targets.size(0)
correct += (predicted == targets).sum().item()
print('Test Accuracy: {}/{} ({:.0f}%)'.format(correct, total, 100.*correct/total))
return correct/total
#Run----------------------------------
for i in range(1,epoch+1):
print("-----------------Epoch: {}-----------------".format(i))
train(i)
test()
writer.add_scalar('test_accuracy', test(), total_train_step)
#save model
torch.save(net,'model/mnist_model.pth')
print('Saved model')
writer.close()