多层感知器

多层感知器一 背景介绍随着科技的不断发展 人工智能成为了当今世界的一个热点研究领域

大家好,欢迎来到IT知识分享网。

一、背景介绍

       随着科技的不断发展,人工智能成为了当今世界的一个热点研究领域。人工智能的发展离不开机器学习的算法,而神经网络作为机器学习的一种重要算法,其在人工智能领域的应用日益广泛。多层感知器(MLP)是神经网络中的一种经典模型,自从1986年由Rumelhart等人提出以来,它已经在许多领域取得了显著的应用成果。本文将探讨多层感知器的理论基础、架构及其在神经网络中的应用,并对其进行实验与分析,以期为多层感知器的研究和应用提供一定的参考。
        多层感知器的研究背景可追溯至20世纪80年代,当时的人工智能领域正处于瓶颈期,传统的线性模型无法解决非线性问题。为了解决这一问题,Rumelhart等人提出了多层感知器模型,该模型具有处理非线性问题的能力,很快在模式识别、自然语言处理等领域取得了显著的成果。随着计算机性能的提升和大数据的兴起,多层感知器模型在深度学习领域得到了进一步的发展,成为当今神经网络研究的一个重要方向。
       多层感知器的意义在于其强大的表示能力和泛化能力。相较于传统的单层感知器,多层感知器可以通过多层非线性变换将输入数据映射到高维空间,从而更好地表征数据的内在结构。此外,多层感知器还可以通过训练学习到数据的通用特征,使得模型具有更好的泛化能力,适用于未见过的数据。
       在当前的研究中,多层感知器已经成功应用于许多领域。例如,在图像识别领域,多层感知器可以实现对图像的自动分类和识别,帮助计算机理解图像的语义信息。在自然语言处理领域,多层感知器可以用于文本分类、情感分析、机器翻译等任务,使得计算机能够更好地理解和生成自然语言。此外,多层感知器还在语音识别、生物信息学、推荐系统等领域取得了显著的成果。
       总之,多层感知器作为一种重要的神经网络模型,其在人工智能领域的应用具有重要的研究意义和价值。本文将深入探讨多层感知器的理论基础、架构及其应用,并进行实验与分析,以期为多层感知器的研究和应用提供一定的参考。

二、实验内容

感知器的一个历史性的缺点是它不能学习数据中存在的一些非常重要的模式。如下图中绘制的数据点。这相当于非此即彼(XOR)的情况,在这种情况下,决策边界不能是一条直线(也称为线性可分)。在这个例子中,感知器失败了。

多层感知器

       XOR数据集中的两个类绘制为圆形和星形。且没有任何一行可以分隔这两个类。

        这一实验旨在探索神经网络中的两种前馈模型:多层感知器和卷积神经网络。这些模型都属于前馈神经网络的范畴,与递归神经网络相比,它们不具备反馈或循环结构。

        多层感知器通过堆叠多个层来扩展简单感知器的结构,每一层包含多个感知器,这些层在结构上逐层堆叠。在实验中,我们将介绍如何构建和应用多层感知器,例如在姓氏分类任务中的应用示例。

       卷积神经网络受到窗口滤波器的启发,特别适用于处理数字信号。这些网络能够学习输入数据中的局部模式,因此在计算机视觉和处理序列数据(如单词或句子)中的子结构时表现出色。在本实验中,我们将概述CNN的工作原理,并展示其在姓氏分类中的应用示例。

       理解神经网络模型中数据张量的大小和形状对于深入理解这些模型的工作方式至关重要。不同类型的神经网络层对数据张量的形状和大小有特定的影响,正确理解这些影响可以帮助我们更好地应用和调整这些模型。

三、多层感知器介绍

       多层感知器(MLP)是一种经典的前馈神经网络模型,通常用于处理分类和回归问题。它由多个全连接层组成,每一层由多个神经元(或称为节点)组成,前一层的每个神经元与下一层的每个神经元都有连接。MLP的基本结构包括输入层、若干个隐藏层和输出层。

结构和特点:

2. 隐藏层:
   每个隐藏层由多个神经元组成,每个神经元与上一层的每个神经元连接,形成全连接结构。
   每个神经元对输入进行加权求和,并通过激活函数(如ReLU、sigmoid等)输出结果。

3. 输出层:
  最后一个隐藏层的输出被传递到输出层。
  输出层的神经元数量通常取决于具体的问题类型:分类问题可能有多个神经元(每个类别一个),回归问题通常只有一个神经元。

4. 激活函数:
   在每个神经元中,激活函数用于引入非线性特性,允许网络模型学习复杂的模式和关系。
   常见的激活函数包括sigmoid函数、ReLU函数(Rectified Linear Unit)等。

训练过程:

        MLP的训练通常通过反向传播算法进行,该算法基于梯度下降优化策略来调整网络的权重和偏差,使得网络能够逐渐优化模型以最小化预测输出与真实标签之间的误差。

应用和局限性:

多层感知器

四、多层感知器示例

       在这个例子中,我们在一个二元分类任务中训练感知器和MLP:星和圆。每个数据点是一个二维坐标。在不深入研究实现细节的情况下,最终的模型预测如图4-3所示。在这个图中,错误分类的数据点用黑色填充,而正确分类的数据点没有填充。在左边的面板中,从填充的形状可以看出,感知器在学习一个可以将星星和圆分开的决策边界方面有困难。然而,MLP(右面板)学习了一个更精确地对恒星和圆进行分类的决策边界。

多层感知器

       上图中每个数据点的真正类是该点的形状:星形或圆形。错误的分类用块填充,正确的分类没有填充。这些线是每个模型的决策边界。在边的面板中,感知器学习—个不能正确地将圆与星分开的决策边界。事实上,没有一条线可以。在右动的面板中,MLP学会了从圆中分离星。

        虽然在图中显示MLP有两个决策边界,这是它的优点,但它实际上只是一个决策边界!决策边界就是这样出现的,因为中间表示法改变了空间,使一个超平面同时出现在这两个位置上。在下图中,我们可以看到MLP计算的中间值。这些点的形状表示类(星形或圆形)。我们所看到的是,神经网络(本例中为MLP)已经学会了“扭曲”数据所处的空间,以便在数据通过最后一层时,用一线来分割它们。

多层感知器

和上图相反,下图所示,感知器没有额外的一层来处理数据的形状,直到数据变成线性可分的。

多层感知器

       在上述章节中,我们讨论了多层感知器(MLP)的核心概念。在本节中,我们将详细介绍如何在PyTorch中实现这一概念。

       MLP通过多个层(或称为完全连接层)和非线性激活函数的堆叠来实现复杂的模式学习。在我们前文提到的例子中,我们使用了一个简单的感知器模型,它只有一层线性层,缺乏非线性激活函数的引入,因此无法有效地捕捉复杂的数据模式。

       在PyTorch的实现中,我们使用了两个线性层(通常称为完全连接层或简称为FC层),分别命名为`fc1`和`fc2`。这些层被堆叠在一起,而在`fc1`的输出被输入到`fc2`之前,我们引入了修正线性单元(ReLU)作为非线性激活函数。这一步骤是必要的,因为它将线性变换后的输出映射到非线性空间,使得模型能够学习并捕捉数据中的非线性关系和模式。

        在PyTorch中,模型的前向传播方法(`forward`)定义了数据如何在网络中流动:从输入层经过`fc1`进行线性变换,然后通过ReLU激活函数进行非线性变换,最终通过`fc2`得到输出。这一过程构成了前向传播的计算图,PyTorch能够利用这个计算图自动计算梯度,并通过反向传播更新模型的权重和偏置,以最小化损失函数。

         PyTorch的实现利用了其自动微分的能力,使得我们只需定义模型的结构和前向传播过程,而无需手动实现反向传播的数学细节,从而简化了深度学习模型的实现和训练过程。

在上一节中,我们概述了MLP的核心思想。在本节中,我们将介绍PyTorch中的一个实现。如前所述,MLP除了实验3中简单的感知器之外,还有一个额外的计算层。在我们在例4-1中给出的实现中,我们用PyTorch的两个线性模块实例化了这个想法。线性对象被命名为fc1和fc2,它们遵循一个通用约定,即将线性模块称为“完全连接层”,简称为“fc层”。除了这两个线性层外,还有一个修正的线性单元(ReLU)非线性(在实验3“激活函数”一节中介绍),它在被输入到第二个线性层之前应用于第一个线性层的输出。由于层的顺序性,必须确保层中的输出数量等于下一层的输入数量。使用两个线性层之间的非线性是必要的,因为没有它,两个线性层在数学上等价于一个线性层4,因此不能建模复杂的模式。MLP的实现只实现反向传播的前向传递。这是因为PyTorch根据模型的定义和向前传递的实现,自动计算出如何进行向后传递和梯度更新。

import torch.nn as nn import torch.nn.functional as F class MultilayerPerceptron(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): """ Args: input_dim (int): the size of the input vectors hidden_dim (int): the output size of the first Linear layer output_dim (int): the output size of the second Linear layer """ super(MultilayerPerceptron, self).__init__() self.fc1 = nn.Linear(input_dim, hidden_dim) self.fc2 = nn.Linear(hidden_dim, output_dim) def forward(self, x_in, apply_softmax=False): """The forward pass of the MLP Args: x_in (torch.Tensor): an input data tensor. x_in.shape should be (batch, input_dim) apply_softmax (bool): a flag for the softmax activation should be false if used with the Cross Entropy losses Returns: the resulting tensor. tensor.shape should be (batch, output_dim) """ intermediate = F.relu(self.fc1(x_in)) output = self.fc2(intermediate) if apply_softmax: output = F.softmax(output, dim=1) return output

我们实例化了MLP。

Example 4-2. An example instantiation of an MLP

batch_size = 2 # number of samples input at once input_dim = 3 hidden_dim = 100 output_dim = 4 # Initialize model mlp = MultilayerPerceptron(input_dim, hidden_dim, output_dim) print(mlp)

多层感知器

Example 4-3. Testing the MLP with random inputs

import torch def describe(x): print("Type: {}".format(x.type())) print("Shape/size: {}".format(x.shape)) print("Values: \n{}".format(x)) x_input = torch.rand(batch_size, input_dim) describe(x_input)

结果如图:多层感知器

y_output = mlp(x_input, apply_softmax=False) describe(y_output)

多层感知器

学习如何读取PyTorch模型的输入和输出非常重要。在前面的例子中,MLP模型的输出是一个有两行四列的张量。这个张量中的行与批处理维数对应,批处理维数是小批处理中的数据点的数量。列是每个数据点的最终特征向量。在某些情况下,例如在分类设置中,特征向量是一个预测向量。名称为“预测向量”表示它对应于一个概率分布。预测向量会发生什么取决于我们当前是在进行训练还是在执行推理。在训练期间,输出按原样使用,带有一个损失函数和目标类标签的表示。我们将在“示例:带有多层感知器的姓氏分类”中对此进行深入介绍。

但是,如果想将预测向量转换为概率,则需要额外的步骤。具体来说,需要softmax函数,它用于将一个值向量转换为概率。softmax有许多根。在物理学中,它被称为玻尔兹曼或吉布斯分布;在统计学中,它是多项式逻辑回归;在自然语言处理(NLP)社区,它是最大熵(MaxEnt)分类器。不管叫什么名字,这个函数背后的直觉是,大的正值会导致更高的概率,小的负值会导致更小的概率。在示例4-3中,apply_softmax参数应用了这个额外的步骤。在下例,可以看到相同的输出,但是这次将apply_softmax标志设置为True:

y_output = mlp(x_input, apply_softmax=True) describe(y_output)

多层感知器

综上所述,mlp是将张量映射到其他张量的线性层。在每一对线性层之间使用非线性来打破线性关系,并允许模型扭曲向量空间。在分类设置中,这种扭曲应该导致类之间的线性可分性。另外,可以使用softmax函数将MLP输出解释为概率,但是不应该将softmax与特定的损失函数一起使用,因为底层实现可以利用高级数学/计算捷径。

五、基于MLP的姓氏分类实验步骤

在本节中,我们将MLP应用于将姓氏分类到其原籍国的任务。从公开观察到的数据推断人口统计信息(如国籍)具有从产品推荐到确保不同人口统计用户获得公平结果的应用。人口统计和其他自我识别信息统称为“受保护属性”。“在建模和产品中使用这些属性时,必须小心。”我们首先对每个姓氏的字符进行拆分,并像对待“示例:将餐馆评论的情绪分类”中的单词一样对待它们。除了数据上的差异,字符层模型在结构和实现上与基于单词的模型基本相似.

应该从这个例子中吸取的一个重要教训是,MLP的实现和训练是从我们在第3章中看到的感知器的实现和培训直接发展而来的。此外,我们不包括“例子:餐馆评论的情绪分类”中看到的代码。

本节的其余部分将从姓氏数据集及其预处理步骤的描述开始。然后,我们使用词汇表、向量化器和DataLoader类逐步完成从姓氏字符串到向量化小批处理的管道。

我们将通过描述姓氏分类器模型及其设计背后的思想过程来继续本节。MLP类似于我们在实验3中看到的感知器例子,但是除了模型的改变,我们在这个例子中引入了多类输出及其对应的损失函数。在描述了模型之后,我们完成了训练例程。训练程序与“示例:对餐馆评论的情绪进行分类”非常相似,因此为了简洁起见,我们在这里不像在该部分中那样深入,可以回顾这一节内容。

5.1.1 The Surname Dataset

姓氏数据集,它收集了来自18个不同国家的10,000个姓氏,这些姓氏是作者从互联网上不同的姓名来源收集的。该数据集将在本课程实验的几个示例中重用,并具有一些使其有趣的属性。第一个性质是它是相当不平衡的。排名前三的课程占数据的60%以上:27%是英语,21%是俄语,14%是阿拉伯语。剩下的15个民族的频率也在下降——这也是语言特有的特性。第二个特点是,在国籍和姓氏正字法(拼写)之间有一种有效和直观的关系。有些拼写变体与原籍国联系非常紧密(比如“O ‘Neill”、“Antonopoulos”、“Nagasawa”或“Zhu”)。

为了创建最终的数据集,我们从一个比课程补充材料中包含的版本处理更少的版本开始,并执行了几个数据集修改操作。第一个目的是减少这种不平衡——原始数据集中70%以上是俄文,这可能是由于抽样偏差或俄文姓氏的增多。为此,我们通过选择标记为俄语的姓氏的随机子集对这个过度代表的类进行子样本。接下来,我们根据国籍对数据集进行分组,并将数据集分为三个部分:70%到训练数据集,15%到验证数据集,最后15%到测试数据集,以便跨这些部分的类标签分布具有可比性。

SurnameDataset的实现与“Example: classification of Sentiment of Restaurant Reviews”中的ReviewDataset几乎相同,只是在getitem方法的实现方式上略有不同。回想一下,本课程中呈现的数据集类继承自PyTorch的数据集类,因此,我们需要实现两个函数:__getitem方法,它在给定索引时返回一个数据点;以及len方法,该方法返回数据集的长度。“示例:餐厅评论的情绪分类”中的示例与本示例的区别在getitem__中。它不像“示例:将餐馆评论的情绪分类”那样返回一个向量化的评论,而是返回一个向量化的姓氏和与其国籍相对应的索引:

5.1.2 Vocabulary, Vectorizer, and DataLoader

为了使用字符对姓氏进行分类,我们使用词汇表、向量化器和DataLoader将姓氏字符串转换为向量化的minibatches。这些数据结构与“Example: Classifying Sentiment of Restaurant Reviews”中使用的数据结构相同,它们举例说明了一种多态性,这种多态性将姓氏的字符标记与Yelp评论的单词标记相同对待。数据不是通过将字令牌映射到整数来向量化的,而是通过将字符映射到整数来向量化的。

THE VOCABULARY CLASS

本例中使用的词汇类与“example: Classifying Sentiment of Restaurant Reviews”中的词汇完全相同,该词汇类将Yelp评论中的单词映射到对应的整数。简要概述一下,词汇表是两个Python字典的协调,这两个字典在令牌(在本例中是字符)和整数之间形成一个双射;也就是说,第一个字典将字符映射到整数索引,第二个字典将整数索引映射到字符。add_token方法用于向词汇表中添加新的令牌,lookup_token方法用于检索索引,lookup_index方法用于检索给定索引的令牌(在推断阶段很有用)。与Yelp评论的词汇表不同,我们使用的是one-hot词汇表,不计算字符出现的频率,只对频繁出现的条目进行限制。这主要是因为数据集很小,而且大多数字符足够频繁。

THE SURNAMEVECTORIZER

虽然词汇表将单个令牌(字符)转换为整数,但SurnameVectorizer负责应用词汇表并将姓氏转换为向量。实例化和使用非常类似于“示例:对餐馆评论的情绪进行分类”中的ReviewVectorizer,但有一个关键区别:字符串没有在空格上分割。姓氏是字符的序列,每个字符在我们的词汇表中是一个单独的标记。然而,在“卷积神经网络”出现之前,我们将忽略序列信息,通过迭代字符串输入中的每个字符来创建输入的收缩one-hot向量表示。我们为以前未遇到的字符指定一个特殊的令牌,即UNK。由于我们仅从训练数据实例化词汇表,而且验证或测试数据中可能有惟一的字符,所以在字符词汇表中仍然使用UNK符号。

虽然我们在这个示例中使用了收缩的one-hot,但是在后面的实验中,将了解其他向量化方法,它们是one-hot编码的替代方法,有时甚至更好。具体来说,在“示例:使用CNN对姓氏进行分类”中,将看到一个热门矩阵,其中每个字符都是矩阵中的一个位置,并具有自己的热门向量。然后,在实验5中,将学习嵌入层,返回整数向量的向量化,以及如何使用它们创建密集向量矩阵。

5.1.3 The Surname Classifier Model

SurnameClassifier是本实验前面介绍的MLP的实现。第一个线性层将输入向量映射到中间向量,并对该向量应用非线性。第二线性层将中间向量映射到预测向量。

在最后一步中,可选地应用softmax操作,以确保输出和为1;这就是所谓的“概率”。它是可选的原因与我们使用的损失函数的数学公式有关——交叉熵损失。我们研究了“损失函数”中的交叉熵损失。回想一下,交叉熵损失对于多类分类是最理想的,但是在训练过程中软最大值的计算不仅浪费而且在很多情况下并不稳定。

5.1.4 The Training Routine

虽然我们使用了不同的模型、数据集和损失函数,但是训练例程是相同的。

5.1.5 Model Evaluation and Prediction

要理解模型的性能,应该使用定量和定性方法分析模型。定量测量出的测试数据的误差,决定了分类器能否推广到不可见的例子。定性地说,可以通过查看分类器的top-k预测来为一个新示例开发模型所了解的内容的直觉。

5.1.5.1 EVALUATING ON THE TEST DATASET

评价SurnameClassifier测试数据,我们执行相同的常规的routine文本分类的例子“餐馆评论的例子:分类情绪”:我们将数据集设置为遍历测试数据,调用classifier.eval()方法,并遍历测试数据以同样的方式与其他数据。在这个例子中,调用classifier.eval()可以防止PyTorch在使用测试/评估数据时更新模型参数。

该模型对测试数据的准确性达到50%左右。如果在附带的notebook中运行训练例程,会注意到在训练数据上的性能更高。这是因为模型总是更适合它所训练的数据,所以训练数据的性能并不代表新数据的性能。如果遵循代码,你可以尝试隐藏维度的不同大小,应该注意到性能的提高。然而,这种增长不会很大(尤其是与“用CNN对姓氏进行分类的例子”中的模型相比)。其主要原因是收缩的onehot向量化方法是一种弱表示。虽然它确实简洁地将每个姓氏表示为单个向量,但它丢弃了字符之间的顺序信息,这对于识别起源非常重要。

5.1.5.2 CLASSIFYING A NEW SURNAME

给定一个姓氏作为字符串,该函数将首先应用向量化过程,然后获得模型预测。注意,我们包含了apply_softmax标志,所以结果包含概率。模型预测,在多项式的情况下,是类概率的列表。我们使用PyTorch张量最大函数来得到由最高预测概率表示的最优类。

5.1.5.3 RETRIEVING THE TOP-K PREDICTIONS FOR A NEW SURNAME

不仅要看最好的预测,还要看更多的预测。例如,NLP中的标准实践是采用k-best预测并使用另一个模型对它们重新排序。PyTorch提供了一个torch.topk函数,它提供了一种方便的方法来获得这些预测。

5.1.6 Regularizing MLPs: Weight Regularization and Structural Regularization (or Dropout)

我们将在本实验后面介绍。除权值正则化外,对于深度模型(即例如本实验讨论的前馈网络,一种称为dropout的结构正则化方法变得非常重要。

六、Convolutional Neural Networks

      在第一部分内容中,我们深入研究了MLPs、由一系列线性层和非线性函数构建的神经网络。mlp不是利用顺序模式的最佳工具。例如,在姓氏数据集中,姓氏可以有(不同长度的)段,这些段可以显示出相当多关于其起源国家的信息(如“O’Neill”中的“O”、“Antonopoulos”中的“opoulos”、“Nagasawa”中的“sawa”或“Zhu”中的“Zh”)。这些段的长度可以是可变的,挑战是在不显式编码的情况下捕获它们。

       在本节中,我们将介绍卷积神经网络(CNN),这是一种非常适合检测空间子结构(并因此创建有意义的空间子结构)的神经网络。CNNs通过使用少量的权重来扫描输入数据张量来实现这一点。通过这种扫描,它们产生表示子结构检测(或不检测)的输出张量。

在本节的其余部分中,我们首先描述CNN的工作方式,以及在设计CNN时应该考虑的问题。我们深入研究CNN超参数,目的是提供直观的行为和这些超参数对输出的影响。最后,我们通过几个简单的例子逐步说明CNNs的机制。在“示例:使用CNN对姓氏进行分类”中,我们将深入研究一个更广泛的示例。

HISTORICAL CONTEXT

CNNs的名称和基本功能源于经典的数学运算卷积。卷积已经应用于各种工程学科,包括数字信号处理和计算机图形学。一般来说,卷积使用程序员指定的参数。这些参数被指定来匹配一些功能设计,如突出边缘或抑制高频声音。事实上,许多Photoshop滤镜都是应用于图像的固定卷积运算。然而,在深度学习和本实验中,我们从数据中学习卷积滤波器的参数,因此它对于解决当前的任务是最优的。

CNN Hyperparameters

为了理解不同的设计决策对CNN意味着什么,我们在下图中展示了一个示例。在本例中,单个“核”应用于输入矩阵。卷积运算(线性算子)的精确数学表达式对于理解这一节并不重要,但是从这个图中可以直观地看出,核是一个小的方阵,它被系统地应用于输入矩阵的不同位置。

多层感知器

输入矩阵与单个产生输出矩阵的卷积核(也称为特征映射)在输入矩阵的每个位置应用内核。在每个应用程序中,内核乘以输入矩阵的值及其自身的值,然后将这些乘法相加kernel具有以下超参数配置:kernel_size=2,stride=1,padding=0,以及dilation=1。这些超参数解释如下:

虽然经典卷积是通过指定核的具体值来设计的,但是CNN是通过指定控制CNN行为的超参数来设计的,然后使用梯度下降来为给定数据集找到最佳参数。两个主要的超参数控制卷积的形状(称为kernel_size)和卷积将在输入数据张量(称为stride)中相乘的位置。还有一些额外的超参数控制输入数据张量被0填充了多少(称为padding),以及当应用到输入数据张量(称为dilation)时,乘法应该相隔多远。在下面的小节中,我们将更详细地介绍这些超参数。

DIMENSION OF THE CONVOLUTION OPERATION

首先要理解的概念是卷积运算的维数。在图4-6和本节的其他图中,我们使用二维卷积进行说明,但是根据数据的性质,还有更适合的其他维度的卷积。在PyTorch中,卷积可以是一维、二维或三维的,分别由Conv1d、Conv2d和Conv3d模块实现。一维卷积对于每个时间步都有一个特征向量的时间序列非常有用。在这种情况下,我们可以在序列维度上学习模式。NLP中的卷积运算大多是一维的卷积。另一方面,二维卷积试图捕捉数据中沿两个方向的时空模式;例如,在图像中沿高度和宽度维度——为什么二维卷积在图像处理中很流行。类似地,在三维卷积中,模式是沿着数据中的三维捕获的。例如,在视频数据中,信息是三维的,二维表示图像的帧,时间维表示帧的序列。就本课程而言,我们主要使用Conv1d。

CHANNELS

非正式地,通道(channel)是指沿输入中的每个点的特征维度。例如,在图像中,对应于RGB组件的图像中的每个像素有三个通道。在使用卷积时,文本数据也可以采用类似的概念。从概念上讲,如果文本文档中的“像素”是单词,那么通道的数量就是词汇表的大小。如果我们更细粒度地考虑字符的卷积,通道的数量就是字符集的大小(在本例中刚好是词汇表)。在PyTorch卷积实现中,输入通道的数量是in_channels参数。卷积操作可以在输出(out_channels)中产生多个通道。您可以将其视为卷积运算符将输入特征维“映射”到输出特征维。下面两个图说明了这个概念。

多层感知器

多层感知器

第一个图, 卷积运算用两个输入矩阵(两个输入通道)表示相应的核也有两层,它将每层分别相乘,然后对结果求和。

第二个图,一种具有一个输入矩阵(一个输入通道)和两个卷积的卷积运算核(两个输出通道)。这些核分别应用于输入矩阵,并堆叠在输出张量。

很难立即知道有多少输出通道适合当前的问题。为了简化这个困难,我们假设边界是1,1,024——我们可以有一个只有一个通道的卷积层,也可以有一个只有1,024个通道的卷积层。现在我们有了边界,接下来要考虑的是有多少个输入通道。一种常见的设计模式是,从一个卷积层到下一个卷积层,通道数量的缩减不超过2倍。这不是一个硬性的规则,但是它应该让您了解适当数量的out_channels是什么样子的。

ERNEL SIZE

核矩阵的宽度称为核大小(PyTorch中的kernel_size)。卷积将输入中的空间(或时间)本地信息组合在一起,每个卷积的本地信息量由内核大小控制。然而,通过增加核的大小,也会减少输出的大小。如下图:核为3.

多层感知器

此外,可以将NLP应用程序中核大小的行为看作类似于通过查看单词组捕获语言模式的n-gram的行为。使用较小的核大小,可以捕获较小的频繁模式,而较大的核大小会导致较大的模式,这可能更有意义,但是发生的频率更低。较小的核大小会导致输出中的细粒度特性,而较大的核大小会导致粗粒度特性。

STRIDE

Stride控制卷积之间的步长。如果步长与核相同,则内核计算不会重叠。另一方面,如果跨度为1,则内核重叠最大。输出张量可以通过增加步幅的方式被有意的压缩来总结信息,如下图所示。

多层感知器

PADDING

即使stride和kernel_size允许控制每个计算出的特征值有多大范围,它们也有一个有害的、有时是无意的副作用,那就是缩小特征映射的总大小(卷积的输出)。为了抵消这一点,输入数据张量被人为地增加了长度(如果是一维、二维或三维)、高度(如果是二维或三维)和深度(如果是三维),方法是在每个维度上附加和前置0。这意味着CNN将执行更多的卷积,但是输出形状可以控制,而不会影响所需的核大小、步幅或扩展。下图展示了正在运行的填充。

多层感知器

DILATION

膨胀控制卷积核如何应用于输入矩阵。在下图中,我们显示,将膨胀从1(默认值)增加到2意味着当应用于输入矩阵时,核的元素彼此之间是两个空格。另一种考虑这个问题的方法是在核中跨跃——在核中的元素或核的应用之间存在一个step size,即存在“holes”。这对于在不增加参数数量的情况下总结输入空间的更大区域是有用的。当卷积层被叠加时,扩张卷积被证明是非常有用的。连续扩张的卷积指数级地增大了“接受域”的大小;即网络在做出预测之前所看到的输入空间的大小。

多层感知器

Implementing CNNs in PyTorch

在本节中,我们将通过端到端示例来利用上一节中介绍的概念。一般来说,神经网络设计的目标是找到一个能够完成任务的超参数组态。我们再次考虑在“示例:带有多层感知器的姓氏分类”中引入的现在很熟悉的姓氏分类任务,但是我们将使用CNNs而不是MLP。我们仍然需要应用最后一个线性层,它将学会从一系列卷积层创建的特征向量创建预测向量。这意味着目标是确定卷积层的配置,从而得到所需的特征向量。所有CNN应用程序都是这样的:首先有一组卷积层,它们提取一个feature map,然后将其作为上游处理的输入。在分类中,上游处理几乎总是应用线性(或fc)层。

本课程中的实现遍历设计决策,以构建一个特征向量。我们首先构造一个人工数据张量,以反映实际数据的形状。数据张量的大小是三维的——这是向量化文本数据的最小批大小。如果你对一个字符序列中的每个字符使用onehot向量,那么onehot向量序列就是一个矩阵,而onehot矩阵的小批量就是一个三维张量。使用卷积的术语,每个onehot(通常是词汇表的大小)的大小是”input channels”的数量,字符序列的长度是“width”。

Classifying Surnames by Using a CNN

为了证明CNN的有效性,让我们应用一个简单的CNN模型来分类姓氏。这项任务的许多细节与前面的MLP示例相同,但真正发生变化的是模型的构造和向量化过程。模型的输入,而不是我们在上一个例子中看到的收缩的onehot,将是一个onehot的矩阵。这种设计将使CNN能够更好地“view”字符的排列,并对在“示例:带有多层感知器的姓氏分类”中使用的收缩的onehot编码中丢失的序列信息进行编码。

The SurnameDataset

虽然姓氏数据集之前在“示例:带有多层感知器的姓氏分类”中进行了描述,但建议参考“姓氏数据集”来了解它的描述。尽管我们使用了来自“示例:带有多层感知器的姓氏分类”中的相同数据集,但在实现上有一个不同之处:数据集由onehot向量矩阵组成,而不是一个收缩的onehot向量。为此,我们实现了一个数据集类,它跟踪最长的姓氏,并将其作为矩阵中包含的行数提供给矢量化器。列的数量是onehot向量的大小(词汇表的大小)。

我们使用数据集中最长的姓氏来控制onehot矩阵的大小有两个原因。首先,将每一小批姓氏矩阵组合成一个三维张量,要求它们的大小相同。其次,使用数据集中最长的姓氏意味着可以以相同的方式处理每个小批处理。

Vocabulary, Vectorizer, and DataLoader

在本例中,尽管词汇表和DataLoader的实现方式与“示例:带有多层感知器的姓氏分类”中的示例相同,但Vectorizer的vectorize()方法已经更改,以适应CNN模型的需要。一般在代码中需要将该函数将字符串中的每个字符映射到一个整数,然后使用该整数构造一个由onehot向量组成的矩阵。重要的是,矩阵中的每一列都是不同的onehot向量。主要原因是,我们将使用的Conv1d层要求数据张量在第0维上具有批处理,在第1维上具有通道,在第2维上具有特性。

除了更改为使用onehot矩阵之外,我们还修改了矢量化器,以便计算姓氏的最大长度并将其保存为max_surname_length

Miscellaneous Topics in CNNs

还有几个其他的主题,这些主题是CNNs的核心,在它们的共同使用中起着主要作用。特别是,你将看到Pooling操作、batch Normalization、network-in-network connection和residual connections的描述。感兴趣的可以自己去搜索一下,这里就不做过多的讨论了。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/116027.html

(0)
上一篇 2024-11-18 22:00
下一篇 2024-11-18 22:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信