Deep-Learning-with-PyTorch-2.1.5
2.1.5 运行
在新数据上运行经过训练的模型的过程在深度学习圈中称为推理(预测)。 为了进行推断,我们需要将网络置于评估模式:
# In[11]:
resnet.eval()
# Out[11]:
ResNet(
(conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3),bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True,track_running_stats=True)
(relu): ReLU(inplace)(maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1,ceil_mode=False)
(layer1): Sequential((0): Bottleneck(
...
)
)
(avgpool): AvgPool2d(kernel_size=7, stride=1, padding=0)
(fc): Linear(in_features=2048, out_features=1000, bias=True)
)
如果我们忘记这样做,则某些预训练的模型(例如批处理规范化和随机失活(dropout))将不会产生有意义的答案,这仅仅是因为它们的内部工作方式。 既然已经设置了评估模式,我们就可以进行推断了:
# In[12]:
out = resnet(batch_t)
out
# Out[12]:
tensor([[ -3.4803, -1.6618, -2.4515, -3.2662, -3.2466, -1.3611,-2.0465, -2.5112, -1.3043, -2.8900, -1.6862, -1.3055,
...
2.8674, -3.7442, 1.5085, -3.2500, -2.4894, -0.3354,0.1286, -1.1355, 3.3969, 4.4584]])
一组涉及4450万个参数的惊人操作刚刚发生,产生了1,000个得分的向量,每个ImageNet类一个。 那没花多久时间,是吧?
现在,我们需要找出得分最高的类别的标签。 这将告诉我们模型在图像中看到了什么。 如果标签与人类描述图像的方式匹配,那就太好了! 这意味着一切正常。 如果不是这样,则可能是在训练过程中出了点问题,或者图像与模型预期的差异太大,导致模型无法正确处理,或者存在其他类似问题。
要查看预测标签的列表,我们将加载一个文本文件,其中列出了标签,它们在训练过程中被呈现给网络的顺序相同,然后我们将从网络中获得最高分的索引处挑选标签。 几乎所有用于图像识别的模型都以类似于我们将要使用的形式输出。
让我们加载包含ImageNet数据集类的1,000个标签的文件:
# In[13]:
with open('../data/p1ch2/imagenet_classes.txt') as f:
labels = [line.strip() for line in f.readlines()]
在这一点上,我们需要确定与先前获得的输出张量中的最大分数相对应的索引。 我们可以使用PyTorch中的max函数来做到这一点,该函数在张量中输出最大值以及出现该最大值的索引:
# In[14]:
_, index = torch.max(out, 1)
现在,我们可以使用索引来访问标签。 在这里,index不是一个普通的Python数字,而是一个一元一维的张量(特别的,tensor([207])),因此我们需要使用index [0]获取实际的数值以用作标签列表中的索引。 我们还使用torch.nn.functional.softmax(http://mng.bz/BYnq)将输出归一化为[0,1]范围,然后除以和。 这使我们大致了解该模型对其预测的信心。 在这种情况下,该模型可以确定自己知道自己在看的是金毛寻回犬的比例为96%:
# In[15]:
percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100
labels[index[0]], percentage[index[0]].item()
# Out[15]:
('golden retriever', 96.29334259033203)
哦,谁是个好男孩?
由于该模型产生了得分,因此我们也可以找出第二好,第三好等等。 为此,我们可以使用sort函数,该函数按升序或降序对值进行排序,并在原始数组中提供排序后的值的索引:
# In[16]:
_, indices = torch.sort(out, descending=True)
[(labels[idx], percentage[idx].item()) for idx in indices[0][:5]]
# Out[16]:
[('golden retriever', 96.29334259033203),
('Labrador retriever', 2.80812406539917),
('cocker spaniel, English cocker spaniel, cocker', 0.28267428278923035),
('redbone', 0.2086310237646103),
('tennis ball', 0.11621569097042084)]
我们看到前四只是狗(redbone是一个品种;谁知道?),然后事情开始变得有趣起来。 第五个答案是“网球”,可能是因为附近有足够多的带狗的网球图片,模型实质上是在说:“我完全误解了网球的可能性为0.1%。” 这是人类和神经网络如何看待世界的根本差异的一个很好的例子,以及奇怪,细微的偏见潜入我们的数据有多么容易。
玩耍的时间到啦! 我们可以继续使用随机图像询问我们的网络,并查看其结果。 网络的成功程度在很大程度上取决于在培训集中是否很好地代表了受试者。 如果我们在训练集之外展示包含主题的图像,则很有可能网络会以非常高的置信度得出错误的答案。 进行实验并了解模型如何处理看不见的数据,这很有用。
我们刚刚运营了一个网络,该网络在2015年赢得了图像分类比赛。它学会了从狗的例子中识别出我们的狗,以及大量其他现实世界的主题。 现在,我们将从图像生成开始,了解不同的架构如何实现其他类型的任务。