点击上方“AI算法与图像处理”,选择加"星标"或“置顶”
重磅干货,第一时间送达
文 |AI_study
原标题:CNN Image Prediction With PyTorch - Forward Propagation Explained
用一个神经网络解释前向传播
到目前为止,我们已经完成了模型的构建,从技术上讲,我们可以从这里直接进入训练过程。但是,让我们努力更好地了解我们的网络是如何开箱即用的,接下来,我们只需对网络有了更深入的了解,将为了解训练过程做更好的准备。
第一步是了解正向传播。
什么是前向传播
正向传播 是将输入张量转换为输出张量的过程。神经网络的核心是将输入张量映射到输出张量的功能,而正向传播只是将传递输入到网络并从网络接收输出的过程的特殊名称。
如我们所见,神经网络对张量形式的数据进行操作。前向传播的概念用于指示输入张量数据是通过网络 在 正向 上传输的。
对于我们的网络,这意味着简单地将输入张量传递到网络并接收输出张量。为此,我们将样本数据传递给网络的forward() 方法。
这就是为什么forward() 方法具有正向名称的原因,forward() 的执行是正向传播的过程。
如果您正在关注本系列,那么到现在为止我们知道,我们不会直接调用forward() 方法,而是会调用网络实例。有关更多详细信息,请参见此内容。
https://deeplizard.com/learn/video/rcc86nXKwkw
forward 这个词很直截了当。
但是,“传播”一词是指通过某种媒介移动或传播。在神经网络的情况下,数据通过网络的各个层传播。
也有反向传播(backpropagation)的概念,这使得术语“正向传播”适合作为第一步。在训练过程中,反向传播发生在正向传播之后。
在我们的例子中,从实际的角度来看,正向传播是将一个输入图像张量传递给我们在上一节中实现的forward()方法的过程。这个输出是网络的预测。
在关于数据集和数据加载器的情节中,我们了解了如何从训练集中访问单个样本图像张量,更重要的是,如何从数据加载器访问一批图像张量。现在我们已经定义了网络并实现了forward() 方法,将图像传递到我们的网络以获得预测。
网络预测:正向传播
在此之前,我们将关闭PyTorch的求导计算功能。当我们的张量流过网络时,这将阻止PyTorch自动构建计算图。
计算图通过追踪每个运算来跟踪网络的映射。该图在训练过程中用于计算损失函数对网络权值的导数(梯度)。
因为我们还没有对网络进行训练,所以我们不打算更新权值,所以我们不需要梯度计算。当训练开始的时候,我们会把它打开。
当计算发生时,跟踪计算的过程实时发生。还记得在本系列开始时,我们说过PyTorch使用动态计算图。我们现在把它关掉。
关闭它并不是必须的,但是关闭这个特性确实会减少内存消耗,因为图并不存储在内存中。这段代码将关闭该特性。
torch.set_grad_enabled(False)
<torch.autograd.grad_mode.set_grad_enabled at 0x17c4867dcc0>
向网络传递一张图像
让我们继续通过创建我们的网络类的一个实例:
network = Network()
接下来,我们将从我们的训练集中获取一个样本,将图像和标签解压,并验证图像的形状:
> sample = next(iter(train_set))
> image, label = sample
> image.shape
torch.Size([1, 28, 28]) # 输出
图像张量的形状表明我们有一个单通道图像,它的高度是28,宽度是28。酷,这就是我们所期待的。
现在,在简单地把这个张量传递给我们的网络之前,还有第二步我们必须预先准备。当我们向网络传递一个张量时,网络需要一批张量,所以即使我们想要传递一张图像,我们仍然需要一批张量。
这不是问题。我们可以创建一个包含单个图像的batch。所有这些都将被打包成一个单一的四维张量,它反映了以下维度。
(batch_size, in_channels, height, width)
这个网络的需求来自于forward()方法在nn.Conv2d卷积层类期望其tenor具有4维。这是一般的规范的,因为大多数神经网络实现处理的是批量输入样本,而不是单个样本。
要将我们的单个样本图像张量放入一个大小为1的批处理中,我们只需要解unsqueeze()张量来添加额外的维度。在之前的几节里我们已经学过了。
# Inserts an additional dimension that represents a batch of size 1
image.unsqueeze(0).shape
torch.Size([1, 1, 28, 28])
利用这一点,我们现在可以将 unsqueezed 的图像传递到我们的网络并得到网络的预测。
> pred = network(image.unsqueeze(0)) # image shape needs to be (batch_size × in_channels × H × W)
> pred
tensor([[0.0991, 0.0916, 0.0907, 0.0949, 0.1013, 0.0922, 0.0990, 0.1130, 0.1107, 0.1074]])
> pred.shape
torch.Size([1, 10])
> label
9
> pred.argmax(dim=1)
tensor([7])
我们做到了!我们使用前向法从网络中得到预测。该网络返回了一个预测张量,其中包含了十类服装中每一类的预测值。
预测张量的形状是1×10。这告诉我们,第一个轴的长度是1,而第二个轴的长度是10。对此的解释是,在我们的batch和10个预测类中有一个图像。
(batch size, number of prediction classes)
对于batch 中的每个输入和每个预测类,我们都有一个预测值。如果我们想要这些值是概率,我们可以使用nn.functional包中的softmax()函数。
> F.softmax(pred, dim=1)
tensor([[0.1096, 0.1018, 0.0867, 0.0936, 0.1102, 0.0929, 0.1083, 0.0998, 0.0943, 0.1030]])
> F.softmax(pred, dim=1).sum()
tensor(1.)
我们的训练集中第一个图像的标签是9,使用argmax()函数,我们可以看到我们的预测张量的最大值出现在由索引 7 表示的类中。
预测: Sneaker(7)
实际:Ankle boot(9)
请记住,每个预测类都由一个对应的索引表示。
这种情况下的预测是不正确的,这和我们想的一样,因为网络中的权值是随机生成的。
网络权重是随机生成的
关于这些结果,我们需要指出几件重要的事情。大多数概率接近10%,这是有意义的,因为我们的网络是猜测的,我们有10个预测类来自一个平衡的数据集。
数据集:https://deeplizard.com/learn/video/mUueSPmcOBc
随机生成的权值的另一个含义是,每次我们创建网络的新实例时,网络中的权值将是不同的。这意味着,如果我们创建不同的网络,我们得到的预测将是不同的。记住这一点。你的预测将与我们在这里看到的不同。
> net1 = Network()
> net2 = Network()
> net1(image.unsqueeze(0))
tensor([[ 0.0855, 0.1123, -0.0290, -0.1411, -0.1293, -0.0688, 0.0149, 0.1410, -0.0936, -0.1157]])
> net2(image.unsqueeze(0))
tensor([[-0.0408, -0.0696, -0.1022, -0.0316, -0.0986, -0.0123, 0.0463, 0.0248, 0.0157, -0.1251]])
下一节:使用Data Loader 传递一个batch
我们现在应该很好地理解了什么是正向传播,以及如何在PyTorch中将单个图像张量传递给卷积神经网络。在下一篇文章中,我们将看到如何使用数据加载器向网络传递批处理。到时候见!
文章中内容都是经过仔细研究的,本人水平有限,翻译无法做到完美,但是真的是费了很大功夫,希望小伙伴能动动你性感的小手,分享朋友圈或点个“在看”,支持一下我 ^_^
英文原文链接是:
https://deeplizard.com/learn/video/6vweQjouLEE
加群交流
欢迎小伙伴加群交流,目前已有交流群的方向包括:AI学习交流群,目标检测,秋招互助,资料下载等等;加群可扫描并回复感兴趣方向即可(注明:地区+学校/企业+研究方向+昵称)
谢谢你看到这里! ????