用 Pytorch 理解卷积网络
如果您是一名深度学习爱好者,那么您可能已经听说过卷积神经网络,也许您甚至自己开发了一些图像分类器。像Tensorflow和PyTorch这样的现代深度学习框架使向机器学习图像变得容易,但是,仍然存在一些问题:数据如何通过神经网络的人工层传递?计算机如何从中学习?更好地解释卷积神经网络的一种方法是使用PyTorch。因此,让我们通过可视化每个图层的图像来深入研究CNN。
在开始使用卷积神经网络之前,了解神经网络的工作原理很重要。神经网络模仿人脑如何解决复杂的问题并在给定的数据集中找到模式。在过去的几年中,神经网络席卷了许多机器学习和计算机视觉算法。
图像分类是指从多波段光栅图像中提取信息类别的任务。多层感知器需要更多的时间和空间来在图片中查找信息,因为每个输入功能都需要与下一层的每个神经元相连。CNN通过使用称为本地连接的概念取代了MLP,该概念涉及将每个神经元仅连接到输入体积的本地区域。通过允许网络的不同部分专门处理高级功能(如纹理或重复图案),可以最大程度地减少参数数量。感到困惑?别担心。让我们比较一下图像如何通过多层感知器和卷积神经网络进行传递的,以更好地理解。
上面的代码段是使用称为Keras的框架实现的(暂时忽略语法)。它告诉我们在第一个隐藏层中有512个神经元,它们连接到形状为784的输入层。该隐藏层之后是一个随机失活层,该层克服了过拟合的问题。0.2表示在第一个隐藏层之后不考虑神经元的可能性为20%。再次,我们在第二个隐藏层中添加了与第一个隐藏层中相同数量的神经元(512),然后添加了另一个随机失活。最后,我们用包含10个类的输出层结束这组层。具有最高值的此类将是模型预测结果。
这是定义所有层之后的网络多层外观。这种多层感知器的一个缺点是全连接的以供网络学习,这需要更多的时间和空间。MLP仅接受向量作为输入。
卷积层不使用全连接层,而是使用稀疏连接层,也就是说,它们接受矩阵作为输入,这比MLP更具优势。输入特征连接到本地编码节点。在MLP中,每个节点负责获得对整个画面的理解。在CNN中,我们将图像分解为区域(像素的局部区域)。每个隐藏节点都必须输出层报告,在输出层,输出层将接收到的数据组合起来以找到模式。下图显示了各层如何本地连接。
与人类通过用眼睛了解图像的计算机不同,计算机使用一组介于0到255之间的像素值来了解图片。计算机查看这些像素值并理解它们。乍一看,它不知道物体或颜色,只识别像素值,这就是图像用于计算机的全部。
在分析像素值之后,计算机会慢慢开始了解图像是灰度还是彩色。它知道差异,因为灰度图像只有一个通道,因为每个像素代表一种颜色的强度。零表示黑色,255表示白色,黑色和白色的其他变化形式,即介于两者之间的灰色。另一方面,彩色图像具有三个通道-红色,绿色和蓝色。它们代表三种颜色(3D矩阵)的强度,并且当值同时变化时,它会产生大量的颜色!确定颜色属性后,计算机会识别图像中对象的曲线和轮廓。
可以使用PyTorch在卷积神经网络中探索此过程,以加载数据集并将滤波器应用于图像。下面是代码片段。(在GitHub上可找到此代码)
现在,让我们看看如何将单个图像输入神经网络。
(在GitHub上可找到此代码)
img = np.squeeze(images[7])fig = plt.figure(figsize = (12,12)) ax = fig.add_subplot(111)ax.imshow(img, cmap='gray')width, height = img.shapethresh = img.max()/2.5for x in range(width): for y in range(height): val = round(img[x][y],2) if img[x][y] !=0 else 0 ax.annotate(str(val), xy=(y,x), color='white' if img[x][y]<thresh else 'black')
这就是将数字“ 3”分解为像素的方式。从一组手写数字中,随机选择“ 3”,其中显示像素值。在这里,ToTensor()归一化实际像素值(0–255)并将其限制为0到1。为什么?因为,这使得以后的部分中的计算更加容易,无论是在解释图像还是找到图像中存在的通用模式。
我们已经知道滤波器是如何从图像中提出特征了,但是为了完成整个卷积神经网络我们需要理解用来设计CNN的各层。
-
卷积层 -
池化层 -
全连接层
使用这3层,可以构造类似这样的图像分类器:
CNN各层的作用
现在让我们一起来看看各层是用来干什么的
卷积层——卷积层(CONV)使用过滤器执行卷积操作,同时扫描输入图像的尺寸。它的超参数包括滤波器尺寸,通常设置为2x2,3x3,4x4,5x5(但并不仅限于这些尺寸),步长(S)。输出结果(O)被称为特征图或激活图,包含了输入层和滤波器计算出的所有特性。下图描述了应用卷积时产生的特征图:
卷积操作
池化层——池化层(POOL)用于特征的降采样,通常在卷积层之后应用 。常见的两种池化操作为最大池化和平均池化,分别求取特征的最大值和平均值。下图描述了池化的基本原理:
最大池化
平均池化
全连接层——全连接层(FC)作用于一个扁平的输入,其中每个输入都连接到所有的神经元 。全连接层通常用于网络的末端,将隐藏层连接到输出层,这有助于优化类分数。
全连接层
我们对CNN的函数有了更好的了解,现在让我们使用Facebook的PyTorch框架来实现它。
步骤1:加载输入图像。我们将使用Numpy和OpenCV。(在GitHub上可找到代码)
步骤2:可视化滤波器,以更好地了解我们将使用的滤波器。(在GitHub上可找到代码)
步骤3:定义卷积神经网络。该CNN具有卷积层和最大池化层,并且权重使用上述滤波器进行初始化:(在GitHub上可找到代码)
步骤4:可视化滤波器。快速浏览一下正在使用的滤波器。(在GitHub上可找到代码)
def viz_layer(layer, n_filters= 4):
fig = plt.figure(figsize=(20, 20))
for i in range(n_filters):
ax = fig.add_subplot(1, n_filters, i+1)
ax.imshow(np.squeeze(layer[0,i].data.numpy()), cmap='gray')
ax.set_title('Output %s' % str(i+1))
fig = plt.figure(figsize=(12, 6))
fig.subplots_adjust(left=0, right=1.5, bottom=0.8, top=1, hspace=0.05, wspace=0.05)
for i in range(4):
ax = fig.add_subplot(1, 4, i+1, xticks=[], yticks=[])
ax.imshow(filters[i], cmap='gray')
ax.set_title('Filter %s' % str(i+1))
gray_img_tensor = torch.from_numpy(gray_img).unsqueeze(0).unsqueeze(1)
滤波器:
步骤5:跨层滤波器输出。 在CONV和POOL层中输出的图像如下所示。
viz_layer(activated_layer)viz_layer(pooled_layer)
参考:CS230 CNNs(https://stanford.edu/~shervine/teaching/cs-230/cheatsheet-convolutional-neural-networks).
查看更多评论 >