通过Pytorch代码可视化理解卷积神经网络

本文代码地址:

https://github.com/AINewHorizon/visualising-cnns

机器在理解和识别图像中的特征和对象方面已经达到了99%的准确度。智能手机可以识别相机中的脸部;能够使用Google图像搜索特定照片; 从条形码或书籍扫描文本。所有这一切都归功于卷积神经网络(CNN),这是一种特殊类型的神经网络,也称为  convnet

如果你是一个深度学习[1]爱好者,你可能已经听说过卷积神经网络,也许你自己甚至开发了一些图像分类器。像Tensorflow和PyTorch这样的现代深度学习框架可以很容易地向机器训练图像,但是,仍然存在一些问题,如数据如何通过神经网络的人工层?计算机如何从中学习?如何更好地解释卷积神经网络。因此让我们通过每一层可视化图像,深入了解CNN。

通过Pytorch代码可视化理解卷积神经网络_第1张图片 卷积神经网络

卷积神经网络解释

什么是卷积神经网络?

卷积神经网络(CNN)是一种特殊类型的神经网络,在图像上工作得非常好。由Yan LeCun于1998年提出,卷积神经网络可以识别给定输入图像中存在的数字。

在开始使用卷积神经网络之前,了解神经网络的工作原理非常重要。神经网络模仿人类大脑如何解决复杂问题并在给定数据集中找到模式。在过去几年中,神经网络已经吞噬了许多机器学习和计算机视觉算法[2]

神经网络的基本模型由组织在不同层中的神经元组成。每个神经网络都有一个输入和一个输出层,根据问题的复杂性增加了许多隐藏层。一旦数据通过这些层,神经元就会学习并识别模式。神经网络的这种表示称为模型。一旦模型被训练,我们要求网络根据测试数据进行预测。如果您是神经网络的新手,那么关于Python深度学习的[3]这篇文章是一个很好的起点。

另一方面,CNN是一种特殊类型的神经网络,它在图像上工作得非常好。由Yan LeCun于1998年提出,卷积神经网络可以识别给定输入图像中存在的数字。使用CNN的其他应用包括语音识别,图像分割和文本处理。在卷积神经网络之前,多层感知器(MLP)被用于构建图像分类器。

图像分类是指从多波段光栅图像中提取信息类的任务。多层感知器需要更多时间和空间来查找图片中的信息,因为每个输入特征都需要与下一层中的每个神经元连接。CNN通过使用称为局部连接的概念来超越MLP,该概念涉及将每个神经元连接到仅输入音量的局部区域。这通过允许网络的不同部分专门处理诸如纹理或重复模式的高级特征来最小化参数的数量。迷茫?别担心。让我们比较一下如何通过多层感知器和卷积神经网络发送图像,以便更好地理解。

比较MLPS和CNNS

考虑到MNIST数据集,多层感知器的输入层的条目总数将为784,因为输入图像的大小为28x28 = 784。网络应该能够预测给定输入图像中的数字,这意味着输出可能属于以下任何类别,范围从0-9(1,2,3,4,5,6,7,8,9) )。在输出层,我们返回类别分数,比如说给定输入是一个数字为"3"的图像,那么在输出层中,相应的神经元"3"与其他神经元相比具有更高的类别分数。**我们需要包含多少个隐藏层以及每个隐藏层应该包含多少个神经元?**这是一个编码MLP的示例:

通过Pytorch代码可视化理解卷积神经网络_第2张图片 卷积神经网络pytorch可视化mlp

上面的代码片段使用名为Keras的框架实现(暂时忽略语法)。它告诉我们在第一个隐藏层中有512个神经元,它们连接到形状784的输入层。隐藏层后面是一个丢失层,它克服了过度拟合的问题**。**0.2表示在第一个隐藏层之后没有考虑神经元的可能性为20%。同样,我们添加了第二个隐藏层,其具有与第一个隐藏层(512)中相同数量的神经元,然后是另一个丢失层。最后,我们以包含10个类的输出层结束这组图层。具有最高值的该类将是模型预测的数量。

这是在定义所有层之后多层网络的样子。这种多层感知器的一个缺点是连接完整(完全连接)以供网络学习,这需要更多的时间和空间。MLP只接受向量作为输入。

通过Pytorch代码可视化理解卷积神经网络_第3张图片 卷积神经网络pytorch可视化图像分类器

卷积不使用全连接层,而是稀疏连接的层,即它们接受矩阵作为输入,这是优于MLP的优势。输入功能连接到本地编码节点。在MLP中,每个节点都有责任了解整个画面。在CNN中,我们将图像分解为区域(像素的小局部区域)。每个隐藏节点必须向输出层报告,其中输出层将接收的数据组合以查找模式。下图显示了各层如何在本地连接。

通过Pytorch代码可视化理解卷积神经网络_第4张图片 卷积神经网络pytorch可视化cnn

在我们了解CNN如何在图片中查找信息之前,我们需要了解如何提取这些功能。卷积神经网络使用不同的层,每层保存图像中的特征。例如,考虑一张狗的照片。每当网络需要对狗进行分类时,它应该识别所有特征 - 眼睛,耳朵,舌头,腿等 - 并且使用滤波器和内核在网络的本地层中分解和识别这些特征。

计算机如何理解图像?

与通过用眼睛拍摄快照来理解图像的人类不同,计算机使用0到255之间的一组像素值来理解图像。计算机查看这些像素值并理解它们。乍一看,它不知道对象或颜色,它只是识别像素值,这是计算机的所有图像。

在分析像素值之后,计算机慢慢开始了解图像是灰度还是彩色。它知道差异,因为灰度图像只有一个通道,因为每个像素代表一种颜色的强度。零表示黑色,255表示白色,黑色和白色的其他变化,即灰色位于两者之间。另一方面,彩色图像有三个通道 - 红色,绿色和蓝色。这些代表三种颜色(3D矩阵)的强度,当值同时变化时,它会产生一组颜色!在计算出颜色属性后,计算机会识别图像中对象的曲线和轮廓。

可以在卷积神经网络中使用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()))
通过Pytorch代码可视化理解卷积神经网络_第5张图片 卷积神经网络pytorch可视化输入数据

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

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]
通过Pytorch代码可视化理解卷积神经网络_第6张图片 单张图片像素可视化

这就是将数字"3"分解为像素的方式。在一组手写数字中,随机选择"3",其中示出了像素值。在这里,ToTensor()将实际像素值(0-255)标准化,并将它们限制在0到1之间。为什么?因为,它使得后面部分的计算更容易,无论是解释图像还是找到它们中存在的常见模式。

构建滤波器

在卷积神经网络中,过滤图像中的像素信息。为什么我们需要一个滤波器?就像孩子一样,计算机需要经历理解图像的学习过程。值得庆幸的是,这不需要多年的时间!计算机通过从头学习,然后继续前进到整体来实现这一目标。因此,网络必须首先知道图像中的所有原始部分,如边缘,轮廓和其他低级特征。一旦检测到这些,计算机就可以处理更复杂的功能。简而言之,必须首先提取低级功能,然后提取中级功能,然后是高级功能。滤波器提供了一种提取信息的方法。

可以使用特定滤波器提取低级特征,该滤波器也是一组像素值,类似于图像。可以理解为连接CNN中的层的权重。这些权重或滤波器与输入相乘以得到中间图像,其描绘了计算机对图像的部分理解。之后,这些副产品将与多个滤波器相乘以扩展视图。这个过程以及功能的检测一直持续到计算机理解它所看到的内容为止。

根据您的需要,您可以使用许多滤波器。您可能想要模糊,锐化,变暗,进行边缘检测等 - 所有都是滤波器。

让我们看一些代码片段来理解滤波器的功能。

通过Pytorch代码可视化理解卷积神经网络_第7张图片 输入图像代码段 通过Pytorch代码可视化理解卷积神经网络_第8张图片 输入狗的图像

通过Pytorch代码可视化理解卷积神经网络_第9张图片

定义一个滤波器
通过Pytorch代码可视化理解卷积神经网络_第10张图片 对输入图像狗进行滤波

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

完整的CNNS

到目前为止,我们已经看到滤波器如何用于从图像中提取特征,但是为了完成整个卷积神经网络,我们需要理解我们用来设计它的层。CNN中使用的层称为:

  1. 卷积层

  2. 池化层

  3. 全连接层

使用这三个层,卷积图像分类器如下所示:

通过Pytorch代码可视化理解卷积神经网络_第11张图片 卷积神经网络

现在让我们看看每个层的作用:

卷积层 - 卷积层(CONV)使用滤波器执行卷积操作,同时扫描输入图像的尺寸。其超参数包括滤波器大小,可以是2x2,3x3,4x4,5x5(但不仅限于这些)和步幅(S)。生成的输出(O)称为  要素图或激活图,并具有使用输入图层和滤波器计算的所有要素。下图描绘了应用卷积时特征贴图的生成:

通过Pytorch代码可视化理解卷积神经网络_第12张图片 卷积运算

池化层 - 该池化层(POOL)用于所述特征采样和一个卷积层之后典型地施加。两种类型的池化操作称为最大和平均池,其中分别采用要素的最大值和平均值。下面,描述了池化操作的工作:

通过Pytorch代码可视化理解卷积神经网络_第13张图片 最大池化操作 通过Pytorch代码可视化理解卷积神经网络_第14张图片 平均池化操作

**全连接层 - **全连接层(FC)在平坦的输入上操作,其中每个输入连接到所有神经元。这些通常在网络末端用于将隐藏层连接到输出层,这有助于优化课程分数。

通过Pytorch代码可视化理解卷积神经网络_第15张图片 全连接层

在PYTORCH中可视化CNNS

现在我们已经更好地了解CNN如何运作,现在让我们使用Facebook的PyTorch  框架实现一个CNN。

步骤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()
通过Pytorch代码可视化理解卷积神经网络_第16张图片 可视化滤波器

第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')
通过Pytorch代码可视化理解卷积神经网络_第17张图片 定义CNN

第3步: 定义CNN。该CNN具有卷积层和最大池化层,并且使用上述滤波器初始化权重:

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)

Conv Layers

通过Pytorch代码可视化理解卷积神经网络_第18张图片 卷积层

池化层

通过Pytorch代码可视化理解卷积神经网络_第19张图片 池化层

本文代码地址:https://github.com/AINewHorizon/visualising-cnns

请长按或扫描二维码关注本公众号

喜欢的话,请给我个在看吧

参考资料

[1]

深度学习: https://builtin.com/artificial-intelligence/deep-learning

[2]

机器学习和计算机视觉算法: https://builtin.com/data-science/tour-top-10-algorithms-machine-learning-newbies

[3]

Python深度学习的: https://builtin.com/data-science/deep-learning-python

你可能感兴趣的:(神经网络,网络,python,计算机视觉,机器学习)