通过PyTorch中的可视化了解卷积神经网络

在我们这个时代,机器在理解和定义图像中的特征和对象方面已经成功实现了99%的精度。 例如,我们每天都面临着这样的情况:智能手机的摄像头中的人脸识别功能,能够在Google上搜索照片,以很高的速度从条形码或书籍中扫描文本等功能。得益于一种称为卷积神经的特殊类型的神经网络,这种机器效率得以实现网络。 如果您是一名深度学习爱好者,您可能听说过它,并且可以开发几个图像分类器。 Tensorflow和PyTorch等现代深度学习框架可简化图像机器学习。 但是,问题仍然存在:数据如何通过神经网络的各个层以及计算机如何从它们中学习? 为了从头开始获得清晰的视图,我们进行了卷积,以可视化每一层的图像。

图片

卷积神经网络


在开始研究卷积神经网络(SNA)之前,您需要学习如何使用神经网络。 神经网络模仿人的大脑来解决复杂的问题并搜索数据模式。 在过去的几年中,它们已经取代了许多机器学习和计算机视觉算法。 神经网络的基本模型由分层组织的神经元组成。 每个神经网络都有一个输入和输出层,并根据问题的复杂性添加了几个隐藏层。 通过层传输数据时,神经元受到训练并识别体征。 神经网络的这种表示称为模型。 训练模型后,我们要求网络根据测试数据进行预测。

SNS是一种特殊的神经网络,可以很好地处理图像。 伊恩·勒昆(Ian Lekun)于1998年提出了它们,他们在输入图像中识别出存在的数字。 SNA还用于语音识别,图像分割和文本处理。 在创建卷积神经网络之前,多层感知器用于构造图像分类器。 图像分类是指从多通道(彩色,黑白)光栅图像中提取类的任务。 多层感知器需要很长时间来搜索图像中的信息,因为每个输入必须与下一层中的每个神经元相关联。 SNA使用称为本地连接的概念绕过了它们。 这意味着我们将仅将每个神经元连接到本地输入区域。 这样可以最大程度地减少参数的数量,从而允许网络的各个部分专门处理高级属性,例如纹理或重复图案。 感到困惑? 让我们比较一下如何通过多层感知器(MP)和卷积神经网络传输图像。

MP和SNA的比较


多层感知器在输入层中的条目总数为784,因为输入图像的大小为28x28 = 784(考虑了MNIST数据集)。 网络必须能够预测输入图像上的数字,这意味着输出可以属于0到9范围内的以下任何类别。在输出层中,我们返回类别估计值,例如该输入是否为数字“ 3”的图像,那么在输出层中,与其他神经元相比,相应的神经元“ 3”具有更高的值。 再次出现一个问题:“我们需要多少个隐藏层,每个层中应该有多少个神经元?” 例如,采用以下MP代码:

图片

上面的代码是使用称为Keras的框架实现的。 第一隐藏层有512个神经元,它们与784个神经元的输入层相连。 下一个隐藏层:排除层,它解决了重新训练的问题。 0.2表示有20%的机会不考虑先前隐藏层的神经元。 我们再次添加了具有与第一个隐藏层(512)中相同数量的神经元的第二个隐藏层,然后添加了另一个排他层。 最后,以包含10个类的输出层结束该层集合。 最重要的类别将是模型预测的数量。 这是识别所有层后多层网络的外观。 多级感知器的缺点之一是它是完全连接的,这需要大量的时间和空间。

图片

Convolts不使用完全粘合的层。 他们使用稀疏层(将矩阵作为输入),这比MP具有优势。 在MP中,每个节点负责了解整个图片。 在SNA中,我们将图像分成多个区域(像素的小局部区域)。 输出层组合从每个隐藏节点接收到的数据以查找模式。 下图是各层之间如何连接的图像。

图片

现在,让我们看看SNA如何在照片中找到信息。 在此之前,我们需要了解如何提取符号。 在SNA中,我们使用不同的层,每个层都保留图像的标志,例如,它考虑了狗的图像,当网络需要对狗进行分类时,它必须识别所有标志,例如眼睛,耳朵,舌头,腿等。 这些标志已被破坏,并使用过滤器和内核在本地网络级别被识别。

计算机如何查看图像?


一个人看着图像并理解其含义听起来很合理。 假设您走路时注意到附近的许多风景。 在这种情况下,我们如何理解自然? 我们使用主要的感知器官-眼睛为环境拍照,然后将其发送到视网膜。 一切看起来都很有趣,对不对? 现在,让我们想象一台计算机也可以这样做。 在计算机中,使用一组介于0到255之间的像素值来解释图像。计算机查看并理解了这些像素值。 乍一看,他不知道物体和颜色。 它仅识别像素值,并且图像等效于计算机的一组像素值。 后来,通过分析像素值,他逐渐了解了图像是灰色还是彩色。 灰度图像只有一个通道,因为每个像素代表一种颜色的强度。 0表示黑色,255表示白色,黑色和白色的其他变体(即灰色)介于它们之间。

彩色图像具有三个通道,红色,绿色和蓝色。 它们代表3种颜色(三维矩阵)的强度,并且当值同时更改时,这将提供大量颜色,实际上是调色板! 之后,计算机将识别图像中对象的曲线和轮廓。 所有这些都可以在卷积神经网络中进行研究。 为此,我们将使用PyTorch加载数据集并将滤镜应用于图像。 以下是一段代码。

# Load the libraries import torch import numpy as np from torchvision import datasets import torchvision.transforms as transforms # Set the parameters num_workers = 0 batch_size = 20 # Converting the Images to tensors using Transforms transform = transforms.ToTensor() train_data = datasets.MNIST(root='data', train=True, download=True, transform=transform) test_data = datasets.MNIST(root='data', train=False, download=True, transform=transform) # Loading the Data train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=num_workers) test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, num_workers=num_workers) import matplotlib.pyplot as plt %matplotlib inline dataiter = iter(train_loader) images, labels = dataiter.next() images = images.numpy() # Peeking into dataset fig = plt.figure(figsize=(25, 4)) for image in np.arange(20): ax = fig.add_subplot(2, 20/2, image+1, xticks=[], yticks=[]) ax.imshow(np.squeeze(images[image]), cmap='gray') ax.set_title(str(labels[image].item())) 

图片

现在,让我们看看如何将单个图像馈入神经网络。

 img = np.squeeze(images[7]) fig = plt.figure(figsize = (12,12)) ax = fig.add_subplot(111) ax.imshow(img, cmap='gray') width, height = img.shape thresh = img.max()/2.5 for 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的范围内。为什么? 因为它有助于后续部分中的计算,所以无论是解释图像还是找到其中存在的常见模式都可以。

创建自己的过滤器


顾名思义,过滤器过滤信息。 对于卷积神经网络,在处理图像时,将过滤有关像素的信息。 我们为什么要过滤呢? 请记住,计算机必须经历学习过程才能理解图像,这与孩子的行为非常相似。 但是,在这种情况下,我们将不需要很多年! 简而言之,他从头开始学习,然后全面发展。

因此,网络首先应该知道图像的所有粗糙部分,即边缘,轮廓和其他低级元素。 一旦发现它们,就为复杂症状铺平了道路。 要获得它们,我们必须首先提取低级属性,然后提取中级属性,然后再提取高级属性。 筛选器是一种提取用户所需信息的方法,而不仅仅是盲目的数据传输,因此计算机无法理解图像的结构。 首先,可以基于特定的过滤器提取低级功能。 这里的过滤器也是一组像素值,类似于图像。 可以理解为连接卷积神经网络中各层的权重。 将这些权重或过滤器乘以输入值以生成表示计算机对图像的理解的中间图像。 然后将它们乘以更多的过滤器以扩展视图。 然后,它检测到人的可见器官(假设图像中存在人)。 后来,由于包含更多的过滤器和几层,计算机惊呼:“哦,是的! 这是一个男人。”

如果我们谈论过滤器,那么我们有很多选择。 您可能需要对图像进行模糊处理,然后应用模糊滤镜,如果您需要增加清晰度,则可以使用清晰度滤镜,以此类推。

让我们看一些代码片段,以了解过滤器的功能。

图片

图片

图片

图片

这就是应用滤镜后图像的外观,在这种情况下,我们使用了Sobel滤镜。

卷积神经网络


到目前为止,我们已经看到了如何使用过滤器从图像中提取特征。 现在,要完成整个卷积神经网络,我们需要了解用于设计它的所有层。 SNA中使用的图层

  1. 卷积层
  2. 汇聚层
  3. 全粘结层

在所有三层中,卷积图像分类器如下所示:

图片

现在,让我们看看每个图层的作用。

卷积层(CONV)使用通过扫描输入图像执行卷积操作的滤镜。 它的超参数包括一个可以为2x2、3x3、4x4、5x5(但不限于此)的滤镜大小和步骤S。结果O称为要素图或激活图,其中所有要素均使用输入层和滤镜进行计算。 下图是应用卷积时生成特征图的图像,

图片

合并层(POOL)用于压缩卷积层之后通常使用的功能。 联合操作有两种类型-这是最大联合和平均联合,分别获取特征的最大值和平均值。 以下是合并操作的操作,

图片

图片

完全连接层(FC)使用平面输入操作,其中每个输入都连接到所有神经元。 它们通常用于网络的末端,以将隐藏层连接到输出层,这有助于优化班级成绩。

图片

PyTorch中的SNA可视化


现在我们已经拥有构建SNA的完整思想,让我们使用Facebook的PyTorch框架来实现SNA。

步骤1 :下载要通过网络发送的输入图像。 (这里我们用Numpy和OpenCV做到)

 import cv2 import matplotlib.pyplot as plt %matplotlib inline img_path = 'dog.jpg' bgr_img = cv2.imread(img_path) gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY) # Normalise gray_img = gray_img.astype("float32")/255 plt.imshow(gray_img, cmap='gray') plt.show() 

图片

第2步 :渲染滤镜

让我们可视化过滤器,以更好地了解我们将使用哪些过滤器,

 import numpy as np filter_vals = np.array([ [-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1] ]) print('Filter shape: ', filter_vals.shape) # Defining the Filters filter_1 = filter_vals filter_2 = -filter_1 filter_3 = filter_1.T filter_4 = -filter_3 filters = np.array([filter_1, filter_2, filter_3, filter_4]) # Check the Filters fig = plt.figure(figsize=(10, 5)) 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)) width, height = filters[i].shape for x in range(width): for y in range(height): ax.annotate(str(filters[i][x][y]), xy=(y,x), color='white' if filters[i][x][y]<0 else 'black') 

图片

步骤3 :确定SNA

该SNA具有卷积层和具有最大功能的池化层,并且权重使用上面显示的过滤器进行初始化,

 import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self, weight): super(Net, self).__init__() # initializes the weights of the convolutional layer to be the weights of the 4 defined filters k_height, k_width = weight.shape[2:] # assumes there are 4 grayscale filters self.conv = nn.Conv2d(1, 4, kernel_size=(k_height, k_width), bias=False) # initializes the weights of the convolutional layer self.conv.weight = torch.nn.Parameter(weight) # define a pooling layer self.pool = nn.MaxPool2d(2, 2) def forward(self, x): # calculates the output of a convolutional layer # pre- and post-activation conv_x = self.conv(x) activated_x = F.relu(conv_x) # applies pooling layer pooled_x = self.pool(activated_x) # returns all layers return conv_x, activated_x, pooled_x # instantiate the model and set the weights weight = torch.from_numpy(filters).unsqueeze(1).type(torch.FloatTensor) model = Net(weight) # print out the layer in the network print(model) 

 Net( (conv): Conv2d(1, 4, kernel_size=(4, 4), stride=(1, 1), bias=False) (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) 
步骤4 :渲染滤镜
快速浏览使用的过滤器,

 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) 

卷积层

图片

池层

图片
来源

Source: https://habr.com/ru/post/zh-CN436838/


All Articles