PyTorch 教程-卷积神经网络模型测试
在上一节中,我们实现了一个神经网络或创建了一个模型,用于对手写数字进行分类。现在,我们通过从网络中获取一张图像来测试我们的模型。我们使用了以下图像:
http://calstormbasketball.com/wp-content/uploads/2018/08/5020657994731_01c.jpeg
当您将此链接粘贴到浏览器中时,您将看到数字5的图像如下:
在看到这个图像后,我们会意识到这是数字5。现在,我们将尝试让我们的网络对其进行预测。
我们有以下步骤来预测数字图像:
步骤1:
在第一步中,我们将执行一个GET请求来检索图像数据。为了进行GET请求,我们需要导入请求:
import requests
现在,我们设置一个变量URL并将链接分配为字符串。
url=' http://calstormbasketball.com/wp-content/uploads/2018/08/5020657994731_01c.jpeg '
步骤2:
在下一步中,我们设置一个变量响应,其值将从请求的get()方法中获取。get()方法将包含两个参数,即URL和stream,stream将等于True。
response=requests.get(url,stream=True)
步骤3:
我们将使用响应的原始内容来获取图像。为此,我们首先必须从PIL(Python图像库)导入Image。
from PIL import Image
我们使用图像的open()方法,并将响应的原始内容作为参数传递。从这个方法返回的值将分配给一个名为img的变量。
img=Image.open(response.raw)
现在,我们绘制图像以确保一切正常工作。
plt.imshow(img)
plt.show()
当我们运行它时,它将生成一个错误,因为PIL。我们必须首先安装pillow才能运行此代码。我们必须在anaconda命令提示符上运行conda install -c anaconda pillow命令来安装pillow。
运行代码后,将得到预期的输出。
步骤4:
我们需要确保图像与神经网络训练学习的内容相对应。我们的图像是1000 1000像素,因此我们需要将其转换为28 28的灰度图像,就像训练数据中的图像一样。在我们训练的图像数据集中,图像具有黑色背景和白色前景,在上面的图像中,有一个白色背景和黑色前景。现在,我们的第一个任务是对这个图像进行预处理。
我们将使用PIL.ImageOps的invert()方法,并将我们的图像作为参数传递。此方法将反转我们图像的颜色。
img=PIL.ImageOps.invert(img)
这个图像是以三个通道的像素强度值为RGB格式,这会导致许多问题。为此,我们必须将此图像转换为二进制的黑白图像,方法如下:
img=img.convert('1')
我们将以与我们转换所有其他训练图像相同的方式转换此图像。我们必须在我们的转换链合成中添加一个resize参数,因为我们要将图像转换为28*28像素。
transform1=transforms.Compose([transforms.Resize((28,28)),transforms.ToTensor(),transforms.Normalize((0.5,),(0.5,))])
img=transform1(img)
现在,我们的图像以张量形式存在,所以我们必须将它转换成numpy数组。在绘制图像之前,我们必须导入PIL.ImageOps,然后绘制图像。
import PIL.ImageOps
plt.imshow(im_convert(img))
步骤5:
现在,我们将把这个图像输入到我们的神经网络中进行预测。我们将图像添加到设备中,并确保输入是四维权重的四维输入。我们将对图像进行展开并将其分配给一个新变量image。
image=img.to(device)
image=image[0].unsqueeze().unsqueeze(0)
这将返回一个在指定位置零插入的新张量,其尺寸为一。
output=model(image)
_,pred=torch.max(output,1)
print(pred.item())
这将给出我们期望的预测。
步骤6:
在下一步中,我们封装我们的验证加载器。这将创建一个对象,允许我们一次访问可变验证加载器中的一个元素。我们通过在dataiter上调用next()函数一次访问一个元素。next()函数将获取我们验证数据的第一个批次,并将该验证数据拆分为图像和标签。
dataiter=iter(validation_loader)
images,labels=dataiter.next()
不需要重塑图像。我们将图像和标签添加到我们的设备中,我们还需要所有图像和预测的输出。
images_=images.to(device)
labels=labels.to(device)
output=model(images_)
_,preds=torch.max(output,1)
步骤7:
现在,我们将批次中的图像与相应的标签一起绘制出来。这将使用plt的figure函数完成,并将fig size设置为整数元组25*4,它将指定图的宽度和高度。
fig=plt.figure(figsize=(25,4))
现在,我们从我们的批次中绘制20个MNIST图像。我们使用add_subplot()方法向当前图添加一个子图,并将2、10和idx作为该函数的参数。这里,2是行数,10是列数,idx是索引。
ax=fig.add_subplot(2,10,idx+1)
现在,我们将显示我们的图像,使用im_show()函数,并为每个图像绘制一个标题。
plt.imshow(im_convert(images[idx]))
ax.set_title("{}({})".format(str(preds[idx].item()),str(labels[idx].item())),
color=("green" if preds[idx]==labels[idx] else "red"))
最后调用plt.show(),它将给出一个错误。这个错误将是im_convert()函数的错误,即无法将CUDA张量转换为numpy。因此,我们必须使用tensor.cpu()。
image=tensor.cpu().clone().detach().numpy()
现在,我们将重新调用plt.show(),它将给出我们期望的输出。
完整代码:
import torch
import matplotlib.pyplot as plt
import numpy as np
import torch.nn.functional as func
import PIL.ImageOps
from torch import nn
from torchvision import datasets,transforms
import requests
from PIL import Image
transform1=transforms.Compose([transforms.Resize((28,28)),transforms.ToTensor(),transforms.Normalize((0.5,),(0.5,))])
training_dataset=datasets.MNIST(root='./data',train=True,download=True,transform=transform1)
validation_dataset=datasets.MNIST(root='./data',train=False,download=True,transform=transform1)
training_loader=torch.utils.data.DataLoader(dataset=training_dataset,batch_size=100,shuffle=True)
validation_loader=torch.utils.data.DataLoader(dataset=validation_dataset,batch_size=100,shuffle=False)
def im_convert(tensor):
image=tensor.cpu().clone().detach().numpy()
image=image.transpose(1,2,0)
print(image.shape)
image=image*(np.array((0.5,0.5,0.5))+np.array((0.5,0.5,0.5)))
image=image.clip(0,1)
return image
dataiter=iter(training_loader)
images,labels=dataiter.next()
fig=plt.figure(figsize=(25,4))
for idx in np.arange(20):
ax=fig.add_subplot(2,10,idx+1)
plt.imshow(im_convert(images[idx]))
ax.set_title([labels[idx].item()])class classification1(nn.Module):
def __init__(self,input_layer,hidden_layer1,hidden_layer2,output_layer):
super().__init__()
self.linear1=nn.Linear(input_layer,hidden_layer1)
self.linear2=nn.Linear(hidden_layer1,hidden_layer2)
self.linear3=nn.Linear(hidden_layer2,output_layer)
def forward(self,x):
x=func.relu(self.linear1(x))
x=func.relu(self.linear2(x))
x=self.linear3(x)
return x
model=classification1(784,125,65,10)
criteron=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.0001)
epochs=12
loss_history=[]
correct_history=[]
val_loss_history=[]
val_correct_history=[]
for e in range(epochs):
loss=0.0
correct=0.0
val_loss=0.0
val_correct=0.0
for input,labels in training_loader:
inputs=input.view(input.shape[0],-1)
outputs=model(inputs)
loss1=criteron(outputs,labels)
optimizer.zero_grad()
loss1.backward()
optimizer.step()
_,preds=torch.max(outputs,1)
loss+=loss1.item()
correct+=torch.sum(preds==labels.data)
else:
with torch.no_grad():
for val_input,val_labels in validation_loader:
val_inputs=val_input.view(val_input.shape[0],-1)
val_outputs=model(val_inputs)
val_loss1=criteron(val_outputs,val_labels)
_,val_preds=torch.max(val_outputs,1)
val_loss+=val_loss1.item()
val_correct+=torch.sum(val_preds==val_labels.data)
epoch_loss=loss/len(training_loader.dataset)
epoch_acc=correct.float()/len(training_dataset)
loss_history.append(epoch_loss)
correct_history.append(epoch_acc)
val_epoch_loss=val_loss/len(validation_loader.dataset)
val_epoch_acc=val_correct.float()/len(validation_dataset)
val_loss_history.append(val_epoch_loss)
val_correct_history.append(val_epoch_acc)
print('training_loss:{:.4f},{:.4f}'.format(epoch_loss,epoch_acc.item()))
print('validation_loss:{:.4f},{:.4f}'.format(val_epoch_loss,val_epoch_acc.item()))
url='http://calstormbasketball.com/wp-content/uploads/2018/08/5020657994731_01c.jpeg'
response=requests.get(url,stream=True)
img=Image.open(response.raw)
img=PIL.ImageOps.invert(img)
img=img.convert('1')
img=transform1(img)
plt.imshow(im_convert(img))
images=img.to(device)
images=images[0].unsqueeze(0).unsqueeze(0)
output=model(images)
_,pred=torch.max(output,1)
print(pred.item())
dataiter=iter(validation_loader)
images,labels=dataiter.next()
images_=images.to(device)
labels=labels.to(device)
output=model(images_)
_,preds=torch.max(output,1)
fig=plt.figure(figsize=(25,4))
for idx in np.arange(20):
ax=fig.add_subplot(2,10,idx+1,xticks=[],yticks=[])
plt.imshow(im_convert(images[idx]))
ax.set_title("{}({})".format(str(preds[idx].item()),str(labels[idx].item())),color=("green" if preds[idx]==labels[idx] else "red"))
plt.show()
所以,很明显,与深度神经网络相比,卷积神经网络以最佳方式对图像进行分类。这就是我们更喜欢使用卷积神经网络而不是深度神经网络的原因。