神经背包
用神经网络求解背包问题
在数据科学的某些情况下,需要对模型的输出运行特定的算法来获得结果。有时,它就像找到最大输出的索引一样简单,而其他时候,则需要更高级的算法。您可以在运行推理后运行算法。然而,设计一个可以在内部运行算法的模型有一些好处。使用神经网络解决背包问题不仅有助于模型在内部运行背包算法,而且允许模型被端到端地训练。
什么是背包问题?
我可爱的计算机算法老师用这个故事给我解释了背包问题。想象一个小偷在抢劫。有一些物品可供抢劫。每个项目都有自己的重量和价值。小偷有一个容量确定的背包,该背包指示他(或她)能够携带的最大重量。小偷的利润是通过对所选物品的价值求和来计算的。我们的目标是最大化利润,同时保持所选物品的重量总和小于背包的容量。
据维基百科:
给定一组项目,每个项目都有一个重量和一个值,确定集合中要包含的每个项目的数量,使总重量小于或等于给定的限制,并且总值尽可能大。它的名字来源于一个人面临的问题,他被一个固定大小的背包所束缚,必须在里面装满最有价值的物品”
在本文中,我们尝试使用神经网络来解决背包问题。
数据
第一步是准备数据。我们使用随机整数来表示物品的重量、价格和背包的容量。创建问题后,我们使用蛮力来寻找最优解。
一个生成背包问题;
Weights: [13, 10, 13, 7, 2]
Prices: [8, 7, 9, 6, 4]
Capacity: 27
Optimum solution: [0, 1, 1, 0, 1]
标准化输入是每个机器学习项目的一部分,因为它有助于模型更好地概括。为了标准化每个背包问题:
- 将价格除以问题的最高价格。
- 用重量除以容量。
- 从输入中删除容量,因为它现在包含在权重中。
先前创建的背包问题的规范化形式:
Weights: [0.48, 0.37, 0.48, 0.26, 0.07]
Prices: [0.89, 0.44, 1.00, 0.67, 0.44]
Optimum solution: [0, 1, 1, 0, 1]
数据集由一万个用于训练的样本和两百个用于测试的样本组成。
模型
我们为此任务选择的模型是一个相当简单的模型。它有两个输入和一个输出。首先,输入被连接在一起。结果进入由 sigmoid 非线性激活的两个连续的密集层。第二密集层的输出是模型的输出。在 Keras 中实施该模型:
下图显示了模型的体系结构:
Model architecture
衡量标准
背包问题需要除二进制分类精度之外的度量来进行评估。我们引入的第一个指标叫做“定价过高”。顾名思义,它评估所选项目的价格和最优解之间的平均差异。它在 Keras 框架中实现如下:
另一个重要的指标是使用的容量超过背包的容量。“空间违规是所选物品重量之和与背包容量之间的正差值。它可以在 Keras 中实现如下:
监督方法
在监督方法中,我们将权重和价格输入到模型中,并期望最优解作为输出。在此过程中,模型使用交叉熵损失函数进行训练。
在使用监督方法训练模型之后,我们在 512 个时期之后获得了以下结果。
Model results(Train/Test):
Loss: 0.24 / 0.24
Binary accuracy: 0.89 / 0.89
Space violation: 0.04 / 0.06
Overpricing: 0.06 / 0.08
不幸的是,有监督的方法有两个基本问题:
- 最佳解决方案是强制开始训练。
- 我们对空间违规和定价过高没有任何控制。
我们将尝试在无监督的方法中解决这些问题。
无监督方法
我们希望在不计算最优解的情况下训练模型。因此,我们需要一个新的损失函数。相应地,我们随后将 w , p , c ,**,**o 定义为物品的重量,物品的价格,背包的容量和模型的产量。首先,我们需要最大化所选商品的价格总和。它可以通过以下方式计算:
同时,我们希望我们的选择不超过背包的容量。该值可以通过以下公式表示:
最后,我们要最大化 总价 同时最小化 空间违例 。这可以通过以下方式制定:
为了控制 空间违逆 ,我们在第二项中加入了 λ 系数。最终损失公式为:
我们可以像这样在 Keras 中实现新的损失:
使用这个损失函数,我们以无监督的方式训练神经网络。
注 1: 背包损耗的 Keras 实现中 λ 参数命名为 cvc 。
注 2: 虽然我们收到了最优解(y_true)作为函数自变量,但我们并不使用它来计算损失。我们也不能省略参数,因为在损失函数中接收预测和预期输出是一个 Keras 约束。
注 3: 当我们归一化数据时,背包的容量等于 1。
在用非监督方法训练模型之后,我们在 512 个时期之后得到以下结果。
Model results(Train/Test):
Loss: -1.83 / -1.75
Binary accuracy: 0.89 / 0.89
Space violation: 0.05 / 0.06
Overpricing: 0.12 / 0.14
增加CVC*(λ)的值会在更少的空间内造成违规和套印。增加太多也会降低二进制精度。我发现它的合理值可能是 5.75。*
结论
如前所述,我们使用神经网络解决了背包问题,而梯度可以通过网络。因此,我们的模型可以使用反向传播算法的任何变体进行端到端的训练。
这篇文章可以用在推荐系统中,特别是那些在保持空间使用率的同时推荐多个项目的系统(比如横幅广告)。
神经机器翻译
注意使用编码器解码器结构的神经机器翻译指南。包括在 Google Colaboratory 中使用 PyTorch 的详细教程。
Image from pixabay.com
机器翻译(MT)是计算语言学的一个分支,致力于将文本从一种语言翻译成另一种语言。随着深度学习的力量,神经机器翻译(NMT)已经成为执行这项任务的最强大的算法。虽然谷歌翻译是 NMT 领先的行业范例,但全球的科技公司都在向 NMT 进军。这种最先进的算法是深度学习的一种应用,其中翻译句子的大规模数据集用于训练一个能够在任何两种语言之间翻译的模型。随着近年来的大量研究,目前行业中正在研究和部署多种 NMT。编码器解码器结构是 NMT 的一个较老且较成熟的版本。这种体系结构由两个递归神经网络(RNNs)组成,这两个网络一前一后用于创建翻译模型。当与注意力机制的力量相结合时,这种架构可以取得令人印象深刻的结果。
这篇文章分为两个不同的部分。第一部分包括 NMT 和编码器解码器结构的简要说明。接下来,本文的后半部分提供了一个教程,让您有机会自己创建一个这样的结构。这段代码教程很大程度上基于关于 NMT 的 PyTorch 教程,并做了一些改进。最值得注意的是,这个代码教程可以在 GPU 上运行,以获得明显更好的结果。
在我们开始之前,假设如果你正在阅读这篇文章,你至少对神经网络和深度学习有一个大致的了解;特别是前向传播、损失函数和反向传播的概念,以及训练和测试集的重要性。
如果你有兴趣直接跳到代码,你可以在我的 GitHub 页面上找到本文概述的 Google Colab 教程的完整 Jupyter 笔记本(或者 Python 脚本)用于这个项目 。
NMT 及编解码结构简述
任何 NMT 模型的最终目标都是将一种语言的句子作为输入,并将翻译成不同语言的句子作为输出返回。下图是一个翻译算法(比如 Google Translate)的简单表示,它的任务是将英语翻译成西班牙语。
Figure 1: Translation from English to Spanish of the English sentence “the cat likes to eat pizza”
在深入研究上图中经常用作算法的编码器/解码器结构之前,我们首先必须了解如何克服任何机器翻译任务中的一大障碍。也就是说,我们需要一种方法来将句子转换成可以输入到机器学习模型中的数据格式。本质上,我们必须以某种方式将文本数据转换成数字形式。
为了在机器翻译中做到这一点,每个单词都被转换成一个热编码向量,然后该向量可以被输入到模型中。一个热点编码向量是除了在对应于特定单词的单个索引处为 1 之外,在每个索引处为 0 的简单向量。这样,每个单词都有一个不同的热编码向量,因此我们可以用数字表示来表示数据集中的每个单词。
创建这些向量的第一步是为输入语言中的每个唯一单词分配一个索引,然后对输出语言重复这个过程。在为每个独特的单词分配一个独特的索引时,我们将为每种语言创建一个词汇表。理想情况下,每种语言的词汇表应该简单地包含该语言中的每个独特的单词。然而,鉴于任何一种语言都可能有几十万个单词,因此词汇表通常会被删减为我们正在处理的数据集中最常见的 N 个单词(其中 N 是任意选择的,但根据数据集的大小,范围通常在 1,000 到 100,000 之间)。
为了理解我们如何使用词汇表为数据集中的每个单词创建一个热编码向量,考虑一个只包含下面表 1 中的单词的小型词汇表。
Table 1: Mini-vocabulary for the English language
给定这个表,我们给小词汇表中的每个单词分配了一个惟一的索引 0-12。表中的和标记被添加到每个词汇中,分别代表句子的开始和结束。它们被 NMT 模型用来帮助识别句子中的关键点。
现在,假设我们想要将句子“蓝鲸吃了红鱼”中的单词转换成它们的一个热编码向量。使用表 1,我们将这样做,如下图 2 所示。
Figure 2: One Hot Encoding vectors for the sentence “the blue whale ate the red fish”
正如您在上面看到的,每个单词都变成了一个长度为 13 的向量(这是我们的词汇量的大小),并且除了表 1 中分配给该单词的索引处的 1 之外,全部由 0 组成。
通过为输入和输出语言创建词汇表,我们可以在每种语言的每个句子上执行这种技术,以将任何翻译句子的语料库完全转换成适合机器翻译任务的格式。
现在,了解了我们如何用数字的方式表示文本数据,让我们看看这个编码器/解码器算法背后的魔力。在最基本的层面上,模型的编码器部分获取输入语言中的一个句子,并根据这个句子创建一个思维向量。这个思维向量存储了句子的意思,并随后被传递给解码器,该解码器以输出语言输出句子的翻译。这个过程如下图所示。
Figure 3: Encoder Decoder structure translating the English sentence “the cat likes to eat pizza” to the Spanish sentence “el gato le gusta comer pizza”
在上述架构中,编码器和解码器都是递归神经网络(RNN)。在这个特别的教程中,我们将使用长短期记忆(LSTM)模型,这是一种 RNN。然而,其他 RNN 架构,如 GRU,也经常使用。在基本层面上,rnn 是专门设计来处理时间/文本数据的神经网络。这篇文章将给出 RNNs 如何在 NMT 环境中工作的高级概述,但是,如果您还不熟悉它们,我强烈建议您进一步研究这些概念。关于 RNNs 和 lstm 的更全面的解释,请参见这里的,关于 lstm 在语言翻译方面的更深入的文章,请参见这里的。
在编码器的情况下,输入句子中的每个单词在多个连续的时间步骤中被分别输入到模型中。在每个时间步 t ,模型使用来自在该时间步*输入到模型的单词的信息更新隐藏向量 h ,。*这个隐藏向量用于存储关于输入句子的信息。以这种方式,由于在时间步 t= 0 还没有字被输入到编码器,编码器中的隐藏状态在该时间步作为空向量开始。我们用图 4 中的蓝框表示这种隐藏状态,其中下标 t =0 表示时间步长,上标 E 对应于编码器的隐藏状态(而不是解码器的 D)。
Figure 4: Encoder hidden vector at t=0
在每个时间步长,这个隐藏向量从该时间步长的输入单词中获取信息,同时保留它已经从先前的时间步长中存储的信息。因此,在最后的时间步,整个输入句子的含义被存储在隐藏向量中。这个在最后一个时间步长的隐藏向量就是上面提到的思想向量,然后输入到解码器中。对英语句子“猫喜欢吃比萨饼”进行编码的过程如图 5 所示。
Figure 5: Encoding of the sentence “the cat likes to eat pizza”
在上图中,蓝色箭头对应于权重矩阵,我们将努力通过训练来增强权重矩阵,以实现更准确的翻译。
此外,请注意编码器的最终隐藏状态如何成为思想向量,并在 t =0 处用上标 D 重新标记。这是因为编码器的这个最终隐藏向量变成了解码器的初始隐藏向量。通过这种方式,我们将句子的编码含义传递给解码器,由解码器翻译成输出语言的句子。然而,与编码器不同的是,我们需要解码器输出一个长度可变的翻译句子。因此,我们将让我们的解码器在每个时间步输出一个预测字,直到我们输出一个完整的句子。
为了开始这个翻译,我们将输入一个标签作为解码器中第一个时间步长的输入。就像在编码器中一样,解码器将在时间步长 t =1 时使用输入来更新其隐藏状态。然而,解码器将使用额外的权重矩阵来创建输出词汇表中所有单词的概率,而不是仅仅前进到下一个时间步。这样,输出词汇中概率最高的单词就会成为预测输出句子中的第一个单词。解码器的第一步,从“猫喜欢吃比萨饼”翻译成“el gato le gusta comer pizza ”,如图 6 所示。为了简单起见,输出词汇表仅限于输出句子中的单词(但实际上是由整个输出词汇表中的数千个单词组成)。
Figure 6: First step of the Decoder
现在,假设单词“el”被赋予最高的概率,这个单词成为我们输出的预测句子中的第一个单词。我们继续使用“el”作为下一个时间步的输入,如下图 7 所示。
Figure 7: Second step of the Decoder
我们以这种方式处理整个句子,直到遇到如图 8 所示的错误。
Figure 8: Translation error in Decoder
正如你所看到的,解码器预测“pizza”是翻译句子中的下一个单词,而实际上它应该是“comer”。当在测试集上测试模型时,我们不会做任何事情来纠正这个错误,并且会允许解码器使用这个不正确的预测作为下一时间步的输入。然而,在训练过程中,我们将保留“pizza”作为句子中该点的预测单词,但强制我们的解码器输入正确的单词“comer”作为下一时间步的输入。这是一种被称为教师强制的策略,有助于加快培训过程。如下图所示。
Figure 9: Teacher-forcing
现在,由于解码器必须输出可变长度的预测句子,解码器将继续以这种方式预测单词,直到它预测句子中的下一个单词是标签。一旦预测了这个标签,解码过程就完成了,我们剩下的是输入句子的完整预测翻译。对输入句子“猫喜欢吃比萨饼”的思想向量进行解码的整个过程如图 10 所示。
Figure 10: Decoding of the sentence “the cat likes to eat pizza”
然后,我们可以将预测翻译的准确性与输入句子的实际翻译进行比较,以计算损失。虽然有几种损失函数,但最常用的是交叉熵损失。该损失函数的公式详见图 11。
Figure 11: Cross-Entropy Loss function
本质上,这个损失函数所做的是对模型在输出句子的每个位置给予正确单词的负对数可能性求和。假设负对数函数在输入为 1 时的值为 0,并且随着输入接近 0 而呈指数增加(如图 12 所示),则模型在句子中的每个点给出正确单词的概率越接近 100%,损失就越低。
Figure 12: Graph of the function y = -log(x)
例如,假设上面输出句子中正确的第一个单词是“el”,并且我们的模型在该位置给出了单词“el”相当高的概率,则该位置的损失将相当低。相反,由于在时间步长 t =5 的正确单词是“comer”,但是我们的模型给单词“comer”的概率相当低,所以在该步骤的损失会相对较高。
通过对输出句子中每个单词的损失求和,获得句子的总损失。该损失对应于翻译的准确性,较低的损失值对应于较好的翻译。训练时,将一批中几个句子的损失值加在一起,得到总的一批损失。然后,该批量丢失将用于执行小批量梯度下降,以更新解码器和编码器中的所有权重矩阵。这些更新修改了权重矩阵,以略微提高模型翻译的准确性。因此,通过反复执行这个过程,我们最终构建了能够创建高质量翻译的权重矩阵。
如果您不熟悉批量和/或小批量梯度下降的概念,您可以在这里 找到这些概念的简短解释 。
正如在引言中提到的,注意机制是一个不可思议的工具,它极大地增强了 NMT 模型创建准确翻译的能力。虽然有许多不同类型的注意力机制,其中一些你可以在这里阅读,本教程中建立的模型使用了一个相当简单的全局注意力实现。在这种注意力方法中,在每个时间步,解码器“回顾”编码器的所有隐藏向量,以创建记忆向量。然后,它使用这个记忆向量,连同解码器中的隐藏向量,来预测翻译句子中的下一个单词。在这样做的时候,解码器利用了来自编码器的有价值的信息,否则这些信息会被浪费掉。这个过程的可视化表示如图 13 所示。我建议阅读本段中的链接文章,以了解更多关于计算内存向量的各种方法,从而更好地理解这一重要概念。
Figure 13: Attention mechanism for time-step t=1 in Decoder
注意:注意力机制非常强大,最近有人提出(并证明)当单独使用时(即没有任何 RNN 架构)会更有效。如果你对《NMT》感兴趣,我建议你去看看《变形金刚》,尤其是读读《》这篇文章。
编码教程(Python)
在开始本教程之前,我想重申一下,本教程主要来自 PyTorch 教程“序列到序列网络的翻译和注意”。然而,本教程在许多方面都进行了优化。最值得注意的是,该代码允许将数据分成批次(从而允许我们利用 GPU 的增强并行计算能力),可以将数据集分成训练集和测试集,并且还添加了在各种格式的数据集上运行的功能。
在我们深入学习代码教程之前,先做一点设置。如果你想在 GPU 上运行模型(强烈推荐),本教程将使用 Google Colab 提供免费使用具有 GPU 功能的 Jupyter 笔记本电脑的机会。如果你有其他方法来使用 GPU,那么也可以随意使用。否则,你可以看看其他各种免费的在线 GPU 选项。代码可以在 CPU 上运行,但是任何模型的能力都会受到计算能力的限制(如果您选择这样做,请确保将 batch-size 改为 1)。
要开始,导航到谷歌联合实验室并登录谷歌账户开始。从这里,导航到文件> New Python 3 Notebook 来启动 Jupyter 笔记本。打开新笔记本后,我们首先需要启用 GPU 功能。为此,导航至页面左上角,选择编辑>笔记本设置。从这里,在“硬件加速器”下的下拉菜单中选择 GPU
Figure 14: Enabling GPU capabilities on Google Colab
我们现在有了一个具有 GPU 功能的 Jupyter 笔记本,可以开始创建一个 NMT 模型了!首先,我们将导入所有必需的包。
现在,运行下面的代码来检查是否启用了 GPU 功能。
如果返回 TRUE,则 GPU 可用。现在,在我们开始做任何翻译之前,我们首先需要创建一些准备数据的函数。以下函数用于清理数据,并允许我们删除过长的句子或输入句子不是以特定单词开头的句子。
现在,使用将清理数据的函数,我们需要一种方法来将清理后的文本数据转换为一个热编码向量。首先,我们创建一个 Lang 类,它将允许我们为输入和输出语言构建一个词汇表。
接下来,我们创建一个 prepareLangs 函数,它将获取翻译句子的数据集,并为数据集的输入和输出语言创建 Lang 类。
这个函数能够处理包含在两个独立文件或一个文件中的输入和输出句子。如果句子在两个单独的文件中,每个句子必须用换行符隔开,并且文件中的每一行必须相互对应(即组成一个句子对)。例如,如果您的输入文件是 english.txt,输出文件是 espanol.txt,那么这些文件的格式应该如图 15 所示。
Figure 15: Format for dataset stored in two separate files.
另一方面,如果输入和输出句子存储在一个文件中,句子对中的每个句子必须用制表符分隔,每个句子对必须用换行符分隔。例如,如果您的单个文件名是 data.txt,那么该文件的格式应该如图 16 所示。
Figure 16: Format for dataset stored in one single file.
注意:为了使这个函数同时处理一个和两个文件,file_path 参数必须是元组格式,如果数据存储在两个文件中,则元组中有两个元素,如果数据存储在单个文件中,则元组中有一个元素。
使用一个为输入和输出语言准备语言词汇表的函数,我们可以使用上述所有函数来创建一个函数,该函数将获取输入和目标句子的数据集,并完成所有预处理步骤。因此, prepareData 函数将为每种语言创建 Lang 类,并根据指定的传递参数完全清理和修整数据。最后,这个函数将返回两个语言类,以及一组训练对和一组测试对。
虽然我们已经为每种语言创建了一个词汇表,但是我们仍然需要创建一些函数来使用这些词汇表将句子对转换成它们的 Hot 编码向量表示,或者将它们转换成它们的 Hot 编码向量表示。
NMT 与正常的机器学习没有什么不同,因为小批量梯度下降是训练模型最有效的方式。因此,在我们开始构建我们的模型之前,我们想要创建一个函数来 batchify 我们的句子对,以便我们可以对小批量执行梯度下降。我们还创建了函数 pad_batch 来批量处理变长句子的问题。这个函数本质上是将< EOS >标签附加到每个较短句子的末尾,直到批中的每个句子长度相同。
至此,我们已经创建了所有必要的函数来预处理数据,并最终准备好构建我们的编码器解码器模型!对编码器/解码器架构和注意力机制有了大致的了解后,让我们深入研究创建这些框架的 Python 代码。我不会解释编码器和解码器的每个方面,而是简单地提供代码,如果您对代码的各个方面有任何问题,请参考 PyTorch 文档。
现在,为了训练和测试模型,我们将使用以下函数。下面的 train_batch 函数对单个训练批次执行一次训练循环。这包括完成通过模型的正向传递以创建该批中每个句子的预测翻译,计算该批的总损失,然后对该损失进行反向传播以更新编码器和解码器中的所有权重矩阵。
train 函数只是对批次列表中的每个批次重复执行 train_batch 函数。这样,我们可以传递所有训练批次的列表,以通过训练数据完成一个完整的时期。
以下 test_batch 和 test 功能与 train_batch 和 train 功能基本相同,除了这些测试功能是对测试数据执行的,不包括反向传播步骤。因此,这些函数不更新模型中的权重矩阵,并且仅用于评估训练数据的损失(即,准确性)。反过来,这将帮助我们跟踪模型在训练集之外的数据上的表现。
在培训期间,能够以更定性的方式跟踪我们的进展也很好。 evaluate 函数将允许我们通过返回我们的模型对给定输入句子做出的预测翻译来这样做。并且evaluate _ random函数将简单地预测从测试集(如果我们有)或训练集中随机选择的指定数量的句子的翻译。
下面的几个助手函数将绘制我们的训练进度,打印内存消耗,并重新格式化时间测量。
最后,我们可以将所有这些函数放入一个主函数中,我们称之为 train_and_test 。该函数将采用相当多的参数,但是将完全训练我们的模型,同时以指定的间隔评估我们在训练集(和测试集,如果存在的话)上的进展。此外,一些参数将指定我们是否希望将输出保存在一个单独的。txt 文件,创建一个损失值随时间变化的图表,并允许我们保存编码器和解码器的权重以供将来使用。此函数后面的几个单元格将概述如何修改每个参数,但要知道,为了训练模型,我们基本上只需要运行此函数。
现在一切就绪,我们准备导入数据集,初始化所有的超参数,并开始训练!
首先,为了上传数据集,运行以下单元格:
您将看到以下内容:
Figure 17: Upload data to Google Colab
只需点击“选择文件”按钮,并导航到您希望上传的数据集。在本教程中,我们使用的数据集与原始 PyTorch 教程中使用的数据集相同。你可以在这里下载英法翻译数据集。你也可以用各种语言的其他数据集进行实验这里。
如果你想获得更多最新的结果,我建议你尝试在更大的数据集上训练。您可以在这里找到一些更大的数据集,但也可以随意使用任何翻译摘录的语料库,只要它们的格式类似于上面的图 15 或图 16。
注意:使用本教程中介绍的上传方法上传大型数据集到 Google Colab 可能会有问题。如果你遇到这样的问题,阅读 这篇文章 学习如何上传大文件。
现在,运行以下单元格以确保数据集已成功上传。
Figure 18: Run ls to ensure dataset has been uploaded
在这里,编辑以下单元格以应用于您的数据集和需求。
下面的单元格由各种超参数组成,为了找到一个有效的 NMT 模型,您需要使用这些超参数。所以,尽情体验这些吧。
最后,您只需要运行下面的单元,根据上面设置的所有超参数来训练您的模型。
瞧!你刚刚训练了一个 NMT 模特!恭喜你。如果保存了任何图形、输出文件或输出权重,可以通过再次运行 ls 来查看所有保存的文件。要下载这些文件,只需运行下面的代码。
现在,如果你想在训练集和测试集之外的句子上测试这个模型,你也可以这样做。只要确保你要翻译的句子和你的模型的输入语言是同一种语言。
我在 PyTorch 教程中使用的同一个数据集上训练我的模型和 PyTorch 教程模型(这是上面提到的英语到法语翻译的同一个数据集)。为了预处理数据,trim 设置为 10,PyTorch 使用的 eng_prefixes 过滤器设置为 TRUE。有了这些限制,数据集被削减到一个相当小的 10,853 个句子对的集合。PyTorch 教程打破了机器学习的一个基本规则,没有使用测试集(这不是好的实践!).因此,仅仅为了比较,我将所有这些句子对保存在我的训练集中,并且不使用测试集(即 perc_train_set = 1.0)。然而,我建议你在训练任何类型的机器学习模型时总是使用测试集。
表 1 显示了我为我的模型选择的超参数与 PyTorch 教程模型中的超参数的比较。图 19 中的下图描绘了在 NVIDIA GeForce GTX 1080 上训练 40 分钟的结果(有点旧的 GPU,使用 Google Colab 实际上可以获得更好的结果)。
Table 1: Hyperparameters comparison
Figure 19: Loss over 40 minute training period for this tutorial model (My Model) vs PyTorch Tutorial Model
由于这个数据集没有训练集,我用训练集中的几个句子评估了这个模型。
Figure 20: Predicted translation of PyTorch tutorial model (Blue) vs. My Model (Orange)
从这些结果中,我们可以看出,本教程中的模型可以在相同的训练时间内创建更有效的翻译模型。然而,当我们试图使用这个模型翻译训练集之外的句子时,它立即崩溃了。我们可以在模型对数据集之外的以下句子的尝试翻译中看到这一点。
Figure 21: Failed translation on sentence outside the dataset.
该模型的失败很大程度上是因为它是在如此小的数据集上训练的。此外,我们没有意识到这个问题,因为我们没有测试集来检查模型翻译训练集之外的句子的能力。为了解决这个问题,我在相同的数据集上重新训练了我的模型,这次使用了 trim=40,并且没有使用 eng_prefixes 过滤器。即使我留出 10%的句子对作为训练集,测试集的规模仍然是之前用于训练模型的 10 倍以上(122,251 个训练对)。我还将模型的隐藏大小从 440 修改为 1080,并将批量大小从 32 减少到 10。最后,我将初始学习率更改为 0.5,并安装了一个学习率时间表,该时间表在每五个时期后将学习率降低五分之一。
利用这个更大的数据集和更新的超参数,模型在相同的 GPU 上被训练。下面显示了训练和测试集在训练期间的损失,以及上面失败的相同句子的翻译。
Figure 22: Train and Test loss vs. time
Figure 23: Improved (yet still imperfect) translation of sentence outside of the dataset.
大家可以看到,这句话的翻译是有显著提高的。然而,为了实现完美的翻译,我们可能需要进一步增加数据集的大小。
结论
虽然本教程介绍了使用编码器和解码器结构的 NMT,但实现的注意机制相当基础。如果你对创建一个更先进的模型感兴趣,我建议你研究一下局部注意力的概念,并尝试在模型的解码器部分实现这种更高级的注意力。
否则,我希望你喜欢教程,并学到了很多东西!这篇文章所涉及的材料的基础来自我在罗耀拉玛丽蒙特大学的论文。如果你想看看我用来分享这些想法的 PPT 演示文稿(包括本文中的大部分图片),你可以在这里找到。你也可以阅读我写的关于这个主题的论文,它更深入地解释了 NMT 背后的数学,这里是。最后,这个项目的完整 Jupyter 笔记本可以在这里找到,或者 Python 脚本版本可以在这里找到。
神经网络
更简单直观的解释。
神经网络是用于学习复杂的复杂学习算法,通常是非线性机器学习模型。
A note on the notation. x_{i} means x subscript i and x_{^th} means x superscript th.
线性回归快速回顾
- 线性回归用于预测+∞和-∞之间任何地方的实值输出。
- 用于训练线性回归模型的每个示例由其属性或特征定义,这些属性或特征统称为特征向量。你的名字、年龄、联系电话、性别等等对应于描述你的特征向量。
- 一个线性回归模型 f(x) 、*、*是输入实例 x 的特征的线性组合,用 f(x) = wx+b 表示。
- 通过平方或立方来变换原始特征(考虑一维特征向量 x )会产生多项式模型(例如 f(x) = wx +b 或 f(x) = wx +b )。
- 通常对于具有 R 维特征向量 x 和一维输出 y 的数据集,线性回归建模一个超平面作为决策边界。超平面在 2D 区域的情况下是一条线,在 3D 空间的情况下是一个平面,在 4D 空间的情况下是一个三维形状,例如一个球体,等等。超平面比它们周围的空间少了一个维度。
- 均方误差成本函数用于找到线性回归模型的最佳值组 w* 和 b* 。
逻辑回归快速回顾
- 逻辑回归是一种分类算法。给定一个输入示例,逻辑回归模型将该示例分配给相关的类。
- 使用 sigmoid 函数在 0 和 1 之间处理从线性回归模型获得的实值输出,以获得逻辑回归模型。然后基于阈值对新的示例进行分类。
- 一个逻辑回归模型表示为f(x)= 1/(1+exp(-(wx+b))),其中 exp 为指数函数。
- 对数似然函数成本函数用于查找逻辑回归模型的最佳值组 w* 和 b* 。
- 就像线性回归一样,我们可以将特征转换为包含二次或三次项的更高阶,以使非线性决策边界适合我们的数据集。
构建模块——神经元
让我们来看看神经网络的构建模块。
Elementary unit of a neural network: A neuron
基本单元中发生的操作可以用下面的等式来表示—
Output from a single neuron.
让我们看看这个等式的各个组成部分,以及随之而来的神经元 —
- x_{i},i ∈ {1,2,…,n} 对应于馈入神经网络的输入特征向量,
- b 是偏置项,
- 对于每个输入特征 x_{i} ,都有一个对应的权重 w_{i},,这表示对应的输入 x_{i} 对输出的影响有多强。例如,考虑一个例子,在给定一个面的面积和立方体的颜色的情况下,计算立方体的总表面积。因为一个立方体有六个面,所以我们用一个面的面积乘以 6 来得到立方体的总表面积。然而,立方体的颜色对它的总表面积没有影响,所以我们把它乘以 0。这里 6 和 0 表示对应于输入特征的权重,一个面的面积和立方体的颜色。权重值越高,表示该要素对输出的影响越大。**
The idea behind weights.
- 请注意,神经元的输入是特征向量和附加偏差的线性组合。最后,该线性组合通过被称为激活函数的函数 f(x) 。
激活功能
在继续之前,让我们简单讨论一下激活函数。给定一个数据集,目标是找到适合我们数据集的最佳模型,或者我们可以说,在数据集的输入和输出之间逼近一个数学函数。事实证明,由于激活函数的存在,神经网络在逼近这些数学函数方面非常出色。就一会儿,想象一个没有任何激活函数的神经网络——它将只是一些线性回归模型。
像 sigmoid 这样的激活函数负责非线性转换,从而使神经网络能够学习复杂的假设。
在上面的等式中,如果你用 sigmoid 函数替换函数 f ,你将得到一个逻辑单元。常用的激活函数有 Sigmoid、ReLU 和 Tanh。
Activation functions : Left-to-Right: Rectified Linear Unit (ReLU), the Sigmoid function and the Tanh function.
神经网络
体系结构
神经网络基本上由三层组成——
- ***输入层:*它是一个被动层,也就是说它不执行任何计算,而是将其输入传播到后续层进行进一步处理。
- 隐藏层:这是实际计算发生的层。每个圆圈代表一个神经元。每个神经元接收来自前一层的输入,进行所需的计算,并将结果传播到下一层。在单个隐藏层的情况下,隐藏层从输入层接收输入,并将输出传播到输出层。然而,在多个隐藏层的情况下,一个隐藏层可以从前一个隐藏层接收其输入,并且可以将其输出传递给下一个隐藏层。
- ***输出层:*这是最后一层,给出我们想要的输出。在回归问题的输出层中有一个神经元,然而在分类问题的情况下存在多个神经元。
- ***箭头:*箭头代表神经网络的参数,称为权重。学习算法的工作是找到一组好的参数,以便神经网络能够很好地泛化。
培养
让我们为某个任意问题假设以下神经网络架构—
Neural Network Architecture
很明显,神经网络主要是由它的权重定义的。一旦找到最佳的权重集,网络就可以进行预测了。
训练过程从随机初始化权重开始,通常在 0 和 1 之间。随机初始化设施对称破坏。考虑一个例子,其中 w_{1 }、 w_{2 }、 w_{3 }和 w_{4 }被初始化为相同的权重值。这将导致 h_{1} 和 h_{2} 产生相同的输出,从而通过引入冗余来降低隐藏层中存在的神经元的可用性。
初始化权重后,接下来的步骤是将输入馈送到神经网络,并获得一些输出y’。这个步骤被称为正向传播。
显然,使用第一次向前传递获得的输出不是最准确的。诸如均方误差的误差函数可用于获取网络的成本。我们的目标是轻推神经网络的权重,以最小化这种误差。如果我们知道误差相对于权重如何变化,我们可以相应地更新权重以最小化误差。这就是反向传播方法派上用场的地方。它使用梯度下降,并决定网络的每个权重应该改变多少。
为简化起见,考虑以下函数—
上述函数对 x 的偏导数为 3 ,对 y 的偏导数为 1 。解释该结果的一种方式是,如果我们将 y 的值增加一个因子 k ,那么函数 f(x,y) 的值也会增加与∂ f(x,y)/ ∂ y = 1 相同的因子 k ,同样,如果我们将 x 的值减少一个因子 k`【也是如此因此,我们可以说一个函数对其变量的导数决定了该函数对该变量的敏感度。本质上,在神经网络的情况下,变量是网络的权重,并且 f(x,y) 对应于神经网络模型。
导数的这一特性有助于我们确定为了使误差最小化并从网络中获得所需的输出,可能需要轻推一个权重的量。
反向传播因以下事实而得名:首先计算输出层的误差,然后通过隐藏层反向传播,在此过程中计算导数。
*A detailed explanation of back-propagation is beyond the scope of this discussion as it can be overwhelming. However the following resource can be useful.*
*[## 反向传播演示
反向传播算法对于快速训练大型神经网络至关重要。这篇文章解释了如何…
google-developers.appspot.com](https://google-developers.appspot.com/machine-learning/crash-course/backprop-scroll/)*
对于分类问题
神经网络也可以用于分类问题。考虑将电子邮件标记为垃圾邮件或非垃圾邮件的二元分类的经典示例。为了使用神经网络来解决这个问题,输出类别被转换成二维向量,其中,如果电子邮件是垃圾邮件,则设置第一维度,如果电子邮件不是垃圾邮件,则设置第二维度。最后,输出的这种变换形式与输入特征向量一起用于训练神经网络。在 n-class 分类的情况下,每个输出被转换成一个 n 维向量,其中如果实例属于相应的类,则设置一个维。
Transformed output variable in case of a spam email.
Architecture of neural network as a classifier.
输出单元 y_{1} 预测电子邮件是垃圾邮件的可能性,而 y_{2} 预测电子邮件不是垃圾邮件的可能性。根据取较高值的输出单位对电子邮件进行分类。
为什么是新算法?
你一定已经学会了线性回归和逻辑回归,那么我们为什么需要训练一个神经网络呢?事实证明,神经网络非常擅长逼近非线性函数。
在我们对线性回归和逻辑回归的回顾中,我们讨论了包含更高次项来近似非线性假设,但是这样做并不能保证更好的假设。此外,假设将取决于我们对高次项的选择。考虑这样一种情况,我们有 10 个参数(比如 a,b,c,…,j),我们决定包括所有平方项,这样做将创建 55 个参数(10+9+8+…+1)。此外,过度拟合的可能性也更高。
神经网络解决了这个问题。观察神经网络的隐含层,隐含层的输入不是简单的原始输入 x_{1} 和 x_{2} ,而是权重,将隐含层的输入转换为原始输入的某个函数。好像神经网络试图找到输入的最佳可能转换,从而解决我们选择更高次项的问题。包括更多的隐藏层允许网络学习甚至更复杂的特征。然而,对于大多数实际用途,两个隐藏层工作得相当好。
神经网络算法—了解如何训练人工神经网络
Neural Network Algorithms — Learn How To Train ANN
顶级神经网络算法
神经网络的学习是基于被研究群体的样本进行的。在学习过程中,将输出装置输出的值与实际值进行比较。之后,调整所有单元的权重,以改善预测。
有许多神经网络算法可用于训练人工神经网络。现在让我们来看看训练神经网络的一些重要算法:
- 梯度下降-用于查找函数的局部最小值。
- 进化算法——基于生物学中自然选择或适者生存的概念。
- 遗传算法——为问题的解决启用最合适的规则,并选择它。所以,他们把他们的‘遗传物质’送给‘孩子’规则。我们将在下面详细了解它们。
获取神经网络学习规则介绍了解更多神经网络算法。
梯度下降
我们使用梯度下降算法来寻找函数的局部最小值。神经网络算法收敛到局部最小值。与函数梯度的负值成正比。为了找到局部最大值,采取与函数的正梯度成比例的步骤。这是一个梯度上升的过程。
在线性模型中,误差曲面是定义明确且众所周知的抛物线形状的数学对象。然后通过计算找到最小点。与线性模型不同,神经网络是复杂的非线性模型。在这里,误差表面具有不规则的布局,丘陵、山谷、高原和深谷纵横交错。为了找到这个表面上的最后一个点,没有可用的地图,用户必须探索它。
在这种神经网络算法中,沿着斜率最大的线在误差面上移动。它还提供了达到最低点的可能性。然后你必须计算出你应该以什么样的最佳速度下坡。
正确的速度与表面的斜率和学习率成正比。学习速率控制学习过程中权重的修改程度。
因此,神经网络的矩会影响多层感知器的性能。
进化算法
这种算法基于生物学中自然选择或适者生存的概念。自然选择的概念表明,对于一个给定的种群来说,环境条件使用了一种压力,这种压力导致该种群中最适者的上升。
要测量给定群体中的适者,您可以应用一个函数作为抽象的度量。
在进化算法的上下文中,将重组称为操作符。然后将它应用于两个或更多的候选项(称为父项),并产生一个或多个新的候选项(称为子项)。对单个候选项应用变异,并产生新的候选项。通过应用重组和变异,我们可以得到一组新的候选者,并根据它们的最适度量值将其放入下一代。
神经网络中进化算法的两个基本要素是:
- 变异算子(重组和变异)
- 选择过程(优胜劣汰)
进化算法的共同特征是:
- 进化算法是基于种群的。
- 进化算法使用群体的重组混合候选者,并创建新的候选者。
- 基于随机选择进化算法的研究。
因此,在细节和应用问题的基础上,我们使用各种形式的进化算法。
一些常见的进化算法有:
- 遗传算法遗传算法——它为优化问题提供解决方案。它在自然进化过程的帮助下提供了解决方案。比如突变、重组、交叉和遗传。
- 遗传编程——遗传编程以计算机程序的形式提供了一种解决方案。由解决计算问题的能力来衡量程序的准确性。
- 进化编程——在模拟环境中开发我们使用的人工智能。
- 进化策略它是一种优化算法。基于生物科学中适应和进化的概念。
- 神经进化——为了训练神经网络,我们使用神经进化。通过指定基因组用来开发神经网络的结构和连接权重。
在所有这些神经网络算法中,遗传算法是最常见的进化算法。
遗传算法
遗传算法,由霍兰德的团队在 20 世纪 70 年代早期开发。它能够选择最合适的规则来解决问题。以便它们将它们的“遗传物质”(它们的变量和类别)发送给“子”规则。
这里指的是一组变量的类别。例如,年龄在 36 至 50 岁之间,金融资产不到 2 万美元,月收入超过 2000 美元的客户。
规则相当于决策树的一个分支;它也类似于基因。你可以将基因理解为细胞内控制生物体如何继承其父母特征的单位。因此,遗传算法旨在复制自然选择的机制。通过选择最适合预测的规则,并通过交叉和变异它们,直到获得预测模型。
它们与神经网络一起构成了第二类算法。它模仿自然机制来解释不一定是自然的现象。执行遗传算法的步骤是:
- 步骤 1:随机生成初始规则——首先生成规则,约束条件是它们必须完全不同。每个规则包含用户选择的随机数量的变量。
- 步骤 2:最佳规则的选择——通过适应度函数针对目标检查规则,以引导向最佳规则的进化。最佳规则使适应度函数最大化,并且随着规则的改进概率增加而保留。有些规则会消失,而其他规则会选择几次。
- 第三步:通过变异或交叉生成新规则——首先,转到第二步,直到算法的执行停止。选择的规则被随机变异或交叉。突变是用一个变量或一个类别替换一个原始规则。
两个规则的交叉是它们的一些变量或类别的交换,以产生两个新的规则。杂交比突变更常见。
当满足以下两个条件之一时,神经网络算法结束:
- 达到的指定迭代次数。
- 从第 n 代开始,第 n 代、第 n-1 代和第 n-2 代的规则(几乎)相同。
所以,这都是关于神经网络算法的。希望你喜欢我们的解释。
结论
因此,人工神经网络通常难以配置并且训练缓慢,但是一旦准备好,在应用中速度非常快。它们通常被设计成模型来克服数学、计算和工程问题。因为,在数学、神经生物学和计算机科学方面有很多研究。
如果你想分享你的观点,或者对人工神经网络算法有任何疑问,请在评论区提出。
我也推荐你看我以前的文章-
用常微分方程重温神经网络反向传播
通过使用微分方程的数值解来优化神经网络参数被评论为在反向传播期间收敛到成本函数的全局最小值的替代方法。
Different optimizers at work to find the global minimum of two different functions. The “ODE Solver” optimizer will be the subject of this post. If you focus on the white dot, you can see that the ODE solver reaches the minimum with fewer iterations in the two cases shown here. The animation on the left is the six-hump camel function with a global minimum at (0,0). The animation on the right is the Goldstein-Price function where the global minimum at (0,-1) is only slightly deeper than the many other local minima. The animations have been created by adapting the code by Piotr Skalski. The code to reproduce the animation above can be found here.
这篇文章的重点是介绍一种不同的方法来优化神经网络的参数(又名权重),同时在训练过程中反向传播损失梯度。核心思想是使用常微分方程(ODE)数值解算器来寻找最小化梯度的权重。这个想法是由亚伦·敖文思等人在 1989 年首次提出的。虽然使用数值解算器增加了大量的计算时间,但是这种方法对于相对较小的数据集和/或收敛到稳定解需要额外努力来微调更“标准”优化器的超参数的情况是有意义的。事实上,数值求解器不需要任何超参数来调整。
最近,在神经网络建模中使用 ODE 求解器已经被用来重新设计深度学习可以对健康变化等连续过程进行建模的方式(见此处)。
在介绍了神经网络之后,我将描述如何对反向传播步骤进行更改,以便使用 ODE 解算器和标准优化器在 TensorFlow 中训练神经网络。
神经网络基础。
神经网络是生物启发的数学模型,可以在计算机上编程,以发现和学习观察数据中的复杂关系。关于神经网络背后的数学的详细回顾,读者可以参考迈克尔·尼尔森的在线书籍。节点的输入层和输出层分别表示特征和结果。一个或多个中间层(称为隐藏层)的序列通常用于捕获初始输入特征的越来越复杂的表示。
An example representation of neural network architecture with two input nodes and a single output node created with the VisualizeNN module. Other online tools exist to create publication-ready images (see for example NN-SVG).
利用这种架构进行学习的基本概念是可调权重,其被表示为网络节点之间的连接线。神经网络也被称为多层感知器网络(MLP),因为中间层充当感知器,即传递来自前一层的传入值或阻止它的本地分类器。
神经网络的训练包括两个阶段,前向和反向传播,这两个阶段重复几次,称为时期。在前向传播过程中,输入数据呈现给网络,并通过其各层进行转换。在任何给定的层 *l,*从前一层𝑙−1 扇出的输入值𝐴使用将层𝑙−1 连接到𝑙的权重( W )和层𝑙的偏置( b )进行线性变换,如下
𝑍是𝑙.图层节点处的值的向量使用如下激活函数将非线性变换应用于𝑍
在反向传播期间,为每一层𝑙.计算成本𝐶相对于网络权重的梯度对于𝑙层来说,
在哪里
知道这些等式就足以使用 *numpy 从头开始编写神经网络程序。*要查看,可以参考 Piotr Skalski 写的代码,并在他关于介质的文章中查看。
用 sklearn 训练 MLP 网络。
在 sklearn 中,可以使用任何监督机器学习技术中使用的典型步骤来训练神经网络模型。为了简单起见,我在下面的代码片段中使用了异或(XOR)真值表。
带 ODE 解算器的张量流。
常微分方程(ODE)可以用数值方法求解。事实上,前一节介绍的反向传播方程可以写成
并且是可以用数字求解的颂歌。在大多数情况下,这种 ODE 在数值上是严格的,也就是说,在积分过程中,通过不稳定性收敛到最优解。
刚性常微分方程的解要求积分器的步长非常小,并且可以随时间变化。在 Python 中, ODE 解算器在 scipy 库中实现。为了使用 ODE 积分器找到最佳权重,我们将变量 t 引入反向传播方程,这对应于改变积分器的步长以达到稳定的数值解。因此,我们将使用下面的等式
本节末尾的笔记本更详细地解释了为了用 ODE 求解器优化张量流神经网络而进行的修改。为此,我们需要在“渴望”模式下运行 TensorFlow,如这里的所示。对于这个练习,我从 MNIST 数据集中提取了两个随机样本,其中一个用于训练,另一个用于验证,即调整网络参数。两个样本都包含 0 到 4 之间的数字的数据,每个数字用 100 个样本来表示。当在 50 次迭代之后没有观察到大于 5%的改进时,停止训练,因为在验证集上有最佳性能。该模型的最终性能是根据数字 0-4 的全部 MNIST 数据(35,000 个样本)计算的,如下所示。
Accuracy of the TensorFlow neural network model on the whole datasets of digits between 0 and 4. (Left) Fewer iterations or presentations of the data to the network are needed to reach optimal performance. (Right) The use of a ODE solver requires significantly greater computation time.
用 ODE 求解器优化神经网络比用标准优化器优化要多花 8 倍的时间。然而,ODE 求解器的精度并不比其他优化器的精度差。
结论。
使用常微分方程(ODE)数值解算器已被视为优化神经网络参数的替代方法。虽然这显著增加了训练神经网络模型的计算时间,但是它不需要任何超参数调整,并且可以成为收敛到成本函数全局最小值而不花费时间微调超参数的替代方式。
基于神经网络的破解大型异或运算的攻击方法
XOR-puf 的漏洞向安全应用程序开发人员揭示了有价值的信息,用于决定为了安全风险而避免哪些 puf。
目标
在本文中,我们将讨论对具有五个或更多仲裁器 puf 组件的大型 XOR PUFs 的基于神经网络的攻击的实现。这篇文章展示了基于神经网络的攻击方法如何能够以高精度,在比其他快速机器学习算法少得多的时间内,甚至破解大型 XOR puf(,即处理可能大于存储容量的训练数据集。
我们将使用 keras 预测来自 k -XOR 仲裁器 PUFs 与 n 位挑战输入的最终输出响应。
在直接进入实现之前,让我们先来看一些关键概念,以便更好地理解正在发生的事情。
你说的 PUFs 是什么意思?
PUF(物理不可克隆功能)是一种物理实体,它利用半导体制造过程中自然发生的变化来为半导体器件提供唯一的身份,这使得不同的半导体器件不可克隆并且是唯一的。PUF 有望为资源受限的物联网设备提供高安全性。如今,puf 通常在集成电路中实现,并且通常用于具有高安全性要求的应用中。
Fig : 1
如上图 1 所示,PUF 是一个输入-输出映射,其中输入是 n 位二进制向量(称为挑战),输出是 m 位二进制向量(称为响应)。
为什么我们需要 puf?
在物联网设备中,确保通信安全至关重要。身份认证是保护物联网设备之间通信的方法之一。 经典认证方法 大多依靠密码算法来处理存储在非易失性存储器中的密钥。这些经典的认证技术有其局限性,这促使 puf 出现。让我们讨论一些限制:-
- 先前存储在数字非易失性存储器(例如 EEPROM、SRAM)中的密码密钥容易受到不同类型的攻击(例如入侵攻击和旁道攻击)。
- 由于这种计算昂贵的加密算法使用非易失性存储器,并且需要更多的制造成本以及更多的功耗等。
因此,puf 被广泛用于认证和密码密钥生成的目的,并且 puf 不是将秘密存储在数字存储器中,而是从集成电路(ic)的物理特性中导出秘密。
让我们现在来理解异或仲裁者 PUF
XOR 仲裁器 puf(也称为 XOR PUFs)由多个仲裁器 puf 构成。首先,我们需要了解仲裁器 PUFs,它测量两条对称路径之间的时间延迟差。如图 2 所示,aribter PUFs 接受输入信号和 n 位挑战,产生单一输出(称为响应)。输入信号根据挑战输入决定其路径,因为它允许输入信号为挑战位的每一位决定每个单独多路复用器中的路径。
Fig-2 : Arbiter PUF circuit.
在图 2 中,仲裁器 PUF 电路为每个输入 X 创建两条具有相同布局长度的延迟路径,并基于哪条路径更快产生输出 Y。
现在在图 3 中,来自 k 仲裁器 puf 的不同响应被一起异或以产生单个和最终响应 r ,其中所有的单个仲裁器 puf 使用相同的 n 位挑战作为挑战输入,这种 k 仲裁器 puf 与 XOR 的组合构成了 k -XOR 仲裁器 puf。
Fig-3 : k-XOR Arbiter PUFs.
理解了与 XOR 仲裁器 puf 相关的所有关键概念后,让我们继续实现。
数据集概述
从 k-XOR 仲裁器 PUFs 模拟中生成了两个数据集:
- 5-XOR _ 128 位数据集:该数据集使用 128 位级或 128 位挑战输入的 5-XOR 仲裁器 PUF 生成。它由 6 百万行和 129 个属性组成,其中最后一个属性是类标签或最终响应(1 或-1)。分为两组:训练组(500 万)和测试组(100 万)。
- 6-XOR _ 64 位数据集:该数据集使用 6-XOR 仲裁器 puf 生成,具有 64 位级或 64 位挑战输入。它由 240 万行和 65 个属性组成,其中最后一个属性是类标签或最终响应(1 或-1)。分为两组:训练集(200 万)和测试集(400K)。
我们可以用神经网络和不同的机器学习算法来实现这两个数据集。两个数据集都是平衡的或者包含相等比例的类。
我们可以从 这里 访问数据集。
Fig-4 : Balanced Dataset (6-XOR_64bit).
对 k-XOR 仲裁器 PUFs 的神经网络攻击
实施不同的机器学习算法,如逻辑回归(或 LR 与 Rprop)可以揭示 XOR 仲裁器 puf 中的漏洞,如建议的 此处 。但是,在高性能计算服务器上,这可能需要几天的并行计算时间来破解如此大的 XOR PUFs。由于神经网络是监督学习的最强大的方法之一,这就是为什么特别是,我试图实现多层感知器之一,非常有效地打破它,正如在这篇 论文 中所建议的。我们将在 keras 中实现与 论文 中建议的相同的 MLPs 架构和参数,并将观察准确性,即我们在破解 XOR 仲裁 puf 时的准确性。
Fig-5 : List of all parameters of MLPs and their implementation.
代码片段:
一些代码片段有助于您理解使用 keras 来破解具有 n 位挑战输入的 XOR 仲裁器 puf 的 MLPs 的实现。
- 对于 5-XOR _ 128 位数据集(仅考虑 100 万):
input_layer = Input(shape = (128,))out1 = Dense(32,activation = 'relu')(input_layer)
out1 = Dropout(0.5)(out1)
out1 = BatchNormalization()(out1)out2 = Dense(32,activation = 'relu')(input_layer)
out2 = Dropout(0.5)(out2)
out2 = BatchNormalization()(out2)out3 = Dense(32,activation = 'relu')(input_layer)
out3 = Dropout(0.5)(out3)
out3 = BatchNormalization()(out3)merge = concatenate([out1,out2,out3])output = Dense(2,activation = 'sigmoid')(merge)model = Model(inputs=input_layer, outputs=output)
# summarize layers
print(model.summary())# plot graph
plot_model(model, to_file='MODEL.png')adam = optimizers.Adam(lr = 0.001)
model.compile(loss='binary_crossentropy', optimizer = adam, metrics=['accuracy'])
2.6-XOR _ 64 位数据集:
input_layer = Input(shape = (64,))out1 = Dense(64,activation = 'relu')(input_layer)
out1 = Dropout(0.5)(out1)
out1 = BatchNormalization()(out1)out2 = Dense(64,activation = 'relu')(input_layer)
out2 = Dropout(0.5)(out2)
out2 = BatchNormalization()(out2)out3 = Dense(64,activation = 'relu')(input_layer)
out3 = Dropout(0.5)(out3)
out3 = BatchNormalization()(out3)merge = concatenate([out1,out2,out3])output = Dense(2,activation = 'sigmoid')(merge)model = Model(inputs=input_layer, outputs=output)
# summarize layers
print(model.summary())# plot graph
plot_model(model, to_file='MODEL.png')adam = optimizers.Adam(lr = 0.001)
model.compile(loss='binary_crossentropy', optimizer = adam, metrics=['accuracy'])
正如我们所见,图 5 考虑了两个数据集的隐藏层数和其他参数,如激活函数和优化器。
结果
在 keras 中实现神经网络后,结果(如图 6 所示)非常好。
Fig-6
在这里,我们许多人可能认为结果是过度拟合的,但事实并非如此,因为当我们考虑实现的一些数据点时,我们可以预期这种结果。
结论
如果你已经到达这里,非常感谢:)。
安全方面最重要的工作是发现或发现所有可能的不安全风险。如果在任何 puf 中发现任何不安全的风险或漏洞,可能会提醒 puf 设计者提出新的 puf,以便他们可以克服这些现有的漏洞。puf 中的漏洞还可以帮助基于 puf 的设备的物联网设备开发人员避免这些 puf。最后,我们能够使用基于神经网络的攻击来发现 XOR 仲裁器 puf 中的漏洞。MLPs 帮助我们用 XOR 仲裁器 puf(即 论文 )的大容量数据集,比其他任何匹配学习算法更快地实现了漏洞。
请参考我的 GitHub 链接 这里 访问 Jupyter 笔记本上写的完整代码。
特别感谢 Srikanth Varma Chekuri 和 AppliedAICourse 团队帮助我在机器学习和深度学习领域学到了这么多东西。
参考
- https://www . semantic scholar . org/paper/A-Machine-Learning-Based-Security-Vulnerability-on-Aseeri-Zhuang/c77f 42238 e 6098000 C7 add 21d 517 c7ff 0676 f 54 f
- https://dl.acm.org/citation.cfm?id=1866335
- https://machine learning mastery . com/keras-functional-API-deep-learning/
- https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=6823677
- https://www.appliedaicourse.com/
PS: 如果你认为可以改进这个博客,我一定会考虑的。
神经网络解释了地震破裂的物理现象
地震破裂动力学的机器学习方法
地震造成的破坏对全世界的人类构成了威胁。为了估计这种危险,科学家们使用不同地点的地震仪记录的历史地震数据和地面运动。然而,目前的方法大多是经验性的,由于缺乏历史地质数据,可能无法捕捉未来大地震中地面震动的全部范围。这导致了危险估计的重大不确定性。不仅如此,由于缺乏足够的历史数据,科学家们大多依赖模拟数据,计算量很大。
在本文中,我将解释使用机器学习预测地震是否会破坏断层的工作流。这个项目是我在孟菲斯大学地震研究和信息中心(CERI)的博士论文的一部分。 Eric.G .涂抹也是这篇论文的合著者,他监督了我和这个项目。最近我们提交了关于 Arxiv 的论文:【https://arxiv.org/abs/1906.06250。
在本文的剩余部分,我将讨论机器学习算法在预测真实地表断层破裂和估计地震危险方面的潜力。我也将解释有助于揭示地震破裂过程的复杂模式
地震破裂域
Figure-1: Rupture domain
我们制作了一组 2,000 个不同断层几何形状(高度和宽度)和材料特性(平面外应力、平面内应力、剪切应力、摩擦下降、动态摩擦系数)的破裂模拟,如图 1 所示。我们使用了 Eric 开发的开源数值模拟代码 fdfault 。该区域长 32 公里,宽 24 公里,横跨断层。该图显示了断层的放大视图,以便更好地观察障碍物。地震在离弯曲的几何障碍 10 公里的成核区(红色)开始。根据断层的几何形状和性质,有些地震能够穿过断层,有些则不能。为了简单起见,我们把它变成一个二元分类问题。更多的细节可以在报纸上找到。
Earthquake rupture propagation along the fault
上面的例子是地震无法突破断层的地震破裂停止之一。断裂止于断层的向上弯曲处。用 4 个 CPU 运行这个模拟大约花了 3.5 个小时。我们开发的 ML 可以在几分之一秒内预测这种地震破裂状态。让我们深入 ML 模型的细节和它们的能力。
浅层神经网络
我们使用随机森林和神经网络开发了两个预测模型。在本文中,我只关注神经网络算法。更具体地说,对所学参数的解释帮助我们揭示了地震破裂过程的机制。
Figure-2: Schematic diagram of the neural network topology used in the work
上面的图-2 说明了我们在这项工作中使用的神经网络拓扑的示意图。网络有一个 12 单元的隐层。八个输入参数被映射到这 12 个单元,为模型产生 12×8 的权重矩阵。当每个输入进入一个单元时,前一个单元的输出乘以其权重。然后,该单元将所有这些新输入相加,从而确定中间单元的输出值。然后,我们将非线性激活函数 ReLu 应用于输出权重,它传递所有大于零的值,并将任何负输出设置为零。最后,隐藏层将 12 个输出与输出层合并,并使用结果权重进行预测。
解释模型参数并获得物理特性
Figure-3: The parameters learned by the NN.
神经网络学习到的权重使我们能够对最能预测破裂传播能力的输入参数组合有所了解。为了可视化权重,我们构建了权重对神经单元矩阵图。这如图 2 所示。左侧面板显示了将八个输入(水平)映射到十二个隐藏单元(垂直)的模型权重。右侧面板显示了将隐藏单元合并为右侧一个输出单元的权重。色标表示重量的范围。模型中的权重范围从负值到正值,表示抑制性或兴奋性影响。
如果特定单元的输出图层权重为正,则参数组合是破裂传播的良好预测值,而负权重表示参数组合是破裂停止的良好预测值。类似地,将输入映射到作为正指示器的隐藏单元的权重表示该输入单元的大值有利于破裂。如果输出单元具有负权重,则隐藏单元的大权重表示该参数的大值预示着停滞。权重提供了对哪些参数组合最能预测破裂的洞察。
Table-1: Five parameter combinations and their corresponding possible predictions
图 2 所示的参数提供了对参数组合及其对确定破裂传播的影响的深入了解。比如 unit-4 负输出权重大。该单元的剪切应力、摩擦下降和滑移弱化距离具有较大的负权重,而高度、半宽度、op、ip 正应力、动摩擦系数和摩擦下降具有正权重。这表明,如果断层具有低剪切应力和低摩擦降,但具有高压缩 op、IP 正应力、高动态摩擦系数、高度和半宽度,则断裂可能不会传播而是停止。
另一方面,单元-8 具有相当大的正输出权重。OP、IP 法向摩擦系数和动态摩擦系数具有大的负权重,而摩擦下降、滑移弱化距离和剪切应力具有高的正权重。请注意,这些基本上是与 unit-4 中的值相反的值,表明数据中存在单一的潜在模式。因此,基于输入数据,模型已经精确地确定了如何以更复杂的方式最佳地组合各种输入参数。表-1 列出了参数组合和相应的预测。
学习参数的稳健性
Figure-4: The illustration shows the coefficient of determination (R2 score) among the weights learned by fifteen neural network models
我们证实,通过重复拟合过程,由 ANN 方法找到的参数组合是稳健的。我们开发了另外 15 个神经网络模型,具有相同的训练数据集,但不同的初始权重,以观察模型是否找到预测破裂的相同特征。模型的平均检验准确率为 83%。尽管不同模型的最终权重略有不同,但根据输出权重按升序排序时,它们表现出高度的相关性。图 4 显示了模型学习的参数(升序)中系数(R2 分数)的确定。模型 11 与另一个模型的相关性最小,而模型 10 和 12 的相关性较高。尽管模型 11 与模型 1 的相关系数最低,为 0.71,但它足够高,仍然包含与其他模型相似的模式。高度相关的权重表明,不管模型初始化的随机方式如何,模型都选取一致的特征。
想要在你的领域找到对机器学习和图论感兴趣的人吗?
我将通过分享关于 xoolooloo 的有趣信息来结束这篇文章。它是一个基于位置的搜索引擎,利用相似和多重兴趣寻找当地人。例如,如果你读了这篇文章,你肯定对数据科学、图论、机器学习感兴趣。因此,你可以在你的地区找到有这些兴趣的人;去 www.xoolooloo.com看看
结论
在计算上,这些模型是非常高效的。一旦计算了训练模拟,并且训练了机器学习算法,模型可以在几分之一秒内做出预测。这有可能将动态破裂模拟的结果纳入其他复杂的计算中,如反演或概率地震危险分析,这通常是不可能的。
该方法还可以应用于其他复杂的破裂问题,如分支断层、断层跨越和其他复杂的非均质性,其中地震破裂传播的物理特性尚未完全了解。机器学习提供了一种处理这种复杂的非线性问题的新方法,并帮助科学家理解潜在的地球物理参数如何与产生的滑动和地面运动相关,从而帮助我们限制未来的地震危害和风险。
非常感谢您的阅读。我希望你喜欢整个系列。完整的代码和相关数据可以在 Github 上找到。论文的细节可以在 Arxiv:https://arxiv.org/abs/1906.06250上找到。
我很想收到你的来信。你可以联系我:
Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)
Python 中张量流用于卫星数据分类的神经网络
Landsat 5 多光谱数据分类的逐步指南
深度学习已经接管了解决复杂问题的大多数领域,地理空间领域也不例外。这篇文章的标题让你感兴趣,因此,我希望你熟悉卫星数据集;目前,Landsat 5 TM。关于机器学习(ML)算法如何工作的小知识,将帮助你快速掌握这个动手教程。对于那些不熟悉 ML 概念的人来说,简而言之,它是在一个实体的一些特征(特征或 x)与其其他属性(值或标签或 Y)之间建立关系——我们为模型提供了大量的示例(带标签的数据),以便它从中学习,然后预测新数据(未标记的数据)的值/标签。机器学习的理论复习到此为止!
卫星数据的一般问题:
卫星数据中的两个或更多要素类(例如,建筑物/荒地/采石场)可能具有相似的光谱值,这使得分类在过去几十年中成为一项具有挑战性的任务。由于上述问题,传统的监督和非监督方法不能成为完美的分类器,尽管它们稳健地执行分类。但是,总是有相关的问题。让我们通过下面的例子来理解这一点:
在上图中,如果您使用一条垂直线作为分类器,并且只沿着 x 轴移动它,使其将右边的所有图像分类为房屋,那么答案可能不是直截了当的。这是因为数据的分布是这样的,不可能用一条垂直线将它们分开。但是,这并不代表房子完全不能分类!
假设您使用红线(如上图所示)来分隔这两个特征。在这种情况下,分类器识别出了大多数房屋,但仍有一所房屋被遗漏,一棵树被错误分类为房屋。为了确保没有一所房子被落下,你可以使用蓝线。在这种情况下,分类器将覆盖所有的房子;这叫做高召回。然而,并不是所有的分类图像都是真正的房屋,这被称为低精度。同样,如果我们用绿线,所有归类为房屋的图像都是房屋;因此,该分类器具有较高的精度。在这种情况下,召回的次数会少一些,因为还有三所房子没有被召回。在大多数情况下,精确度和召回率之间的这种权衡成立。
上面展示的房屋和树木问题类似于建筑、采石场和荒地的情况。卫星数据的分类优先顺序可能因目的而异。例如,如果您希望确保所有堆积像元都被分类为堆积像元,一个也不留,并且您不太关心具有相似特征的其他类的像素被分类为堆积像元,则需要具有高召回率的模型。相反,如果优先级是只对纯堆积像素进行分类,而不包括任何其他类别的像素,并且您可以放弃混合堆积像素,则需要高精度分类器。通用模型将在房子和树的情况下使用红线,以保持精确度和召回率之间的平衡。
当前范围内使用的数据
这里,我们将把 Landsat 5 TM 的六个波段(波段 2 —波段 7)作为特征,并尝试预测二元组合类。2011 年为班加罗尔获取的多光谱 Landsat 5 数据及其相应的二元组合层将用于培训和测试。最后,2011 年为海得拉巴获取的另一个多光谱 Landsat 5 数据将用于新的预测。要了解更多关于如何为模型创建训练数据,你可以查看这个视频。
由于我们使用带标签的数据来训练模型,这是一种受监督的 ML 方法。
Multispectral training data and its corresponding binary built-up layer
我们将使用谷歌在 Python 中的 Tensorflow 库来构建一个神经网络(NN)。将需要以下其他库,请确保您提前安装它们(查看此视频了解安装说明):
- pyrsgis —读写 GeoTIFF
- sci kit-learn—用于数据预处理和准确性检查
- numpy —用于基本数组操作
- Tensorflow —建立神经网络模型
不再拖延,让我们开始编码吧。
将所有三个文件放在一个目录中—在脚本中指定路径和输入文件名,并读取 GeoTIFF 文件。
pyrsgis 包的栅格模块分别读取 GeoTIFF 的地理位置信息和数字编号(DN)值作为 NumPy 数组。有关这方面的详细信息,请参阅 pyrsgis 页面。
让我们打印出已读取数据的大小。
输出:
*Bangalore multispectral image shape: 6, 2054, 2044
Bangalore binary built-up image shape: 2054, 2044
Hyderabad multispectral image shape: 6, 1318, 1056*
从输出可以明显看出,班加罗尔图像中的行数和列数是相同的,多光谱图像中的层数也是相同的。该模型将学习根据所有波段的相应 DN 值来决定像素是否是累积的,因此,两个多光谱图像应该具有以相同顺序堆叠的相同数量的特征(波段)。
我们现在将把数组的形状改为二维数组,这是大多数 ML 算法所期望的,其中每行代表一个像素。 pyrsgis 包的 convert 模块将为我们完成这项工作。
Schemata of restructuring of data
输出:
*Bangalore multispectral image shape: 4198376, 6
Bangalore binary built-up image shape: 4198376
Hyderabad multispectral image shape: 1391808, 6*
在上面代码片段的第七行,我们提取了所有值为 1 的像素。这是一个自动防故障装置,可以避免由于 NoData 像素通常具有极高和极低的值而导致的问题。
现在,我们将拆分数据进行训练和验证。这样做是为了确保模型没有看到测试数据,并且在新数据上表现得同样好。否则,模型将过拟合,并且仅在训练数据上表现良好。
输出:
*(2519025, 6)
(2519025,)
(1679351, 6)
(1679351,)*
上面代码片段中的 test_size (0.4)表示训练-测试比例是 60/40。
包括神经网络在内的许多 ML 算法期望标准化的数据。这意味着直方图在某个范围内(这里是 0 到 1)被拉伸和缩放。我们将正常化我们的功能,以满足这一要求。归一化可以通过减去最小值并除以范围来实现。由于 Landsat 数据是 8 位数据,因此最小值和最大值分别为 0 和 255 (2⁸ = 256 个值)。
请注意,从数据中计算最小值和最大值进行标准化始终是一个好的做法。为了避免复杂性,我们将坚持使用默认的 8 位数据。
另一个附加的预处理步骤是将特征从二维重新整形为三维,使得每行代表一个单独的像素。
输出:
*(2519025, 1, 6) (1679351, 1, 6) (1391808, 1, 6)*
现在一切就绪,让我们使用构建模型。首先,我们将使用顺序模型,一个接一个地添加图层。有一个节点数等于 nBands 的输入层。使用一个具有 14 个节点的隐藏层和作为 激活函数 的 relu 。最后一层包含二进制组合类的两个节点,具有’ softmax '激活功能,适用于分类输出。你可以在这里找到更多的激活功能。
Neural Network architecture
*如第 10 行所述,我们用’亚当’优化器编译模型。(还有几个其他的可以查一下。)我们现在将使用的损失类型是*分类稀疏交叉熵。你可以在这里查看详情。模型性能评估的度量是“准确性”。
最后,我们用两个时期**(或迭代)在 xTrain 和 yTrain 上运行模型。根据您的数据大小和计算能力,拟合模型需要一些时间。模型编译后可以看到以下内容:**
让我们预测我们单独保存的测试数据的值,并执行各种准确性检查。
softmax 函数为每个类类型概率值生成单独的列。我们只对类一(构建的)进行提取,如上面代码片段的第六行所述。地理空间相关分析的模型变得难以评估,因为与其他一般的 ML 问题不同,依赖一个概括的总结误差是不公平的;空间位置是制胜模式的关键。因此,混淆矩阵、精度和召回率可以更清楚地反映模型的表现如何。
Confusion matrix, precision and recall as displayed in the terminal
正如在上面的混淆矩阵中所看到的,有成千上万的堆积像素被分类为非堆积像素,反之亦然,但占总数据大小的比例较小。在测试数据上获得的准确率和召回率都在 0.8 以上。
您总是可以花一些时间并执行一些迭代来找到最佳的隐藏层数量、每个隐藏层中的节点数量以及获得精确度的历元数量。一些常用的遥感指数如 NDBI 或 NDWI 也可以在需要时用作特征。达到所需精度后,使用模型预测新数据并导出 GeoTIFF。稍加调整的类似模型可以应用于类似的应用。
请注意,我们导出的是具有预测概率值的 GeoTIFF,而不是其阈值二进制版本。我们始终可以稍后在 GIS 环境中设置 float 类型图层的阈值,如下图所示。
Hyderabad built-up layer as predicted by the model using the multispectral data
模型的精度已经通过精度和召回率进行了评估,您也可以对新的预测栅格进行传统检查(例如 kappa 系数)。除了上述卫星数据分类的挑战之外,其他直观限制包括由于光谱特征的变化,该模型无法预测不同季节和不同地区获得的数据。
我们在本文中使用的模型是神经网络的一个非常基本的架构,一些复杂的模型,包括卷积神经网络(CNN)** 已经被研究人员证明可以产生更好的结果。想入门 CNN 进行卫星数据分类,可以看看这篇帖子“**CNN 在中分辨率卫星数据上同样闪亮吗?T13”。这些方法的主要优点是模型训练后的可伸缩性。**
请在此找到使用的数据和完整的脚本。
用 NNI 搜索神经结构
探索微软开源 AutoML 工具的强大功能
Photo by Filip Bunkens on Unsplash
神经架构搜索(NAS)是深度学习中的一个困难挑战。我们中的许多人都经历过,对于给定的数据集,网络最初可能很难学习。但只要简单地改变一个超参数,学习就会变得非常有效。手动调整包括架构在内的超参数既耗时又具有挑战性,尽管对某些人来说也很有趣。最近,自动超参数调优变得越来越流行,因为它提供了大规模解决 NAS 的有效机制。
在这篇文章中,我们将展示如何使用自动化机器学习(AutoML)工具来执行超参数搜索——NNI(用于神经网络智能)由微软开源。我刚刚开始和 NNI 一起踢球,到目前为止我都很喜欢它。在这里,我想分享我如何使用 NNI 搜索最佳超参数和架构。
作为一个例子,我们将建立一个神经网络来近似数学函数。假设满足激活函数的某些非线性条件,具有一个或多个隐藏层的神经网络被称为连续函数的函数逼近器[1]。像只有一个隐藏层的浅层网络不如宽度限制的深层网络有效(例如[2])。对于神经网络如何逼近函数,迈克尔·尼尔森给了一个很好的、通俗易懂的解释。
简单非线性函数
我们从一个简单的非线性目标函数 y = x 开始。我们用一个有几个隐层的全连通网络,在范围[0,1]内学习这个函数。
下面是将此函数实现为 PyTorch 数据集的代码。输入数据和地面实况标签由 shape (1,1)的张量表示,其中两个分量分别是通道和数据维度。它们都是 1,因为 x 和 y 只保存标量值。如果您有基于图像的神经网络的经验,您可以将数据视为单通道、单像素图像。
我们建立了一个多达三个隐藏层的全连接网络。该网络可以灵活地配置成具有从 1 到 3 范围内的隐藏层深度。
为了让训练进行下去,我们需要做出许多选择。我们必须决定隐藏层的数量,每层的大小,激活函数,优化器,学习率等。我们从一个由 16 个神经元组成的单一隐藏层的网络开始,选择如下:
activation_function: 'Sigmoid'learning_rate: **0.01** optimizer: 'Adam'loss_function: 'MSELoss'
运行脚本250 个时期,您将获得下图所示的学习功能。红点是网络输出,大致遵循实际的二次函数(蓝色曲线)。但显然,还有改进的空间。
Fig. 1
请注意,我们在 Python 中有固定的随机数生成种子,因此每个网络总是以相同的初始权重/偏差集开始,并且结果是可重复的。
作为一个有趣的实验,我们可以让网络架构更宽或更深,看看它是否能提高近似性。下图显示了一个 256 个神经元的单一隐藏层的“更广泛”模型的结果。性能和 16 神经元版本差不多。
Fig. 2
但是,如果我们使用一个“更深”的模型,每层有 16 个神经元的三个隐藏层,网络输出与目标函数非常匹配(见下图)。更具体地说,网络可以描述为{ 隐藏 _ 层 _ 1 _ 大小:16,隐藏 _ 层 _ 2 _ 大小:16,隐藏 _ 层 _ 3 _ 大小:16 }。为了便于我们讨论各种网络架构,我们将使用三个数字{ n1、n2、n3 }的简写来表示一个网络。在这种情况下,模型是{16,16,16}。目标函数和网络输出之间的最大近似误差约为 0.02。误差在 x (1.0)的上限附近达到最大值。其他地方的误差要小得多。
Fig. 3
更具挑战性的功能
现在让我们尝试一个更具挑战性的函数。该函数上下波动几次,变化幅度缓慢衰减。由于没有更好的名字,我将这个函数命名为振荡器。振荡器是连续的,因此神经网络可以近似。然而,它并不平滑,有突然的“跳跃”(令人惊讶的是,神经网络仍然能够处理这些,正如我们稍后看到的那样)。
Fig. 4
该函数可以通过构建一系列点( x,y )来创建,其中 x 均匀分布在[0,1]之间,间距为 0.1,并且 y 从 0.5 开始,并且每个后续的 y 值从其最后一个值计算。
yᵢ₊₁ = -(yᵢ² - 0.5)
现在,找出所有的超参数并不容易。例如,如果我们使用相同的{16,16,16}网络,并运行超过 1000 个时期,结果是:
Fig. 5
注意,由于目标函数比简单的二次函数更复杂,所以我们在更多的时期训练它。学习的函数(红色)不像二次函数那样逼近实际函数(蓝色),即使网络已经“识别”了函数中最显著的特征并逼近它们。
至于之前的二次函数,我们可以把网络架构做得更宽或者更深,看看是否提高了逼近度。但是找到最有效的模型将会很费时间,因为它涉及到大量的试验和错误。
在下一部分,我们将使用 NNI 自动进行搜索。
神经网络智能
NNI 是一个灵活和强大的超参数搜索工具。我发现 NNI 的文档和工作流程很容易理解和遵循,不像其他自动机器学习选项。NNI 可以很容易地配置为在本地机器上运行。对于我们的目的来说,在本地进行搜索就足够了,因为每次训练不超过几分钟,甚至不需要 GPU。
NNI 的一个实验由许多试验组成,每个试验评估一个独特的搜索参数组合。在每次试验中,使用选定的参数从头开始构建模型并进行训练。所有的性能指标都被记录下来,并可以在最后使用提供的 WebUI 进行检查。
有两种方式使用 NNI:通过 NNI API 或通过 NNI Python 注释。主要区别是在哪里指定搜索参数选项。NNI API 方法希望在 JSON 文件中列出选项,而 Python Annotation 方法允许您将选项作为特殊格式的代码注释嵌入到脚本中的参数定义旁边。后者为神经架构搜索提供了更好的支持(命名为神经架构搜索的 NNI 编程接口),允许您在注释中方便地指定不同的架构选项。然而,在撰写本文时,这仍然是一个实验性的特性。在本帖中,我们将使用 NNI API 进行包括架构在内的超参数搜索。与 NNI 编程接口相比,这需要我们编写更多的代码来管理架构搜索,但对于我们的目的来说,这仍然是可管理的。
第一次 NNI 实验
有许多超参数可能会影响我们的模型性能,但同时搜索所有这些参数非常耗时。假设我们想要探索 7 个参数,每个参数有 4 个值要尝试。唯一参数组合的总数是 4⁷ = 16384。运行如此多的试验将需要很长时间,甚至分析最终结果也可能变得棘手。如本文后面所示,我们将使用 NNI WebUI 来可视化和查看结果。但是,如果我们有太多的数据点,这将不会工作得很好。
相反,我们将把搜索分为两步。还记得我们在这篇文章前面选择的四个参数(激活函数、学习率、优化器和损失函数)的值吗?第一步是尝试为这些与网络架构无关的参数找到合适的值。一旦我们摆脱了这些不确定性,我们就可以专注于架构搜索。注意,激活功能可以被视为一个架构参数。但是它与网络的拓扑无关。在我们的实验中,我们将它与其他非体系结构参数分组,以便稍后我们可以从拓扑角度关注体系结构搜索。
请注意,这种两步走的方法是一种妥协。这里,我们隐含地假设非架构参数(如损失函数)的优化不依赖于网络拓扑,因此我们可以将它们解耦并分别优化。但在现实中,拓扑、非架构超参数和初始网络权重/偏差很可能交织在一起,它们的优化在某种程度上都相互依赖。我们采取这种实用的方法来寻找一个很好的解决问题的方法,但我们不能保证它是最好的。
我们在这个实验中使用一个具有{16,16,16}网络的模型。它可能不是最好的架构(我们还不知道),但它将允许我们首先深入了解其他超参数。
我们将首先了解 NNI 是如何运作的。使用 NNI API 运行搜索实验的工作流程如下:
**1。定义搜索空间。**搜索空间描述了要搜索的每个参数的所有选择。这些选项将在 JSON 文件中列出,如下所示:
"act_func"**:** {"_type"**:** "choice"**,** "_value"**:** ["ReLU"**,** "LeakyReLU"**,** "Sigmoid"**,** "Tanh"**,** "Softplus"]}**,** "learning_rate"**:** {"_type"**:** "quniform"**,** "_value"**:** [**0.005, 0.05, 0.01**]}**,** "optimizer"**:** {"_type"**:** "choice"**,** "_value"**:** ["SGD"**,** "Adam"**,** "RMSprop"]}**,** "loss"**:** {"_type"**:** "choice"**,** "_value"**:** ["SmoothL1Loss"**,** "MSELoss"]}
这里,由于学习率是一个连续变量,我们将其设置为在[0.005,005]的范围内变化,间距为 0.01。
**2。修改模型代码以使用 NNI API。**该步骤包括在每次试验之前调用 nni.get_next_parameter() 以获得所有搜索参数的唯一组合,在训练期间调用*nni . report _ intermediate _ result()以将中间性能指标作为时间序列记录到 nni,并在每次训练会话之后调用nni . report _ final _ result()*以记录最终指标。一个这样的培训脚本的例子在这篇文章的报告中提供。
3。创建一个 YAML 配置文件,并在其中启用 NNI API。
authorName: default
experimentName: single_var_func
trialConcurrency: 2
maxExecDuration: 5h
maxTrialNum: 5000
trainingServicePlatform: local
searchSpacePath: search_space_non_arch.json
*#searchSpacePath: search_space_arch.json* useAnnotation: false
tuner:
builtinTunerName: GridSearch
trial:
command: python3 func_approx_nni.py oscillator
codeDir: .
gpuNum: 0
注意,我们将 useAnnotation 设置为 false 来启用 NNI API。我们使用 GridSearch 搜索调谐器参数builtin tunername来搜索所有可能的参数值组合。NNI 调谐器还有其他选项可以使用不同的搜索算法来减少搜索空间和节省搜索时间。在撰写本文时,我还没有很好地理解这些搜索算法所做的权衡。你需要给他们一个尝试,看看哪个更适合你。
4。进行实验。
像这样运行实验:
nnictl create --config config.yaml
如果一切顺利,这将启动一个 NNI 搜索实验,并告诉你查看结果的网址。用浏览器打开网址,你可以看到 NNI 的网页界面。这个漂亮的 UI 工具非常容易使用。它报告作业运行状态,当实验完成时,它以直观的图形显示所有试验的结果。这是有趣的部分——看看哪个参数组合能给你最好的结果。
下面的超参数视图突出显示了该实验中表现最好的部分(红色部分)。
Fig. 6
我们可以看到, SmoothL1Loss 损失函数、 Adam 优化器和 LeakyReLU 激活函数的组合往往工作得非常好,并且性能对学习速率不太敏感。
超参数视图的一个很大的特点是我们可以向左或向右移动参数线。在下面的屏幕截图中,我们将“loss”参数与“act_func”参数互换。现在很容易看出 ReLU 不管其他参数如何都是一个糟糕的选择,因为它没有与任何接近或高于 2.0 的好的度量值相关联(用红色或橙色标出)。
Fig. 7
同样,如果我们将“优化器”参数移至“默认指标”线附近,我们可以看到 RMSprop 和 SGD 通常与较低的指标值(绿色或黄色)相关联,无法与 Adam 竞争。
Fig. 8
有趣的是,表现最好的人在人群中脱颖而出。这种差异可能不是非常显著,因为一些模型的指标在训练期间波动很大。最佳表现者具有以下参数:
'act_func': 'LeakyReLU'**,** 'learning_rate': **0.005,** 'optimizer': 'Adam'**,** 'loss': 'SmoothL1Loss'
如果我们采用这些参数值并训练相同的{16,16,16}网络,则网络输出与目标函数非常匹配(与图 5 相比):
Fig. 9
建筑搜索
我们的架构搜索是为了找到隐藏层的最佳数量和每个隐藏层的大小,如下面另一个 JSON 文件中所列:
"hidden_size_1"**:** {"_type"**:** "choice"**,** "_value"**:** [**4, 8, 16, 32, 64, 128**]}**,** "hidden_size_2"**:** {"_type"**:** "choice"**,** "_value"**:** [**0, 4, 8, 16, 32**]}**,** "hidden_size_3"**:** {"_type"**:** "choice"**,** "_value"**:** [**0, 4, 8, 16, 32**]}
将零作为 hidden_size_2 和 hidden_size_3 的选项有效地覆盖了不使用隐藏层 2 或 3 的情况。例如,将 hidden_size_2 和 hidden_size_3 都设置为零会产生单个隐藏层网络。
搜索结果如下图所示。表现最好的人用红色或橙色突出显示。我们可以看到,第一个隐藏层中的神经元数量与性能指标大致相关。这一层的神经元越多,我们得到的结果就越好。一般来说,其他隐藏层也是这样,有道理。网络掌握的参数越多,它就越容易学习。
Fig. 10
就网络拓扑而言,没有明显的模式。有这样的网络,每一层的神经元数量随着我们的深入而减少,或者大致保持不变,或者实际上增加。
我们对具有最少层数和最少神经元的简单网络更感兴趣。这就是神经架构搜索的目标——在性能很少或没有妥协的情况下找到高效的网络。所有单隐藏层网络的性能在此图中突出显示:
Fig. 11
{64,0,0}模型可以给出非常好的结果,最大近似误差约为 0.006:
Fig. 12
网络中使用的参数(权重和偏差)数量为 64+64+64+1=193,明显少于我们之前尝试的{16,16,16}网络(有 593 个参数)!
如果一个 64 个神经元的单隐层的网络可以在这里工作,为什么一个 128 个神经元的单隐层的网络不能在比较中表现得更好呢?在 WebUI 上,我们可以轻松地检查每个网络随时间推移的性能。结果是{128,0,0}模型的度量比{64,0,0}模型波动更大。因为我们只报告了最后 5 个指标中的最小值作为最终结果,所以{128,0,0}模型的值碰巧更低。但是来自{128,0,0}模型的最后 5 个指标的上限与该实验中的其他顶级表现者一样具有竞争力。为什么训练时波动这么大?在训练的后期阶段,网络性能可能对微小的参数调整很敏感,对于更大的网络,保持所有神经元以同步方式更新更具挑战性。因此,有时性能会有较大的波动。
另一个有趣的观察是,对于所有只有一个隐藏层的网络,那些不超过 32 个神经元的网络显然不会从目标函数中学习。事实上,我们可以通过粗略的分析来理解这一点。近似振荡器函数所需的最小参数是 112 = 22,因为我们需要知道范围[0,1]中的所有 11 个关键点,并且每个都需要两个值( x 和 y )来指定。参数在 22 左右的网络将由 4 或 8 个神经元的单一隐藏层组成。但这并不意味着{8,0,0}网络可能是最有效的架构,因为我们知道神经网络在默认情况下不会自动学习变得高效和苗条。也就是说,网络不知道如何最有效地利用每个参数的。因此,我们的任务所需的网络可能会比{8,0,0}网络大一点。事实上,如果我们试图训练一个少于 16 个神经元的单一隐藏层的网络,即使经过 5000 多个纪元,我们也无法找到一个像样的解决方案。*
概述
NNI 是一个轻量级,灵活的 AutoML 工具,可以帮助神经架构搜索。在这篇文章中,我们用 NNI 优化了一个近似函数的神经网络。这个实验可以在计算能力一般的台式机上完成。因此,与其他 NAS 框架相比,它很容易上手。我们只探索了使用 NNI 的基本方法。我希望他们是有趣的,并且让你对 NNI 能做什么有一个好的感觉。
这篇文章的全部源代码是在这里。
参考文献
[1] G. Cybenko,“通过叠加 sigmoidal 函数的近似法”,控制、信号和系统的数学,2(4),303–314,1989。
【2】s . Liang 和 R. Srikant,“为什么深度神经网络要进行函数逼近?、ICLR 20172017。
神经网络优化
涵盖优化器,动量,自适应学习率,批量标准化,等等。
“我们的目标是找到最大价值优化的最佳点,在这一点上,愚蠢的风险与过度的谨慎相平衡。”―史蒂文·j·鲍恩
Example of non-convex loss surface with two parameters. Note that in deep neural networks, we’re dealing with millions of parameters, but the basic principle stays the same. Source: Yoshua Bengio.
本文是旨在揭开神经网络神秘面纱并概述如何设计和实现它们的系列文章中的第三篇。在本文中,我将讨论以下与神经网络优化相关的概念:
- 优化挑战
- 气势
- 自适应学习率
- 参数初始化
- 批量归一化
您可以访问下面的前几篇文章。第一个为那些不熟悉的人提供了神经网络主题的简单介绍。第二篇文章涵盖了更多的中间主题,如激活函数、神经结构和损失函数。
神经网络的详细概述,有大量的例子和简单的图像。
towardsdatascience.com](/simple-introduction-to-neural-networks-ac1d7c3d7a2c) [## 神经网络体系结构综合介绍
神经架构、激活函数、损失函数、输出单元的详细概述。
towardsdatascience.com](/comprehensive-introduction-to-neural-network-architecture-c08c6d8e5d98)
这些教程主要基于哈佛和斯坦福大学计算机科学和数据科学系的课堂笔记和例子。
优化挑战
当在神经网络的上下文中讨论优化时,我们讨论的是非凸优化。
凸优化 涉及一个只有一个最优的函数,对应全局最优(最大或最小)。凸优化问题没有局部最优的概念,使它们相对容易解决——这些是本科和研究生优化课程中常见的介绍性主题。
非凸优化涉及一个具有多个最优值的函数,其中只有一个是全局最优值。根据损失面的不同,很难找到全局最优解
对于神经网络来说,我们所说的曲线或曲面就是损失曲面。因为我们试图最小化网络的预测误差,所以我们对在这个损失表面上找到全局最小值感兴趣——这是神经网络训练的目的。
与此相关的问题有很多:
- 什么是合理的学习率?太小的学习率需要太长的时间来收敛,而太大的学习率将意味着网络不会收敛。
- 我们如何避免陷入局部最优?一个局部最优值可能被一个特别陡峭的损失函数包围,并且可能很难“逃离”这个局部最优值。
- **如果损失面形态发生变化怎么办?**即使我们能找到全局最小值,也不能保证它会无限期地保持全局最小值。一个很好的例子是在不代表实际数据分布的数据集上进行训练时,当应用于新数据时,损失面会有所不同。这就是为什么试图使训练和测试数据集代表整个数据分布如此重要的一个原因。另一个很好的例子是,由于其动态特性,数据的分布习惯性地发生变化——这方面的一个例子是用户对流行音乐或电影的偏好,这种偏好每天和每月都在变化。
幸运的是,有一些方法可以解决所有这些挑战,从而减轻它们潜在的负面影响。
局部最优
以前,局部最小值被认为是神经网络训练中的一个主要问题。如今,研究人员发现,当使用足够大的神经网络时,大多数局部最小值会导致低成本,因此找到真正的全局最小值并不特别重要——具有合理低误差的局部最小值是可接受的。
鞍点
最近的研究表明,在高维空间中,鞍点比局部极小值更有可能出现。鞍点也比局部最小值更成问题,因为接近鞍点的梯度可能非常小。因此,梯度下降将导致可忽略的网络更新,因此网络训练将停止。
Saddle point — simultaneously a local minimum and a local maximum.
经常用于测试鞍点上优化算法性能的一个示例函数是 罗森布鲁克函数 。该函数由公式描述: *f(x,y) = (a-x) + b(y-x),*在 (x,y) = (a,a ) 处具有全局最小值。
这是一个非凸函数,其全局最小值位于一个狭长的谷中。找到山谷相对容易,但是由于平坦的山谷,很难收敛到全局最小值,因此具有小的梯度,因此基于梯度的优化过程很难收敛。
A plot of the Rosenbrock function of two variables. Here a=1,b=100, and the minimum value of zero is at (1,1).
Animation of Rosenbrock’s function of three variables. [Source](http://Simionescu, P.A. (2014). Computer Aided Graphing and Simulation Tools for AutoCAD users (1st ed.). Boca Raton, FL: CRC Press. ISBN 978-1-4822-5290-3.)
调理不良
一个重要的问题是代表学习问题的误差函数的特殊形式。早就注意到,误差函数的导数通常是病态的。这种病态反映在包含许多鞍点和平坦区域的误差地形中。
为了理解这一点,我们可以看看 Hessian 矩阵——一个标量值函数的二阶偏导数的方阵。 Hessian 描述了多变量函数的局部曲率。
Hessian 可以用来确定一个给定的驻点是否是鞍点。如果 Hessian 在该位置是不定的,则该驻点是鞍点。这也可以通过查看特征值以类似的方式进行推理。
计算和存储完整的 Hessian 矩阵需要 O(n ) 内存,这对于高维函数如神经网络的损失函数是不可行的。对于这种情况,通常使用截断牛顿和拟牛顿算法。后一类算法使用对 Hessian 的近似;最流行的准牛顿算法之一是 BFGS 算法。
通常对于神经网络来说,Hessian 矩阵是不适定的——输入的微小变化都会导致输出快速变化。这是一个不希望的特性,因为这意味着优化过程不是特别稳定。在这些环境中,尽管存在强梯度,学习仍然很慢,因为振荡减慢了学习过程。
消失/爆炸渐变
到目前为止,我们只讨论了目标函数的结构——在这种情况下是损失函数——及其对优化过程的影响。还有一些与神经网络架构相关的问题,这与深度学习应用程序特别相关。
上述结构是具有 n 个隐藏层的深度神经网络的一个例子。当第一层的要素在网络中传播时,它们会经历仿射变换,然后是激活函数,如下所述:
上述等式对于单层是正确的。我们可以写出 n 层网络的输出:
根据 a 和 b 的大小,上述公式有两种可能的情况。
如果值大于 1,对于较大的值 n (深度神经网络),梯度值将在网络中传播时迅速爆炸。除非实现梯度裁剪,否则爆炸梯度会导致“悬崖”(如果梯度超过某个阈值,就会被裁剪)。
An example of clipped vs. unclipped gradients.
Gradient clipping rule.
如果值小于 1,梯度将很快趋于零。如果计算机能够存储无限小的数字,那么这就不是问题,但是计算机只能存储有限的小数位数。如果梯度值变得小于该值,它将被识别为零。
那我们该怎么办?我们已经发现,神经网络注定具有大量的局部最优值,通常包含尖锐和平坦的谷,这导致学习停滞和不稳定的学习。
我现在将讨论一些我们可以帮助减轻我们刚刚讨论的关于神经网络优化的问题的方法,从动量开始。
动力
随机梯度下降(SGD)的一个问题是不利用曲率信息的更新导致的振荡的存在。这导致当曲率较高时 SGD 较慢。
(Left) Vanilla SGD, (right) SGD with momentum. Goodfellow et al. (2016)
通过采用平均梯度,我们可以获得更快的优化路径。这有助于抑制振荡,因为相反方向的梯度被抵消了。
动量这个名称来源于这样一个事实,即它类似于物理学中的线性动量概念。具有运动的对象(在这种情况下,这是优化算法移动的大致方向)具有一些惯性,这导致它们倾向于在运动方向上移动。因此,如果优化算法在大致方向上移动,动量使其“抵抗”方向的变化,这导致高曲率表面的振荡衰减。
动量是目标函数中的一个附加项,它是一个介于 0 和 1 之间的值,通过试图从局部最小值开始跳跃来增加向最小值前进的步长。如果动量项很大,那么学习率应该保持较小。动量值大也意味着收敛速度快。但是如果动量和学习率都保持在大值,那么你可能会跳过最小值一大步。小的动量值不能可靠地避免局部最小值,并且还会减慢系统的训练。如果梯度不断改变方向,动量也有助于平滑变化。动量的正确值可以通过反复试验或交叉验证来学习。
动量使用过去的梯度来更新值,如下式所示。与动量相关的值 v 通常被称为“速度”。将更多的权重应用于较新的渐变,从而创建渐变的指数衰减平均值。
我们可以看到增加动量对优化算法的影响。最初的几次更新并没有显示出相对于普通 SGD 的真正优势——因为我们没有以前的梯度用于我们的更新。随着更新数量的增加,我们的动力开始启动,并允许更快的收敛。
SGD without momentum (black) compared with SGD with momentum (red).
另一种存在的动量是内斯特罗夫动量,我们将简要讨论它。
内斯特罗夫势头
在 Sutskever,Martens 等人的《论深度学习中初始化和动量的重要性》2013 中对内斯特罗夫动量进行了很好的讨论。
主要的区别是,在经典动量理论中,你首先修正你的速度,然后根据这个速度前进一大步(然后重复),但是在内斯特罗夫动量理论中,你首先向速度方向前进一步,然后根据一个新的位置修正速度矢量(然后重复)。
即经典动量:
vW(t+1) = momentum.*Vw(t) - scaling .* gradient_F( W(t) )
W(t+1) = W(t) + vW(t+1)
而内斯特罗夫的势头是这样的:
vW(t+1) = momentum.*Vw(t) - scaling .* gradient_F( W(t) + momentum.*vW(t) )
W(t+1) = W(t) + vW(t+1)
这种差别很微妙,但在实践中,它会产生巨大的影响。
这个概念可能很难理解,所以下面是传统动量更新和内斯特罗夫动量之间的区别的直观表示。
Source (Stanford CS231n class)
自适应学习率
沿垂直方向的振荡-沿参数 2 的学习速度一定较慢。对每个参数使用不同的学习速度?
阿达格拉德
动量增加了误差函数斜率的更新,从而加快了 SGD 的速度。AdaGrad 根据每个参数的重要性调整更新,以执行更大或更小的更新。
Adagrad 的主要优势之一是,它消除了手动调整学习速度的需要,并在平缓的倾斜方向上取得更大的进步。
AdaGrad 的主要缺点是它在分母中累积平方梯度:因为每个增加的项都是正的,所以累积和在训练期间保持增长。这反过来导致学习速率缩小,最终变得无穷小,此时算法不再能够获得额外的知识。
RMSProp
对于非凸问题,AdaGrad 会过早地降低学习速率。我们可以使用指数加权平均值进行梯度累积。
圣经》和《古兰经》传统中)亚当(人类第一人的名字
Adam 是 RMSprop 和 momentum 的组合(类似地,Nadam 指 RMSprop 和内斯特罗夫 momentum 的组合)。Adam 指的是自适应矩估计,,它是当今用于神经网络的最流行的优化器。
Adam 计算每个参数的自适应学习率。除了存储像 Adadelta 和 RMSprop 这样的过去平方梯度 vt 的指数衰减平均值之外,Adam 还保持过去梯度的指数衰减平均值,类似于动量。
参数初始化
在前面的章节中,我们研究了如何最好地导航神经网络目标函数的损失面,以便收敛到全局最优(或可接受的良好局部最优)。现在,我们将看看如何操纵网络本身,以帮助优化程序。
网络权重的初始化是开发神经网络的一个重要且经常被忽视的特征。初始化不良的网络会带来多种问题,对网络性能不利。
以一个网络为例,我们将其初始化为全零值。在这种情况下会发生什么?网络实际上根本学不到任何东西。即使在梯度更新之后,所有的权重仍然是零,因为我们计算梯度更新的固有方式。
假设我们实现了这一点,并发现这是一个问题,然后决定将我们的网络初始化都设置为相同的值 0.5。现在会发生什么?网络实际上会学习一些东西,但我们过早地规定了神经单元之间的某种对称形式。
一般来说,通过根据正态分布随机化权重来避免预设任何形式的神经结构是一个好主意。在 Keras 中,这通常是通过指定一个随机状态来实现的(这提供了随机性,但确保了测量的可重复性)。
这种初始化的规模应该是多少?如果我们为权重选择大的值,这可能导致爆炸梯度。另一方面,较小的权重值会导致渐变消失。在这两者之间有一个最佳平衡点,但是它不能被先验地知道,必须通过反复试验来推断。
Xavier 初始化
Xavier 初始化是分配网络权重的简单启发式方法。每经过一层,我们希望方差保持不变。这有助于我们防止信号爆炸到高值或消失为零。换句话说,我们需要初始化权重,使得输入和输出的方差保持不变。
权重来自具有零均值和特定方差的分布。对于具有 m 输入的全连接层:
值 m 有时被称为*扇入:*传入神经元的数量(权重张量中的输入单元)。
重要的是要记住,这是一个启发,因此没有特别的理论支持-它只是凭经验观察到表现良好。可以在这里阅读原论文。
他正常初始化
正常初始化基本上与 Xavier 初始化相同,只是方差要乘以 2 倍。
在这种方法中,记住前一层的大小来初始化权重,这有助于更快更有效地获得成本函数的全局最小值。权重仍然是随机的,但是范围根据前一层神经元的大小而不同。这提供了受控的初始化,因此更快和更有效的梯度下降。
对于 ReLU 装置,建议:
偏置初始化
偏置初始化指的是应该如何初始化神经元的偏置。我们已经描述了权重应该用某种形式的正态分布随机初始化(以打破对称性),但是我们应该如何处理偏差呢?
套用斯坦福 CS231n 课程的话:初始化偏差的最简单、最常见的方式是将其设置为零——因为权重中的小随机数提供了不对称打破。对于 ReLU 非线性,一些人喜欢对所有偏差使用小的常数值,例如 0.01,因为这确保所有 ReLU 单元在开始时启动,并因此获得和传播一些梯度。然而,尚不清楚这是否提供了一致的改善,更常见的是将偏差设置为零。
偏置初始化的一个主要问题是避免隐藏单元在初始化时饱和,例如在 ReLU 中,可以通过将偏置初始化为 0.1 而不是 0 来实现。
预初始化
另一种初始化权重的方法是使用预初始化。这对于用于检查图像的卷积网络来说是常见的。该技术包括输入已经训练好的网络(例如 VGG16)的权重,并使用这些权重作为待训练网络的初始权重。
这种技术只对用于类似数据的网络才是真正可行的,所述数据是网络被训练的数据。例如,VGG16 是为图像分析开发的,如果您计划分析图像,但数据集中的数据样本很少,那么预初始化可能是一种可行的方法。这是迁移学习背后的基本概念,但是术语预初始化和迁移学习不一定是同义词。
批量标准化
到目前为止,我们已经研究了使用动量和自适应学习率来导航神经网络损失面的方法。我们还研究了参数初始化的几种方法,以便最小化网络内的先验偏差*。在这一节中,我们将看看如何操作数据本身,以帮助我们的模型优化。*
为了做到这一点,我们将研究批处理规范化以及实现批处理规范化以帮助优化神经网络的一些方法。
特征归一化
特征规范化正是它所说的,它包括在应用学习算法之前规范化特征。这涉及到重新缩放特征,通常在预处理过程中完成。
根据论文“批量归一化:通过减少内部协变量移位来加速深度网络训练”,梯度下降在有特征缩放的情况下比没有特征缩放的情况下收敛得快得多。
有几种方法可以缩放数据。一种常见的方法是最小-最大归一化,由此
缩放数据的最简单方法称为最小-最大归一化,它涉及重新缩放要素的范围,以在[0,1]或[1,1]中缩放范围。这是通过用最小值减去每个值,然后用数据集中存在的值的范围对其进行缩放来实现的。如果数据的分布高度倾斜,这可能会导致许多值聚集在一个位置。如果发生这种情况,有时可以通过对特征变量取对数来缓解(因为这有可能会导致异常值崩溃,因此它们对分布的影响不太大)。
另一种常用方法是均值归一化,这基本上与最小-最大归一化相同,只是从每个值中减去平均值。这是本文讨论的三种方法中最不常见的一种。
特征标准化使数据中每个特征的值具有零均值(当减去分子中的均值时)和单位方差。这种方法广泛用于许多机器学习算法(通常是那些涉及基于距离的方法)中的归一化。计算的一般方法是确定每个特征的分布平均值和标准偏差。接下来,我们从每个特征中减去平均值。然后,我们将每个特征的值(平均值已经减去)除以其标准偏差。
通过执行归一化,我们可以改善数据集的失真(例如一个要素相对于另一个要素的拉长)并使其更加均匀。
内部协方差移位
这个思路也来源于之前提到的论文批量归一化:通过减少内部协变量移位加速深度网络训练。
作者定义内部协方差移位:
我们将内部协变量移位定义为由于训练期间网络参数的变化而导致的网络激活分布的变化。
这可能有点模糊,所以我会尝试解开这个。在神经网络中,第一层的输出馈入第二层,第二层的输出馈入第三层,依此类推。当一层的参数改变时,对后续层的输入分布也改变。
输入分布的这些变化对于神经网络来说可能是有问题的,因为它有减慢学习的趋势,尤其是可能具有大量层的深度神经网络。
众所周知,如果输入已被白化(即零均值、单位方差)且不相关,则网络收敛更快,而内部协变量移位会导致相反的结果。
批量标准化是一种旨在减轻神经网络内部协变量变化的方法。
批量标准化
批量标准化是将特征标准化的思想扩展到神经网络的其他层。如果输入层可以从标准化中受益,为什么网络层的其余部分不能呢?
为了提高神经网络的稳定性,批标准化通过减去批平均值并除以批标准偏差来标准化先前激活层的输出。
批量标准化允许网络的每一层独立于其他层进行学习。
然而,在通过一些随机初始化的参数对激活输出进行移位/缩放之后,下一层中的权重不再是最优的。如果这是最小化损失函数的一种方式,SGD(随机梯度下降)撤销这种归一化。
因此,批量归一化会向每一层添加两个可训练参数,因此归一化输出会乘以一个“标准差”参数(γ)并添加一个“均值”参数(β)。换句话说,批量规范化让 SGD 通过只改变每次激活的这两个权重来进行反规范化,而不是通过改变所有权重来失去网络的稳定性。
这个过程被称为批量归一化转换。
The batch normalization transform.
为了直观地说明这一点,我们可以分析下图。我们正在看第一个隐藏层,紧接着输入层。对于每个 N 小批量,我们可以计算输出的平均值和标准偏差。
随后对所有随后的隐藏层重复这一过程。接下来,我们可以区分 N 个小批量的联合损失,然后通过归一化操作反向传播。
批处理规范化减少了过度拟合,因为它有轻微的正则化效果。类似于脱落,它给每个隐藏层的激活添加一些噪声。
在测试期间,平均值和标准偏差由训练期间收集的运行平均值代替。这与使用总体统计而不是小批量统计是一样的,因为这确保了输出的确定性地依赖于输入。
使用批处理规范化有几个优点:
- 减少内部协变移位。
- 降低梯度对参数比例或其初始值的依赖性。
- 规则化模型,并减少对丢失、光度失真、局部响应归一化和其他规则化技术的需要。
- 允许使用饱和非线性和更高的学习率。
最终意见
这就结束了我关于全连接神经网络系列文章的第三部分。在接下来的文章中,我将提供一些深入的编码示例,演示如何执行神经网络优化,以及神经网络的更高级主题,如热重启、快照集成等。
时事通讯
关于新博客文章和额外内容的更新,请注册我的时事通讯。
丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…
mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)
进一步阅读
深度学习课程:
- 吴恩达的机器学习课程有一个很好的神经网络介绍部分。
- Geoffrey Hinton 的课程:用于机器学习的 Coursera 神经网络(2012 年秋季)
- 迈克尔·尼尔森的免费书籍神经网络和深度学习
- 约舒阿·本吉奥、伊恩·古德菲勒和亚伦·库维尔写了一本关于深度学习的书
- 雨果·拉罗歇尔在舍布鲁克大学的课程(视频+幻灯片)
- 斯坦福关于无监督特征学习和深度学习的教程(吴恩达等人)
- 牛津大学 2014-2015 年 ML 课程
- 英伟达深度学习课程(2015 年夏季)
- 谷歌在 Udacity 上的深度学习课程(2016 年 1 月)
面向 NLP:
以视觉为导向:
- 用于视觉识别的 CS231n 卷积神经网络作者 Andrej Karpathy(之前的版本,更短更不完善:黑客的神经网络指南)。
重要的神经网络文章:
- 神经网络中的深度学习:概述
- 神经网络的持续终身学习:综述——开放存取
- 物理储层计算的最新进展:综述—开放存取
- 脉冲神经网络中的深度学习
- 集成神经网络(ENN):一种无梯度随机方法——开放存取
- 多层前馈网络是通用逼近器
- 深度网络与 ReLU 激活函数和线性样条型方法的比较——开放访问
- 脉冲神经元网络:第三代神经网络模型
- 多层前馈网络的逼近能力
- 关于梯度下降学习算法中的动量项
使用 PyTorch 的梵文字符神经网络教程
用 PyTorch 训练一个人工神经网络用于识别手写的梵文字符。
Source: images.google.com
顾名思义,神经网络是由人脑神经元松散地激发出来的。但是我们不会在这里讨论大脑类比的任何细节。相反,我们将通过一些数学和编码来理解它。
感知器
弗兰克·罗森布拉特(Frank Rosenblatt)在 20 世纪 50 年代提出了感知机(perceptron),表明一种算法可以模仿人类大脑的决策能力(我们仍在尝试)。他在论文中写道,我们可以将输入视为由二进制数组成的神经元。如果这些二进制数可以生成一个二进制数作为输出**,如果输出满足某个阈值,则只生成。**
Perceptron model
你可能会问:
但是 Gopal,我们也可以写一个程序来做这个任务;为什么要写神经网络呢?我很高兴你问了。
选择神经网络而不是任何程序的第一个原因是,它们是通用函数逼近器,可以推断出我们试图建立的模型,或者如果它太复杂,神经网络总是代表那个函数。
我们可以假设将任何函数转化为数学术语,然后我们可以使用神经网络来表示该函数。
第二个原因是可伸缩性和灵活性。我们可以很容易地在神经网络中堆叠层,这将增加神经网络的复杂性。
神经网络的基本架构
神经网络由以下组件组成:
- 输入层 x
- 任意数量的隐藏层
- 输出图层,𝑦
- 一套 parameters(𝑊)和 biases(𝑏)各 layer,𝑊和𝑏之间
- 每个隐藏层的激活函数的选择,𝜎
Resource from https://tex.stackexchange.com/questions/132444/diagram-of-an-artificial-neural-network
我们训练神经网络进行 n 次迭代;每次迭代包括两个步骤:
- 前馈
- 反向传播
前馈:
简单来说,当第一层的输出成为下一层的输入。这种网络称为前馈网络。
我们的网络中没有反馈信息的回路;它将总是被前馈。
反向传播:
这是我们的神经网络实际上从训练数据中学习的过程。
但问题仍然没有答案,我们的网络如何学习分类或预测?如果我们的模型已经预测到了什么,那么我们的模型如何确定它是正确的预测还是错误的呢?
答案是损失函数;它有助于我们的网络预测与原始值相差多少。
我们的模型已经预测了一所房子的价格为 100K 美元,而原始价格为 101K 美元,那么原始价格和预测价格之间的差异将为 1K 美元;这就是损失函数帮助我们的网络决定的。
回到反向传播,在我们借助损失函数计算模型预测和原始值的误差之后,我们发回这个误差以更新我们的输入神经元或 权重和偏差。这被称为反向传播。
但是我们需要多少来更新我们的权重和偏差?
为了知道调整权重和偏差的适当量,我们必须推导出我们的 权重和偏差的损失函数。
我认为现在我们有足够的直觉来开始我们的编码部分。
实现人工神经网络对手绘天体文字的分类
我们将使用 PyTorch 库来构建我们的神经网络。
我写了一个小程序 plot_images 用于显示字符及其标签。
让我们看看我们的 CSV 文件中有什么。
df.head() 将给出数据帧的前 5 列。在我们的数据集中,我们有从 0 到 1023 的像素值。用于显示特定字符的字符列由特定像素值组成。
让我们运行我们的 plot_images 函数,看看这些图像。
>>plot_images(df, 4, "character")
我们的数据集中有 46 个独特的手绘字符;因此,数字 46 将是我们神经网络的输出维度。
但是在创建神经网络之前,我们需要准备数据加载器,以便将它提供给我们的模型进行训练和测试,因为 NumPy 数据不能与 PyTorch 的库一起工作。
因此,在上面的代码示例中,我们读取数据并从中分离出要素和标签。如果你注意到了,我也在用 255.0 除features _ numpy;我这样做是为了规范我们的像素值。
然后,我将我们的分类标签转换成代码,因为我们只能用数字数据来创建张量值。
在我们的 data_loader 函数中,我们获取特性和目标;如果它们在 NumPy 数据中,我们就把它们转换成张量;之后,我们用torch . utils . Data . tensordataset、 和创建张量数据,最后将数据转换成数据加载器。
就是这样;我们的数据现在可以输入到模型中了。让我们现在建立神经网络。
在我们的 ANNModel 中,取 32*32,最后一层输入的输出维度为 46。但是我们这里有两个我还没有谈到的新术语。
Dropout:删除带有概率值的随机激活权重。假设我们已经将概率值设置为 0.2。那么对于每一个前馈或者反向传播过程,它都会忽略掉那 20%的神经元。它有助于防止过度合身。
Softmax:在数学中,Softmax 函数,也称为 softargmax 或归一化指数函数,是一个将 K 个实数的向量作为输入,并将其归一化为由 K 个与输入数的指数成比例的概率组成的概率分布的函数。
通过理解这两个术语,我们现在可以继续培训过程。
训练过程简单;我们正在迭代我们的训练数据加载器的图像和标签。然后清除初始梯度值并随后进行预测。运行这个程序后,您应该可以获得超过 94%的测试数据的准确率。
不可能解释每一步;请在评论区问我。
培训结束后,让我们看看我们的培训和验证曲线。
Training vs. Validation loss
看起来不错。😃
推论:
让我们检查一下我们的模型在测试数据上的表现。
>> make_predictions(test_loader, 44)
Inference
它做得非常好。😃
参考
在数学中,softmax 函数,也称为 softargmax 或归一化指数函数,[2] :198 是一个…
en.wikipedia.org](https://en.wikipedia.org/wiki/Softmax_function)
数据集:
[## 梵文字符集
下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…
www.kaggle.com](https://www.kaggle.com/rishianand/devanagari-character-set)
如何停止使用回调训练神经网络?
Photo by Samuel Zeller on Unsplash
Tensorflow 和 Keras 的有用工具
介绍
通常,当训练一个非常深的神经网络时,一旦训练精度达到某个期望的阈值,我们就想停止训练。因此,我们可以实现我们想要的(最优模型权重)并避免资源浪费(时间和计算能力)。
在这个简短的教程中,让我们学习如何在 Tensorflow 和 Keras 中实现这一点,使用回调方法,4 个简单的步骤。
深潜
# Import tensorflow
import tensorflow as tf
- 首先,设置精度阈值,直到您想要训练您的模型。
ACCURACY_THRESHOLD = 0.95
2.现在实现回调类和函数,在精度达到 ACCURACY_THRESHOLD 时停止训练。
# Implement callback function to stop training
# when accuracy reaches e.g. ACCURACY_THRESHOLD = 0.95class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if(logs.get('acc') > ACCURACY_THRESHOLD):
print("\nReached %2.2f%% accuracy, so stopping training!!" %(ACCURACY_THRESHOLD*100))
self.model.stop_training = True
这到底是怎么回事?我们正在通过扩展TF . keras . callbacks . callback来创建新的类,并实现 on_epoch_end() 方法。这在每个时期结束时调用。接下来,我们获取该时期结束时的精度值,如果它大于我们的阈值,我们将模型的 stop_training 设置为 True。
3.实例化一个 myCallback 类的对象。
callbacks = myCallback()
接下来,按照 TensorFlow 或 Keras 的正常步骤建立一个 DNN 或 Conv 网络模型。当使用 fit() 方法训练模型时,将使用我们在上面构建的回调。
4.只需将一个参数作为callbacks =[<my callback 类的新实例化对象> ] 传递给 fit()方法。
model.fit(x_train, y_train, epochs=20, callbacks=[callbacks])
仅此而已!训练时,一旦精度达到在 ACCURACY_THRESHOLD 中设置的值,训练将会停止。
为了将所有这些联系在一起,这里有一个完整的代码片段。
结论
凭借我们的想象力,这种方法可以以各种创造性的方式使用,特别是当我们想要运行快速 POC 来测试和验证多个 DNN 架构时。你还能想到什么有趣的用法?请在下面的评论区分享你的想法。
深入探究人工神经网络与生物神经网络的功能
通信、噪声处理和架构变化
亮点:
生物神经网络由振荡器组成——这赋予了它们过滤输入和与噪音共振的能力。这也让他们有能力保留隐藏的点火模式。
人工神经网络与时间无关,不能过滤其输入。他们在训练后保持固定和明显的(但黑匣子)发射模式。
不同类型的噪声与人工神经网络不同元素的相互作用仍然是一个开放的研究课题。我们知道噪声可以用来调整它们的性能或帮助避免梯度下降中的局部最小值。
大脑重组其连接的能力被称为突触可塑性,它是通过长时程增强来实现的。人工神经网络在训练期间使用梯度下降来确定它们的连通性。梯度是使用反向传播计算的,我们可以将其与赫比长时程增强进行比较。
简介
头脑是大脑做的事情。那么,大脑到底在做什么,我们能造出什么来做类似的事情呢?这些东西到底是怎么做的?
在本文中,我们深入研究生物和人工神经网络的功能来回答这些问题。我们研究神经元和节点如何通信,它们如何处理噪声,以及网络在学习时如何变化——最终引导我们做出适当的选择和行为。
如果您对这些主题不熟悉,请点击此处了解这些网络的结构组件介绍:
生物神经网络
最终,任何网络的输出都取决于其节点的激活模式。在基本水平上,我们可以说一个神经元拥有一个电位,如果达到某个电阈值,就会触发。神经元通过突触进行交流,突触是细胞之间的间隙,信号在这里变成化学物质。一些化学物质会告诉突触后神经元触发,一些会告诉它不要触发。后面的神经元是否会放电,最终取决于它的电位。
人工神经网络
另一方面,一个节点持有一个称为“激活”的数值——这个数值越大,这个神经元对下一个神经元的影响越强。通常,我们使用一个 sigmoid 函数来保持激活值在 0 和 1 之间,并且我们有一个偏置项来左移或右移激活函数。通常,节点被组织成层,其中一层中的所有节点都连接到前一层中的每个节点。“权重”决定了连接的强度,就像化学物质一样,它们可以向下面的节点发送积极(着火)或消极(不着火)的信息。
通信: 阈值和定时
我们将会非常仔细地观察随着学习的进行,权重和突触是如何变化的,但是首先,一个有效的连接看起来像什么?基本上,人工神经网络权重不必担心基于它们的时序被忽略,而突触传递则需要。正如我们将看到的,其原因对信息处理有深远的影响。
直到 20 世纪末,神经元被认为只是简单地将它们从周围所有神经元接收到的电输入相加,如果总和超过-70 毫伏,就会触发。今天,我们知道神经元作为一个弱混沌振荡器持有能量。这意味着它们有一个轨道吸引子,所以不是每次振荡都走完全相同的路径,而是走近似相同的路径。更具体地说,神经元是非谐振子,这意味着它们振荡的速度不是恒定的。这些也称为松弛振子,因为它们的特点是能量的松弛积累,周期性地转化为能量的突然损失(类似于动作电位)。
让我们以 gy rgy buzáki 的家用放松振荡器为例,这样我们就可以把它分解开来:滴水的水龙头。一个松弛的振荡器有三个阶段:兴奋状态,活跃状态和不应期。第一个对应于一个积累一滴水的水龙头,而如果你点击它或产生某种输入,水就会下降(但如果你等待更多的水积累,水滴可能会更大)。然后,在活动阶段,液滴会自己落下。随着水的下降,在不应期之后,当没有水或水很少时,系统不会受到干扰。
神经元就像水龙头,在激活和不应期对突触活动免疫。这意味着松弛振荡器在信息传输和接收周期之间交替,其中这些周期的长度由振荡器的频率决定。
这种相位重置特性赋予振荡器网络学习和存储模式的能力。人工神经网络也存储连接模式,但它们完全脱离时间(除了我们试图优化它们运行多长时间)。这里,所有节点接收来自前一层中所有节点的信息,我们能做的最好的事情是调整权重和偏置项,以保持激活为 0。神经元结合高通(电压相关)和低通(时间相关)滤波来执行基于频率的输入选择。在现实中,神经元的每个部分(即树突、轴突等。)可以起到这种有滤波能力的谐振振荡器的作用。
为什么这如此重要?除了由输入选择引起的明显的信息处理差异之外,这是网络如何处理噪声的决定性因素。
噪声: 偏差-方差权衡和随机共振
过度拟合是人工神经网络的致命弱点,噪声可以帮助我们解决这个问题。当机器学习模型具有低偏差(它捕捉变量之间的关系)和高方差(它在数据集之间具有高度可变的拟合质量)时,就会发生过度拟合。这是有问题的,因为它使我们的模型在新数据上工作不佳或不可靠。减少过度拟合的过程称为正则化,在该过程中,偏差上升,方差下降。
在训练过程中添加噪声是调整人工神经网络的一个很好的方法。通常怀疑是高斯噪声(即随机噪声),如果应用于输入,这也被认为是一种数据增强技术。我们还可以将噪声添加到权重、梯度(我们将在后面进一步探讨)和激活函数中。这些不同元素中的噪声提高性能的机制还没有被精确地确定下来,但是我们可以从大脑中寻找灵感。
在神经科学中,我们可以从随机共振的角度来看待噪音。在这里,神经元的振荡性质清楚地表明,噪声并不总是干扰信号。相反,它能够通过在适当的时候推动神经元超过激活阈值来放大隐藏或“习得”的信号。这就是众所周知的共振,当能量以其自然频率输入系统时就会发生共振。大脑的节奏将这比作站在钢琴旁边——当力施加到钢琴附近的地板上时,钢琴的弦会振动。好的乐器能做到这一点是因为它们能放大声音,或者就大脑信号而言,它们能产生共鸣。如果不是通过共振,人工智能中的信号如何或是否被噪声放大还有待观察。现在,让我们仔细看看什么是梯度。
架构变化: 梯度下降/反向传播和长时程增强
神经网络在学习时会改变它们的连接。这导致更有效和更准确地处理它们的输入,将我们带到正确的输出,就像一幅图像是猫还是狗。人工神经网络对固定量的输入——训练数据——进行这种操作,而大脑则连续进行这种操作,但它们是如何做到的呢?
在人工神经网络中,连接不会像在大脑中一样出现或消失,它们只会变强或变弱。最终,目标是最小化网络输出中的误差,这可以使用成本函数来测量。这个成本函数就是我们的模型预测的答案和实际答案之间的误差平方和的平均值。这将我们带到梯度下降——我们称之为下降,因为目标是降低误差。梯度这个词指的是我们如何寻找这个最小误差——使用导数来寻找最陡下降的方向。我们可以将此想象为一个在山谷中滚动的球,它将向下运动,直到最低点,此时表面是平坦的(即导数为零)。在 2D 图中,如果斜率为负,我们将向右移动,如果斜率为正,我们将向左移动。这带来了一些挑战,主要是速度和找到真正的最小值,而不是在山谷中的两个山峰之间卡住,而附近还有一个表面。在一些网络中,梯度噪声不仅有助于防止过度拟合,还降低了训练损失,而在其他网络中,它有助于避免局部极小值。
梯度告诉我们如何最小化成本,反向传播是如何计算成本的。想象一个神经网络,其中输出层有 2 个神经元,一个将图像分类为树懒,另一个将图像分类为熊猫。激活程度较高的神经元将是网络预测的结果——那么当这一预测错误时会发生什么呢?我们不能直接改变激活,但我们可以改变前一层神经元的权重。
假设一个图像的正确答案是 panda,我们的 panda-node 只有 0.2 激活,而它应该是 1。我们可以通过增加积极联系的权重,减少消极联系的权重来提高这个数字。由于来自前一层的具有较大激活值的节点具有更强的效果,因此改变这些节点的权重将对损失函数产生更大的影响(无论权重是正还是负)。这可以与神经科学中的 Hebbian 学习相比较,在 Hebbian 学习中,一起放电的神经元之间的联系得到了最大程度的加强。
同时,我们可以尝试给与我们的 panda-node 有大量连接的节点一个更高的激活值,但是正如我们已经建立的,我们不能直接改变激活值。然而,为了实现这一点,我们可以调整从倒数第二层到该节点的权重。事实上,我们有,这就是为什么我们称之为反向传播。现在,回到我们的输出,懒惰节点将对每层权重应如何变化有自己的看法,因此反向传播取平均值,以最小化两者的损失(在现实生活中,这是对训练数据的子集进行的,也称为小批量,导致随机梯度下降)。
另一方面,大脑改变其连接的能力被称为突触可塑性,其中一种机制被称为长时程增强(LTP)。在这里,突触基于最近的活动而被加强/削弱,这被视为学习和记忆的基础。有几种具有不同属性的 LTP,包括 Hebbian-LTP,其中“一起放电的神经元连接在一起”,就像在人工神经网络中一样。然而,也有非 Hebbian-LTP,其中突触前和突触后神经元不需要一起放电,以及反 Hebbian-LTP,其中突触后神经元必须超极化。
到目前为止,对 LTP 最了解的例子是成人 CA1 海马区的 NMDA 受体依赖性 LTP。以此为例,我们可以探究一些最常见的属性。首先,这种 LTP 是输入特异性的,这意味着一个突触的 LTP 诱导不会改变其他突触。其次是关联性。这意味着当一个途径的活性不足以诱导 LTP 时,另一个途径的同时强活性能够在两个途径中诱导 LTP。最后,我们有持久性,这表明这种增强是长期的,持续几分钟到几个月。到目前为止,我们已经确定的这种现象背后的主要机制是树突棘的修改,树突棘是信号交换的微小突起。
随着我们越来越了解 LTP、神经元和突触,我们也就越来越了解大脑。随着人工神经网络的出现,我们正在接近我们建造像我们自己一样复杂的东西的潜力。
最初于 11 月 1 日由 安巴尔·克莱恩波特 发表,并在《分析》杂志 Vidhya 上发表
参考文献:
- https://neuro physics . ucsd . edu/courses/physics _ 171/Buzsaki % 20G。% 20 rhythms % 20 of % 20 the % 20 brain . pdf
- https://www . cell . com/neuron/pdf/s 0896-6273(16)30957-6 . pdf
- http://proceedings.mlr.press/v97/zhou19d/zhou19d.pdf
- 【https://openreview.net/pdf?id=rkjZ2Pcxe
- https://www.youtube.com/watch?v=aircAruvnKk&t = 203s
- https://www.youtube.com/watch?v=qPix_X-9t7E
神经网络和斐波那契数
好吧,数学是美丽的,也许是我们可以用来表达自然界模式的最好工具。一个比率形式的特殊数字在自然界中经常出现,它的性质吸引了一代又一代从事构思和探索的精英。
Does this spiral of Parthenon, ring a bell !!
嗯,不是别人,正是黄金比例!!在数学上,它被简单地定义为一个数,该数是由线段的较长部分除以较短部分得到的,等于这两个给定部分之和与较长部分之比。
(a+b)/a = a/b = φ
用 phi(φ)来表示。这个数字可以在整个自然界和时间的历史中看到。从历史上看,从埃及到希腊建筑,从达芬奇的“神圣比例”到萨尔瓦多·达利的艺术作品,这种比例一直在重复出现。一位名叫斐波那契的数学家在 1200 年左右发现了这个数列,它有一个独特的性质,可以表示为数列中前两项之和。这个数列也有与黄金分割率相关的特殊性质。这个序列中两个连续项的比率接近黄金分割率,当项变得更高时,值接近黄金分割率!!
L = φ, for the above mentioned limit at infinity.
简介:神经网络中的斐波那契数
神经网络使用人工神经元来理解和制定嵌套层次概念形式的人类智能。同时,人类和自然界中的许多事物都服从斐波那契数列。因此,在本文中,我们旨在复制 2000 年代的一项研究,该研究声称,以黄金比例作为学习速率的斐波纳契初始化权重矩阵在学习曲线性能方面将优于随机初始化。因为,这是一个合理的假设,相信随着性能的提高,神经网络方程确实用 Fibonacci 值表示其自然对应物,因为它是可调的权重。
因此,在本文中,我们将用斐波那契数初始化权重矩阵,并将它与随机初始化得到的结果进行比较。与 LabVIEW 中的早期研究不同,我们将针对相对复杂和庞大的 MNIST 图像数据集以及 tensorflow 的现代框架来测试我们的网络。在这之后,让我们从实验中观察成本函数学习曲线和准确性,并相应地得出结论。
让我们初始化:编码斐波那契权重
在用不同的斐波纳契数和来自该系列的权重矩阵的排列进行重复实验后。我们提供了一个按比例缩小到 0.001 倍的以下数字列表[0、1、2、3、5、8、13、21、34、55、89、144、233、377、610],这些数字随机排列在权重矩阵中,以获得更好的精度。这里,下面参考 784x100 权重矩阵上的可视化图,该图将输入图像像素映射到大小为 100 的隐藏单元。
Fibonacci Initialization
Fibonacci Initialization
这种可视化给出了关于为给定维度的权重矩阵生成的斐波纳契数列的分布的粗略想法,其以随机方式分布在数组元素上。下面是提到的代码,它将 X 和 Y 维度作为输入,并返回具有斐波纳契权重的给定大小的权重矩阵。
def fib_init(X_val,Y_val):
# Starting filling array values from F5 of Fibonacci
mul_fact = 0.001
fib_series = [0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
W = np.zeros((X_val, Y_val))for i in range(X_val):
for j in range(Y_val):
W[i][j] = random.choice(fib_series) * mul_fact
if(random.uniform(0, 1)<0.5):
W[i][j] = -W[i][j]
return np.float32(W)
# float type-casting is for maintaining compatibility with our tensor-flow code.
以类似的方式,我们设计了基于 Fibonacci 初始化的偏置矩阵*‘b’*的代码。经过反复实验,我们得出了以下值[5,8,13,21,34,55],按比例缩小到 0.01,以获得更好的偏置矢量精度。下面是一个类似的代码片段,它将向量的大小作为输入,并将 Fibonacci 初始化的向量作为输出返回。
def fib_bias(X_val):
mul_fact = 0.01
fib_series = [5, 8, 13, 21, 34, 55]
b = np.zeros(X_val)
for i in range(X_val):
b[i] = random.choice(fib_series) * mul_fact
if(random.uniform(0, 1)<0.5):
b[i] = -b[i]
return np.float32(b)
# float type-casting is for maintaining compatibility with our tensor-flow code.
将上述初始化与随机初始化进行比较,随机初始化即从均匀分布中产生随机数,并缩放到因子 0.01。参考下图,了解分布情况。
Random Initialization
Random Initialization
显然,上述初始化矩阵在初始化数据方面具有更高的幅度。此外,对于随机初始化技术,这导致数据中更多的变化。这可以通过对这两种初始化技术的直方图进行比较研究来观察。
Fibonacci Initialization
Random Initialization
显然,在我们当前设计的实验中,随机初始化具有更大的方差,与斐波那契权重相比,权重的范围要高得多。你可以参考 github 库,获取更新的实验(完成)的斐波那契初始化结果,该实验的数据方差几乎相等,数据分布相似。
让我们来比较一下:在 MNIST 运行我们的网络
在我们的实验中,我们训练了一个前馈神经网络,该网络仅具有单个隐藏层的 300 个隐藏单元输入,并使用交叉熵作为该模型的成本函数。对于与训练模型相关的代码,plot 实用程序脚本会引用 github 库。通过这个实验,我们想要比较和观察给定训练模型的损失函数的行为。损失函数是否真的像早期研究声称的那样收敛得更快,以及所使用的两种初始化的准确性。损失函数值越低,精度真的提高了吗?关于两种初始化的成本函数比较曲线,请参考下文。
Cross Entropy Loss Function Comparison
显然,我们可以观察到,利用上述成本函数值与历元数的关系图,模型在斐波纳契初始化上的训练确实优于具有低得多的值的随机初始化。即使在达到饱和之后,对于第 300 个时期,Fibonacci 初始化的损失也低得多。因此,我们的模型确实学习了训练样本到正确输出的非常精确的映射。
我们可以在测试集上比较准确性,看看哪个模型具有更好的准确性。现在,需要回答的一个重要问题是,随着成本函数值的降低,模型能够捕捉到 MNIST 数据集中的高方差,精确度确实得到了提高。意思是在这么多胡言乱语之后什么都没发生。让我们看看下面…
Model Accuracy Comparison 😠
随机初始化确实以 0.33%的小百分比优于我们的斐波纳契初始化的神经网络。但是,考虑到斐波纳契初始化权重的方差较小,斐波纳契初始化仍然产生了良好的精度,我们还需要进行更多的实验。因此,根据我们的结果,我们在训练集上获得了更好的成本函数收敛结果😉和在上述相同条件下重复实验时相对几乎相同或稍低的精确度😠。需要进行更多不同条件的实验。因此,旅程仍在继续!!
结论和未来范围
的研究走得很远,声称神经网络方程是自然重现的对应模式的真实表示,神经网络模拟其自然对应模式,权重为斐波那契数。事实上,我们的实验并不确定这一点,因为精度并没有提高很多,事实上结果是更低,但对于 Fibonacci 初始化的权重,损失函数确实更早得到最小化。这种行为需要一个合理的解释💭。
此外,探索不同的数学上合理的初始化似乎是一个非常酷的构思过程,并在其上对我们的神经网络管道进行建模。未来的工作将在 CNN、RNNs 和初始化数据的更高方差上进行类似的实验。同样,需要添加与 Xaviar 和 He 初始化的比较。关于更新,敬请关注 github 知识库 ( 进行中)以及本文的更新。
将非常感谢您的意见和建议,以改进我们的实验和提到的方法。感谢阅读!!
实验结果更新
- 基于高方差 Fibonacci 初始化权重的实验表明,对于这种实验来说,这是一条直线下坡路,并且精度随着基于完全随机分布的选择的较高 Fibonacci 权重而急剧下降。
神经网络和语言哲学
为什么维特根斯坦的理论是所有现代自然语言处理的基础
Photo by Alexandra on Unsplash
单词嵌入可能是人工智能历史上最美丽和浪漫的想法之一。如果语言哲学是探索语言和现实之间的关系以及我们如何能够进行有意义的对话以理解彼此的哲学分支,那么现代自然语言处理(NLP)中的这种非常具体的技术在某种意义上就是对上个世纪最相关的哲学家之一路德维希·维特斯坦根的理论的经验证明。对于维特根斯坦来说,词语的使用是社会语言游戏中的一步棋,由相互理解的社区成员进行。一个词的意义仅取决于它在上下文中的有用性,而不仅仅是与现有世界对象的 1:1 关系。
对于我们使用“意义”这个词的一大类情况,它可以这样定义:一个词的意义是它在语言中的用法。
当然,知道一个词的确切含义是一件复杂的事情,涉及许多不同的方面:它可能指代的对象,它是什么词性,它是否是一种习惯表达以及它可能带有的所有味道,等等。所有这些方面,最后都可以归结为一个:懂得利用。
的意思是的概念,以及为什么一组有序的字符在一种语言中具有特定的内涵,这不仅仅是哲学上的兴趣,而是可能是从事 NLP 工作的人工智能专家每天都必须面对的最大挑战。作为说英语的人,理解“狗”是一种“动物”,并且更像“猫”而不是“海豚”,这是非常琐碎的,但是这个任务远不容易以系统的方式来解决。稍微调整一下维特根斯坦的理论,我们可以说狗和猫很相似,因为它们经常出现在相同的上下文中:更有可能找到与“房子”和“花园”等词相关的狗和猫,而不是与“大海”和“海洋”等词相关的狗和猫。这种直觉是 Word2Vec 的核心,这是最著名和最成功的单词嵌入实现之一。如果今天的机器距离真正理解长文本和段落还很遥远,那么毫无疑问,单词嵌入是过去十年中允许该领域朝着这个方向迈出最大一步的唯一技术。
从 BoW 到 Word2Vec
许多计算机科学相关任务中的一个初始问题是用数字形式表示数据;单词和句子可能是以这种方式表示的最具挑战性的数据类型。在我们的设置中,从由 D 个不同单词组成的词汇表中选择单词,集合中的每个单词都可以关联到一个数字索引 i 。几十年来使用的经典方法是将每个单词表示为一个 D 大小的数字向量,由除了位置 I 处的 1 之外的所有 0 组成。以仅由 3 个单词组成的词汇为例:“dog”、“cat”和“dolphin”(D = 3)。每个单词可以表示为一个 3 维向量:“狗”对应于[1,0,0],“猫”对应于[0,1,0],“海豚”,显然对应于[0,0,1]。作为一个简单的扩展,文档可以表示为一个 D 大小的向量,其中每个元素计算文档中第 I 个单词的出现次数。这种方法被称为单词袋(BoW ),已经使用了几十年。
虽然 BoW 在 90 年代取得了成功,但它缺少一个非常酷的词汇特征:意义。我们知道两个非常不同的单词可能有相似的意思,即使从正字法的角度来看它们完全不同。“猫”和“狗”都代表宠物,“国王”和“王后”的意思完全一样,只是体裁不同,“苹果”和“香烟”完全没有关系。我们知道这一点,但是使用弓模型,它们在向量空间中的距离都是一样的,1。同样的问题也可以扩展到文档:使用 BoW,我们可以说,只有当两个文档在一定次数上包含完全相同的单词时,它们才是相似的。这就是 Word2Vec 的用武之地,它将维特根斯坦 60 年前在他的哲学研究中所做的大量哲学讨论用机器学习的术语表达出来。
给定大小为 D 的字典,其中单词由其索引标识,目标是学习每个单词的 N 大小的向量表示,其中 N <<d. ideally=“” we=“” want=“” this=“” n-sized=“” vector=“” to=“” be=“” dense=“” and=“” able=“” represent=“” some=“” semantic-specific=“” aspects=“” of=“” meaning.=“” for=“” example=“” that=“” class=“ls”>、狗和猫具有相似的表示,而“苹果”和“香烟”、在向量空间中具有非常远的表示。我们希望能够对像 king+woman-man = queen 这样的向量进行一些基本的代数运算,或者说代表“男演员”和“女演员”的向量之间的距离和“王子”和“公主”之间的距离差不多。尽管这些结果非常理想化,但实验表明通过 Word2Vec 获得的载体表现出与这些非常接近的性质。</d.>
Word2Vec 不直接学习这些表示,而是作为无监督分类任务的副产品获得它们。一个平均的 NLP 数据集(称为语料库)由一组句子组成;属于一个句子的每个单词都出现在周围单词的上下文中。分类器的目标是在给定其上下文单词作为输入的情况下预测目标单词。提取像“一只棕色的狗在花园里”这样的句子,单词[a,brown,is,in,the,garden]被提供作为模型的输入,输出单词“dog”是要预测的单词。这项任务被认为是无监督的学习,因为语料库不需要使用外部真实来源进行标记:给定一组句子,总是可以自动创建正面和负面的例子。将“一只棕色的狗在花园里”视为正面示例,我们可以创建大量负面样本,如“一架棕色的飞机在花园里”或“一只棕色的东西在花园里”,用从数据集中提取的随机单词替换目标单词“狗”。
现在维特根斯坦的理论的切入点已经很清楚了:语境对于学习嵌入是至关重要的,正如在他的理论中赋予意义是至关重要的一样。正如两个单词具有相似的意思一样,它们将具有相似的表示(N 维空间中的小距离),因为它们经常出现在相似的上下文中。所以“猫”和“狗”将最终具有相近的向量,因为它们经常出现在相同的上下文中:模型对它们使用相似的嵌入是有用的,因为这是在给定上下文的情况下预测两个单词时具有更好性能的最方便的事情。
原始论文提出了两种不同的体系结构:CBOW 和 Skip-gram。在这两种情况下,单词表示与特定于味道的分类任务一起被训练,提供最佳可能的向量嵌入,最大化模型的性能。
Figure 1 — Architecture comparison between CBOW and Skip-gram
CBOW 代表连续单词包,其目标是在给定输入上下文的情况下正确预测单词。输入和输出被提供为 D 大小的向量,并被投影到共享权重的 N 大小的空间中。用于将 D 大小的向量投影到 N 大小的内部向量的权重是我们正在寻找的嵌入。基本上,单词嵌入被表示为一个 D×N 矩阵,其中每行代表词汇表中的一个单词。所有上下文单词被投影到相同的位置,并且它们的向量表示被平均化;因此,单词的顺序不影响投影。
Skip-gram 做了同样的事情,但是又恢复了:试图预测作为目标词输入的 C 上下文词。预测多个上下文单词的问题可以被重塑为一组独立的二元分类任务,现在的目标是预测上下文单词的存在(或不存在)。
根据经验,Skip-gram 需要更多的时间来训练,并且通常会给出稍微好一点的结果,但是,像往常一样,不同的应用程序有不同的要求,并且很难预先预测两者中哪一个会优于另一个。由于优化模型权重所需的数据量和计算能力,这个概念看起来很简单,训练这种架构是一场噩梦。幸运的是,一些预先训练好的单词嵌入可以在网上找到,并且只需几行代码就可以探索向量空间——最有趣的部分。
可能的改进:手套和快速文本
在经典的 Word2Vec 之上,并遵循或多或少相同的方法,在过去几年中已经提出了大量可能的改进。最有趣和最常用的两个是 GloVe(由斯坦福大学开发)和 fastText(由脸书开发),主要是因为它们强调并试图克服原始算法的局限性。
在原始 GloVe 论文中,作者强调了在单独的本地上下文中训练模型如何很好地利用了语料库的全局统计数据。克服这个限制的第一步是创建一个全局矩阵 X ,其中每个元素 I,j 计算单词 j 在单词 i 的上下文中出现的次数。本文的第二个最大贡献是理解了这些原始概率本身在确定意义方面并不强大,引入了一个共现矩阵,从这个矩阵中可以直接提取意义的某些方面。
考虑两个单词 I 和 j,它们展示了感兴趣的特定方面;具体来说,假设我们对热力学相的概念感兴趣,我们可以取 i =冰,j =蒸汽。可以通过研究这些词与各种探测词 k 的共现概率的比率来检查这些词的关系。对于与冰而不是蒸汽相关的词 k,假设 k =固体,我们预计比率 Pik/Pjk 将很大。同样,对于与蒸汽有关但与冰无关的单词 k,比如说 k =气体,比例应该很小。对于像水或时尚这样的词,要么与冰和蒸汽都有关系,要么两者都没有关系,比率应该接近 1。
这个概率比现在是学习嵌入的起点。我们希望能够计算出与特定函数结合的表示,F 在嵌入空间中保持这个比例常数。
Figure 2 — Most general formula for GloVe embeddings
函数 F 和单词 k 的相关性可以被简化,并由指数和固定偏差代替,作为结果给出这个最小平方误差函数 J :
Figure 3 — Final scoring function for computing GloVe embeddings
函数 f 是一个评分函数,它试图不对太频繁和太罕见的共现进行加权,而 bi 和 bj 是用于恢复函数对称性的偏差。在论文的最后几段中,展示了如何训练该模型,最终与训练经典的跳格模型没有太大的不同,即使经验测试显示 GloVe 如何优于 Word2Vec 实现。
另一方面,fastText 对 Word2Vec 提出了完全不同的批评:从 D 大小的 one-hot 编码向量开始训练模型的缺点是忽略了单词的内部结构。fastText 提出学习字符 n-gram 的表示,并将单词表示为 n-gram 向量的总和,而不是一次性编码单词来学习单词表示。例如,在 n=3 的情况下,单词“flower”被编码为 6 个不同的 3-gram[<fl、flo、low、owe、wer、er > ]加上特殊序列< flower >。注意尖括号是如何用来表示单词的开始和结束的。因此,一个单词由其在单词字典中的索引及其包含的 n 元语法集来表示,并使用哈希函数映射到整数。这个简单的改进允许跨单词共享 n 元语法表示,并计算没有出现在训练语料库中的单词的嵌入。
实验和可能的应用
正如所承诺的,使用这些嵌入只是几行 Python 代码的问题。我用一个 50 码大小的手套模型和一个 300 码大小的 fastText 模型进行了一些实验,前者训练了 60 亿个单词,这些单词是从主要在维基百科上检索的句子中提取的,后者训练了 6000 亿个令牌。在这一段中,来自两者的结果混合在一起,只是为了证明概念并给出对主题的一般理解。
首先,我想测试一些基本的单词相似性,这是单词嵌入的最简单也是最重要的特性。不出所料,与“狗”这个词最相似的词是“猫”(0.92)、“狗”(0.85)、“马”(0.79)、“小狗”(0.78)、“宠物”(0.77)。请注意,复数形式与单数形式的意思非常相似。再说一次,对我们来说这么说是很琐碎的,但对机器来说,这是完全不同的事实。现在的食物:和“披萨”最相似的词是“三明治”(0.87)、“三明治”(0.86)、“零食”(0.81)、“面包店”(0.79)、“薯条”(0.79)、“汉堡”(0.78)。有道理,结果令人满意,模型表现相当好。
下一步是尝试在向量空间中执行一些基本代数,以检查我们的模型是否正确地学习了一些期望的行为。“女演员”(0.94)这个词可以作为女人+演员-男人的结果得到,“国王”(0.86)作为男人+女王-女人。一般来说,如果在意义上 a : b = c : d,单词 d 应该是 d = b-a+c。更进一步说,这种向量运算甚至能够描述地理方面,这令人难以置信:我们知道罗马是意大利的首都,因为柏林是德国的首都,事实上柏林+意大利-罗马=德国(0.88)和伦敦+德国-英格兰=柏林(0.83)。
现在最有趣的部分,按照同样的想法,我们可以尝试加减概念,看看会发生什么。例如,意大利人的比萨饼在美国相当于什么?披萨+美国-意大利=汉堡(0.60),其次是芝士汉堡(0.59)。自从我搬到荷兰,我总是说这个国家是三种东西的混合体:一点点美国资本主义、瑞典人的冷漠和生活质量,以及最后一点点那不勒斯的繁荣。稍微调整一下原始定理,去掉一点瑞士精度,我们得到荷兰(0.68)为美国+瑞典+那不勒斯-瑞士:老实说,相当令人印象深刻。
Figure 4 — To all the Dutch readers: take this as a compliment. Ok?
可以在这里和这里找到使用这种预训练嵌入的良好动手起点。Gensim 是一个用 Python 编写的简单而完整的库,有一些现成的代数和相似函数。这些预先训练的嵌入可以以许多不同的(和有用的)方式使用,例如,提高情感分析器或语言模型的性能。而不是喂养这些模型(不管他们的任务是什么!)对于一个热编码字,使用这些 N 大小的向量将显著提高性能。当然,训练特定领域的嵌入可以带来更好的性能,但是训练这种架构所需的时间和精力可能有点多余。
神经网络:基础
Auditory learner? Listen to this article in podcast form instead!
人工神经网络(ann)是机器学习领域的热门话题。因此,大量的研究正在进行。计算机视觉对噪音数据的容忍度、自动驾驶汽车对道路路线的预测,以及自然语言处理(NLP)的进步,使你可以与你的语音助手交流,这些都归功于人工神经网络。了解神经网络的基础知识将有助于你参与到围绕这个话题的对话中。
让我们从定义开始:人工神经网络是一种数学结构,当给定输入时,它可以映射到期望的输出。这样,十几个问题就会浮现在你的脑海里。让我们继续回答一些常见问题,以了解神经网络的基础知识。
谁发明了神经网络?
这个答案会因你问的人而异。有些人相信沃伦麦卡洛克和沃尔特皮茨的第一个理论。他们被认为描述了一个神经元如何有一个数学表示。然而,在这篇文章中,我们说的是一位名叫弗兰克·罗森布拉特的心理学家。
罗森布拉特
罗森布拉特在 1957 年发表了一篇名为“感知机:感知和识别自动化”的论文。该出版物描述了神经网络的构建模块,感知器。他描述了这些人工神经元如何从数据中学习。他被认为创造了监督学习,允许神经元根据其准确性改变自己的权重。
麦卡洛克和皮茨
麦卡洛克和皮茨在 1943 年发表了一篇名为“神经活动中固有观念的逻辑演算”的论文。他们极大地影响了罗森布拉特的研究。在那篇论文中,他们描述了人类神经元如何在生物神经网络的“全有或全无”特征中进行数学表示。
当神经元接收到一个信号时,它不会自动开始向下游传递信号。它会保持信号,直到达到阈值,然后它沿着轴突发送信息,被邻近的细胞接收。
Hebb
神经心理学的心理学家先驱唐纳德·赫布(Donald Hebb)在 1949 年发表了一篇名为“行为的组织:一种神经心理学理论”的论文。这篇开创性的论文产生了心理学中一个全新的规则,叫做赫布规则。该规则描述了一个神经元如何刺激另一个神经元,在重复激活后,细胞 A 变得有效地激活细胞 b。用 Hebb 的话说,“一起放电的神经元连接在一起”。
“当 A 细胞的轴突足够接近以激活 B 细胞,并重复和持续地参与其激活时,在一个或两个细胞中发生某种类型的生长过程或代谢变化,从而增加 A 细胞激活 B 细胞的效率”
赫布规则定义
什么是感知器,它是如何组成神经网络的?
感知器是神经网络的构建模块,类似于核酸、脂类、碳水化合物和蛋白质的生物构建模块。四个部分也构成了这些:
- 输入值
- 权重和偏差
- 求和函数
- 激活功能
输入值受到预定权重值的影响,然后在求和函数中相加在一起。在求和函数之后,该值在激活函数中被压缩在-1 和 1 之间或 0 和 1 之间。这将决定感知器是否会被激活。值越负,越接近最小值(-1 或 0),值越正,越接近最大值(1)。如果它被激活,那么输出将沿着它的路径发送。
单一感知器
如果感知器是单一形式的,那么第一个也是唯一的输出将是 yes 或 no 格式。单感知器非常适合线性可分性数据集,即可以使用具有恒定斜率的单条线来分离的组。
感知器对于“与”、“或”、“异或”逻辑门来说非常优秀。让我们来分解一下:
如果两个输入都为真,那么结果逻辑将为真。
或者,如果一个或两个输入为真,则推理结果为真。
XOR ',exclusive 'OR ',如果信息中的一个(但不是两个)为真,则命题将得出 true。
神经网络
然而,如果有一个以上的感知器存在并以分层的方式连接,我们就产生了一个神经网络。第一层的输出成为第二层的输入,依此类推,直到输出层对总激活进行求和。总激活度是网络最终决策的置信度。
神经网络有哪些层?
神经网络有 3 层:
- 输入层
- 隐蔽层
- 输出层
输入层是网络的起点。这是将用于预测的值引入的图层。隐藏层是网络发挥其“魔力”的地方。在整个区域计算输入值的激活量。隐藏层可以小到 1 层,也可以大到项目所需的数量。最后,输出层是每个最终节点的激活用于选择解决方案的地方。
如您所见,每个单元都连接到后续层的每个单元。这使得附近的感知器可以相互通信,并创建最适合其使用的权重。
只要记住,第一层是输入,最后一层是输出。中间的任何东西都是隐藏层。
计算机如何“看见”神经网络?
经常用于表示神经网络的图表(如上图所示)是人类友好的版本。计算机如何处理和观察它们是以矩阵的形式出现的。
我们将首先讨论前馈或训练部分。这是使用矩阵乘法完成的。
矩阵乘法
让我们分解一个具有 2 个输入值的神经网络,1 个隐藏层包含 3 个节点,我们以 2 个输出层节点结束。
我们将通过对每个元素使用唯一的字母来保持这一点,以便您可以在我们进行的过程中引用它。
权重 x 输入层
矩阵乘法是通过取第一矩阵的行并将每个元素与第二矩阵中的相应元素相乘来完成的。该操作的主要规则是第一个矩阵中的列数必须与第二个矩阵中的行数相匹配。让我们看一下将用于该网络的第一组矩阵。
正如我们所看到的,如果输入值的矩阵是第一个,我们将得到一个未定义的结果,因为上面的规则不被遵守。然而,如果我们翻转矩阵,我们将能够执行乘法。结果/输入矩阵作为第二个或右矩阵,权重矩阵作为第一个或左矩阵。
让我们在这个网络中执行第一次乘法。
我们得到的矩阵包含 3 行,分别对应于隐藏层中的 3 个节点:
权重 x 隐藏层
让我们做最后的乘法。
输出矩阵具有最终结果,它包含与输出层的 2 个节点相关的 2 行:
上述等式的结果将是每个神经元的激活水平。如果 O 0 高于 O 1,那么与 O 0 相关的预测将作为解给出。
神经网络是如何“学习”的?
神经网络分两步学习,前馈(我们刚刚讲过)和反向传播。反向传播本身可以分为两步,计算成本,然后最小化成本。
成本是网络的预测值和数据集的期望值之间的差值。成本越大,误差越大。目标是尽可能降低成本。为了实现这一目标,通过改变权重和偏好来最小化成本是游戏的名称。简单来说,它的前馈是反向的。你正在做矩阵乘法来改变权重,以便根据某些神经元将接收到的内容来给予它们更多的强调。
最小化成本函数的一种常见方法是通过梯度下降。
梯度下降
目标是通过合计实际和预期输出之间的所有差异,然后将其乘以学习率,找到函数的全局成本最小值。最常见的成本函数是均方误差。
J(θ)由梯度下降函数调用。
学习率α基本上是收敛的一大步(换句话说就是找到全局最小值)。为了给你一个视觉效果,想象你站在山顶上,下面是一个美丽的山谷。你开始沿着山坡往下走。对抗听从你内心孩子的冲动,快速滚下山(可能错过你的目标),你从容不迫,轻松地走下来,避开路上的任何石头和树木。
学习率类似于你要走多大步或方法才能到达山谷。如果学习率太大,你可能会继续滚向另一边,并且由于你滚的冲力而完全错过山谷。如果学习率太小,那么在你到达山谷(最佳目标)之前,天就已经黑了。为您的模型找到合适的学习速率对于创建有效且高效的神经网络至关重要。
如果你想知道从哪里开始机器学习的自学,请查看学习机器学习的 5 个简单步骤。这篇文章将帮助你有效地学习这个广泛的主题。
在我们重新学习之前,
神经网络,去神秘化
Image by Gerd Altmann from Pixabay
你肯定听说过神经网络——这种神秘的、科幻般的技术成为了一个伟大的时髦词汇。但是作为一个非技术人员,你已经把它们当作一个只留给计算机科学书呆子(像我一样)的谜而一笔勾销了。今天,这一关于它们如何工作的初级读本改变了这一点,它是为对计算机科学、编码或数学一无所知的人设计的。
什么是神经网络?
神经网络可以被认为是一个人工信息处理器。它接受输入,以某种方式进行处理,然后产生一些输出。网络的结构决定了它如何进行处理,不同的结构产生不同的输出。其结果是网络可以对图像进行分类,翻译语言等等。
我们很快就会看到,网络的某些部分是固定的,而其他部分,即参数,是可以改变的。我们的目标是调整这些参数,使我们的网络学会解决问题。最初,我们的网络在完成任务时会非常糟糕,就像一个孩子在做微积分一样,因为这些参数是随机设置的。但是,随着我们反复测试网络,并根据其响应更新参数,随着时间的推移,它会变得更好。不出所料,这种测试和更新的重复过程意味着训练数据是神经网络的一大部分。
让我们来看看神经网络是什么样子的。
网络体系结构
神经网络的原始动机是人脑中的神经元,其具有几个重要特征:
- 我们大脑中的神经元通过一个巨大的网络相互连接,其中一些神经元的输出可以作为其他神经元的输入。
- 神经元之间的连接强度可以根据使用频率而变化,这导致了唐纳德·赫布的流行短语“一起放电的神经元,连接在一起”。
- 神经元中的电化学电势可以增加,但神经元不会“激发”,直到电势超过某个阈值。
让我们看看是否可以通过观察神经网络的构建模块——感知器——来人工复制其中的一些功能。
*在上图中,我们已经表示了两个相连的神经元 A 和 C,其中神经元 A、 *x、的输出等于神经元 C 的输入。我们将用节点(圆圈)表示神经元,用边(线条)表示神经元之间的连接。你可以这样想象一个神经元:它接受一些输入,保存一个值(它的输入的某种组合),然后将该值作为输出传递。到目前为止,这个模型满足上面列出的第一个特征。让我们介绍一下连接强度。
我们可以通过引入一个连接* 权重 w来改变连接的强度,神经元 C 的输入现在将是神经元 A 的输出 x ,乘以权重 w 。直觉上, w 的值越大(越小),两个神经元之间的联系越强(越弱)。这满足了第二个特征。最后,我们来介绍一下潜在门槛。*
我们现在引入了另一个神经元 B,它的值为 b ,连接权重为-1。b 是众所周知的偏差,我们很快就会知道为什么。对 C 的输入成为 A 和 B 的加权和,即 w x + (-1)b .接下来,我们对 C 处的输入应用阶跃函数定义为 f(x) = 1 如果 x > 0,0 否则。
The step function
总而言之,如果 w x -b > 0,则 C 处的值变为 1,否则为 0。我们到底为什么要这么做?嗯,如果 w x < b,C 处的值将等于 0。换句话说,偏差 b 充当一个阈值,我们需要通过该阈值才能使 C 处的值不为 0。这和前面讨论的神经元的第三个特征一模一样!正因为如此,我们称阶跃函数为“激活函数”。**
只有一个问题。x = 0 处阶梯图的垂直部分意味着它不可微。如果你不知道那是什么意思,不要着急(不满意看结论)。你只需要知道,我们可以用 sigmoid 函数来近似阶跃函数。
The Sigmoid function
您可以将 sigmoid 函数视为所有可能输入的“压缩”,以适应 0 和 1 之间的值。x 越大(越小) sigmoid(x) 越接近 1 (0)。
我们可以扩展当前的模型,让许多神经元提供输入,每个神经元都有自己的权重。请注意,其中只有一个是偏差。同样,输入成为它之前的神经元的加权和(每个节点的输出与其连接权重的乘积)。
既然如此,为什么不在每一层增加几个节点,增加几层连接呢?我们称第一层和最后一层之间的层为“隐藏层”。这里,每一层将只有一个偏差。
我们通常从填充最左边的神经元层开始,通过计算下一层中每个神经元的值在网络中“向前”移动,等等。最后,我们可以计算输出层中神经元的值。
我们之前说过,我们的网络中有一些固定的特征和一些参数。一般结构,即层数、每层节点数和激活函数是固定的。根据我们在网络中前进的方式,给定神经元及其前面的权重,每个神经元的值是确定的。因此我们唯一能改变的,我们的参数,变成了神经元之间连接的权重。
既然我们已经了解了什么是网络,那么让我们来看看如何使用它来解决问题。
它如何“学习”
我们将看看最著名的机器学习任务之一,识别手写图像。
学习的一般过程是这样的:
- 定义一个网络
- 将图像传入网络(输入)
- 网络将预测图像的标签(输出)
- 使用预测以网络“学习”的方式更新网络
- 返回第二步并重复
让我们假设每个图像都是 28x28 (784)像素,并且因为它们是灰度的,所以每个像素的值的范围从 0(黑色)到 1(白色)。为了训练网络,我们需要图像及其相关标签形式的训练数据。
我们网络的第一层将代表数据;这就是我们如何将一个数据点(一幅图像)输入我们的网络。在第一层中将有 784 个神经元(加上一个偏差),并且每个神经元的值将是来自训练图像的一个像素的值。网络中的最后一层将代表输出;图像标签的模型预测。这一层将有 10 个神经元,神经元 i 中的值越接近 1,模型越认为图像具有标签 i 。
最初,我们将图的权重设置为随机值,这就是为什么最初的预测不会很好。选择隐藏层的数量和每层中神经元的数量是一个很难解决的问题,我们将跳过这个问题。出于教育目的,让我们假设有一个 10 个节点的隐藏层,看一个例子。
在这个例子中,图像的值被输入到模型中,我们通过网络向前移动来计算输出神经元的值。该模型认为图像是 4,因为第 4 个神经元的输出最接近最后一层的 1。
如前所述,目标是更新图的权重,以便更好地对数据进行分类。我们怎么才能让它做到这一点?为了做到这一点,我们首先需要定义一个损失函数,在做出预测后,它给我们一个量化的衡量模型表现好坏的方法。一个例子是平方误差损失。我们从图像的标签中知道它是 5,所以我们理想的是输出层的每个神经元都是 0,除了第 5 个应该是 1。下面是我们计算预测损失的方法:
如果模型在正确预测标签方面做得非常好,损失的总和将接近于 0。
使用损失函数和一些被称为“反向传播”的应用微积分(我们将跳过),我们可以找到我们应该如何调整权重以最小化损失函数。换句话说,我们可以找出方向(更大或更小)和每个权重应该改变的量,以便使图表更好地预测这个特定图像的。但是我们不希望它只学习预测这张图像,我们希望它能够预测数据集中的所有图像,并且能够推广到新的图像。所以我们只在反向传播建议的方向上稍微更新一下权重。如果我们对许多不同的图像重复这个过程很多次,网络将学习能够很好地分类手写图像的权重。
这已经很多了,让我们来回顾一下:
- 网络有代表神经元的节点和代表连接权重的边。我们的目标是以这样一种方式调整权重,使流程能够学习完成一项任务。
- 我们使用输入层将数据传递到网络中,其中每个节点的值对应于图像中的一个像素。
- 然后,我们通过图表向前移动,计算训练示例的预测输出。网络的预测最初会很糟糕,因为权重是随机设置的。
- 我们使用损失函数来计算错误程度的量化指标。
- 使用损失函数,我们执行反向传播来确定方向,以及每个权重应该调整多少来最小化该训练示例的损失函数。**
- 我们对权重进行少量更新,并对许多不同的训练示例进行重复
结论
一旦你看到神经网络是如何运作的,它们看起来更像是人工的而不是智能的。我希望从这本初级读本中,你能受到启发,进一步研究它们。为了简单起见,我们跳过了许多重要的想法,其中最主要的是反向传播,尽管它是大多数神经网络的核心,但对于这样的文章来说太“数学化”了。对于感兴趣的人来说,我们需要用 sigmoid 函数代替阶跃函数,因为反向传播依赖于微分,而阶跃函数没有导数。我们建立的特定网络被称为前馈全连接网络。在实践中,卷积神经网络可以更好地识别手写图像。最后,如果你想进一步探索机器学习的世界,我推荐 3blue1brown 的精彩视频系列 (~1 小时)。
神经网络:初学者用。由初学者。
一个足智多谋的初学者指南神经网络的本质和实施
Photo by Bit Cloud on Unsplash
挺住!为什么要看一个初学者写的文章?答案很简单——我决定写一篇关于神经网络的文章,它是用一种简单的语言写的,即使像我这样的初学者也能理解,同时也足够足智多谋,可以帮助某人很好地掌握这一庞大的材料。
先决条件
您需要具备以下方面的基本知识:
- 线性代数
- 计算机编程语言
- NumPy
你不需要擅长这些,但是如果你以前用过的话会容易得多。
密码
我在整篇文章中放了你需要的每一段代码,但是如果你想拥有整段代码,这里有 Jupyter 笔记本:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/KrumovAI/Neural-Networks-From-Scratch/blob/master/neural_network.ipynb)
介绍
神经网络。这是大多数普通编码人员在听到人工智能和/或机器学习这些流行语时首先想到的。虽然不是书中最基本的材料,但如果用初学者友好的语言来解释,它实际上是一个不错的起点。
在整篇文章中,我将带您开始一段旅程,从神经网络思想的最开始开始,带您通过使其学习的核心现代原则,最后向您展示一个从头开始的神经网络模型的一步一步的实现,其特点是完全连接、激活、扁平化、卷积和池层。这个实现很大程度上基于并受到了 Omar Aflak 的这篇令人惊叹的文章的启发,这篇文章是每个想要了解更多关于神经网络的数学背景的人的必读之作。
制作自己的机器学习库。
medium.com](https://medium.com/datadriveninvestor/math-neural-network-from-scratch-in-python-d6da9f29ce65)
理解神经网络
神经网络的历史可以追溯到 1943 年,当时神经生理学家沃伦·麦卡洛克和数学家沃尔特·皮茨描绘了一个带有简单电子电路的人脑神经元模型,该电路采用一组输入,将它们乘以加权值,并使它们通过一个阈值门,该阈值门根据阈值给出 0 或 1 的输出值。这个模型被称为麦卡洛克-皮茨感知器。
McCulloch-Pitts perceptron | Source: Wikimedia Commons
一位名叫罗森布拉特的心理学家进一步发展了这一想法,他创建了感知器的数学模型,并将其命名为 Mark I 感知器。它基于麦卡洛克-皮茨模型,是让机器学习的最初尝试之一。感知器模型也接受一组二进制输入,然后乘以加权值(代表突触强度)。然后添加一个值通常为 1 的偏置(该偏置确保使用相同的输入可以计算更多的函数),并再次基于阈值将输出设置为 0 或 1。上面提到的输入要么是输入数据,要么是其他感知器的输出。
虽然麦卡洛克-皮茨模型在当时是一项开创性的研究,但它缺乏良好的学习机制,这使得它不适合人工智能领域。
罗森布拉特从唐纳德·赫布(Donald Hebb)的论文中获得灵感,即学习通过神经元之间突触的形成和变化发生在人脑中,然后提出了以自己的方式复制它的想法。他想到了一种感知器,这种感知器接受一组输入-输出示例的训练集,并通过改变感知器的权重来形成(学习)一个函数。
实施分四步进行:
- 用随机权重初始化感知器
- 对于训练集中的每个示例,计算输出
- 如果输出应该是 1,但却是 0,则用输入 1 增加权重,反之亦然-如果输出是 1,但应该是 0,则用输入 1 减少权重。
- 对每个示例重复步骤 2-4,直到感知器输出正确的值
这套指令是现代感知机的基础。然而,由于计算能力的显著提高,我们现在可以与更多的感知器一起工作,形成一个神经网络。
Source: mlxtend
然而,它们并不只是随机放在网络中,而是实际上是另一个构建块(层)的一部分。
层
一个层由感知器组成,这些感知器连接到前一层和下一层的感知器,如果这样的感知器确实存在的话。每一层都定义了自己的功能,因此服务于自己的目的。神经网络由输入层(获取初始数据)、输出层(返回网络的整体结果)和隐藏层(一个或多个具有不同大小(感知器数量)和功能的层)组成。
Source: cs231n.github.io
为了使网络能够学习并产生结果,每一层必须实现两个功能— 正向传播和反向传播(简称为反向传播)。
Base Layer Class
想象一列火车行驶在 A 点(输入)和 B 点(输出)之间,每次到达其中一个点时都会改变方向。从 A 到 B 的过程从输入层提取一个或多个样本,并将其连续通过所有隐藏层的前向传播函数,直到到达 B 点(并产生结果)。反向传播基本上是相同的事情,只是方向相反-本课程以相反的顺序通过所有图层的反向传播方法获取数据,直到数据到达点 a。但这两个课程的不同之处在于这些方法内部发生的情况。
正向传播只负责通过函数运行输入并返回结果。没有学习,只有计算。反向传播有点棘手,因为它负责做两件事:
- 更新层的参数,以提高正向传播方法的准确性。
- 实现正向传播函数的导数并返回结果。
那么这到底是怎么发生的,为什么会发生。谜团在 B 点解开——在火车改变方向并通过所有层的反向传播之前。为了调整我们的模型,我们需要回答两个问题:
- 模型的结果与实际产出相比有多好?
- 我们如何最小化这种差异?
回答第一个问题的过程被称为计算误差。为此,我们使用成本函数(与损失函数同义)。
成本函数
有不同类型的成本函数进行完全不同的计算,但都服务于相同的目的-显示我们的模型离实际结果有多远。选择成本函数与模型的目的密切相关,但在本文中,我们将只使用最流行的一种方法——均方误差(MSE)。
Formula for Mean Squared Error(MSE) | Source: DataQuest.io
这是一个非常简单的函数——我们对实际输出和模型输出之间的差的平方求和,然后计算平均值。但是帮助我们的模型只实现 MSE 不会有任何显著的帮助。我们也必须实现它的衍生物。
但是我们为什么需要这个呢?因为臭名昭著的…
梯度下降
这里我们需要做的最后一件事是向我们的模型展示如何最小化误差。为此,我们需要一个优化算法(optimizer) 。同样,有许多种类的优化器都服务于相同的目的,但为了保持简单但仍然有意义的事情,我们将使用最广泛使用的一个,许多其他优化算法的基础。看这强大的梯度下降:
Graphical representation of Gradient Descent | Source: Medium
看起来不像听起来那么可怕,对吧?好消息,这是一个相对简单的概念。根据定义,梯度是一个有趣的词,表示导数,或者函数的变化率。
3D representation of Gradient | Source: OReilly
假设我们的模型是一个球。该表面表示误差的梯度(导数)。我们希望球滚下表面(下降)尽可能低,以降低高度(误差)。从数学层面来说——我们需要达到一个全局(或者至少是一个足够好的局部)最小值。
为了让球移动,我们需要以一定的速率更新我们的参数——称为学习速率。这是一个预定义的参数,我们在运行模型之前将它传递给我们的模型。这种参数被称为超参数,在我们的模型性能中有着巨大的作用。我的意思是:
Significance of Learning Rate | Source: analyticsvidhya.com
如果我们选择一个太大的学习率,参数将会剧烈变化,我们可能会跳过最小值。另一方面,如果我们的学习率太小,那么要达到令人满意的结果将花费太多的时间和计算能力。这就是为什么通过用不同的学习率值测试模型来调整这个参数是相当重要的。强烈建议从 0.1 或 0.01 的学习率开始,并从那里开始调优。
背靠背(传播)
现在,我们需要通过将适当的数据传递给反向传播方法来逐层更新模型的参数。反向传播有两个参数——输出误差和学习速率。输出误差的计算方式可以是成本函数的导数,也可以是前一层反向传播的结果(从 B 点到 A 点),如上所述,反向传播应该给出正向传播函数的导数。通过这样做,每一层向它的前一层显示它的错误。
换句话说,如果出于某种原因,我们有一个正弦层,它看起来会像这样:
现在我们已经得到了所需的两个参数,反向传播应该更新层权重(如果存在的话)。由于每种类型的层都是不同的,因此它定义了自己的参数调整逻辑,这一点我们稍后会谈到。
结束梯度下降
当每一层的反向传播完成,我们的列车到达 A 点时,它获取下一个样本(或样本集),并再次通过隐藏层的前向传播函数开始它的过程——只是这一次,它们应该表现得更好一点。这个过程不断继续,直到训练完成和/或达到最小误差。
现在我们已经解释了梯度下降背后的所有理论,下面是它在代码中的样子:
我希望这段代码片段能对算法本身给出更多的解释。唯一我们还没有完全覆盖的是我们可以在网络中使用什么类型的层以及如何实现它们。
基本层
对于初学者来说,似乎有很多种层可供选择,臭名昭著的全连接层无疑是最佳选择。
全连接的
全连接层是使用最广泛的类类型。其工作原理基于罗森布拉特模型,具体如下:
- 来自前层的每一个感知器都链接到这层的每一个感知器。
- 每个环节都有一个加权值(weight)。
- 一个偏差被添加到结果中。
- 该层的权重保存在一个 2D 数组中,大小为***【m】xn***(其中 m 是前一层的感知器数量, n 是该层的感知器数量)。它们被初始化为随机值。
- 该层的偏差保存在大小为 n 的 1D 数组中。它被初始化为随机值。
Visual representation of Fully-Connected(FC) Layer | Source: cs231n.github.io
现在让我们来看看我们的实现:
正如你所看到的,只要你知道基本的线性代数,我们的 to 方法的实现并不复杂。虽然相对简单,但这是一个完全有用且优化的层实现,我们将很容易在以后使用它。
然而全连接层的唯一问题是它们是线性的。事实上,大多数层都有完全线性的逻辑。线性函数是一次多项式。仅使用这样的函数妨碍了模型学习复杂函数映射的能力,因此,学习是有限的。这就是为什么(按照惯例)在每个使用激活层的线性层之后添加非线性功能是好的。
活化层
激活层与任何其他类型的层一样,只是它们没有权重,而是对输入使用非线性函数。
这种激活函数的一个很好的例子是代表双曲正切的 tanh 。
Tanh compared to sinh and cosh | Source: Wikipedia
因为我们在开始构建模型时会用到它,所以我们需要实现它:
现在我们已经实现了最重要的两层,让我们继续实现整个神经网络类。
神经网络实现
有几种方法需要实现
- 一个构造函数——这里我们需要传递超参数(学习率和历元数——我们的网络在输入数据集上运行的次数);必要字段的初始化
- 添加层方法—传递层的实例;用于模型构建;可以(应该)用几次才能加几层;
- 使用成本函数方法-指定训练模型时要使用的成本函数
- 拟合方法——执行训练过程的方法的标准名称;这里是我们放置之前的渐变下降片段的地方
- 预测方法—仅用于计算结果的方法的标准名称;一旦训练过程完成,它是有用的
代码是这样的:
您可能已经注意到在每个方法的末尾都出现了return self
语句。我这样做的原因是它允许我们做方法链接。如果你不确定我在说什么,你马上就会看到一个很好的例子。
现在让我们将它付诸实践。我们将使用 MNIST 数据库对手写数字进行分类。可以从这里下载,也可以从 Keras 轻松导入。
因为像素值表示在范围[0;255],我们将把它缩小到范围[0.0,1.0]。
我们做的另一件事是让 y (结果)变得更方便一点(注意keras . utils . to _ categorial)。它的作用是在一个独热向量中表示数值结果:
5 =>【0,0,0,0,0,1,0,0,0,0,0】
这很有帮助,因为我们网络的输出层将由 10 个节点组成,每个节点保存一个输出值。由于理想情况下的输出是正确的独热向量,因此成本函数现在更容易完成其工作。
现在,让我们通过放置一些 FC 和激活层来构建我们的第一个网络:
我们只使用前 1000 个样本的原因是,如果我们使用所有的样本,运行时间会太长。在这种情况下,使用更多的样本会得到更好的结果,所以如果有时间,可以尝试更大的范围。
在我们运行这个之前,我们需要再添加一个最后的触摸——另一个预输出激活函数— Softmax 。它所做的是对一个概率分布数组中有 n 个元素的数组进行归一化,该数组由与输入数字的指数成比例的 n 个概率组成,或者简单地说,计算样本匹配某个类别的概率。
Softmax formula | Source: hackernoon.com
以及实现:
让我们再试一次,只是这一次我们将有 Softmax 激活作为我们的最后一层。
现在我们已经训练了我们的数据,让我们评估我们的最终模型。
估价
请记住,我们已经实现了一个用于教育目的的小型模型。它不会产生很高的结果。我强烈建议用它来玩,以获得更好的准确性。
为了评估我们的结果,我们将使用一个来自 sklearn 的简单实用程序,它显示了我们模型的准确性。
现在你知道了神经网络构建的基础,我们可以继续学习更高级的东西…
卷积神经网络(CNN)
使用 FC 层执行图像识别任务的主要问题是,它将每个像素作为一个单独的特征,这似乎不太正确,因为神经网络的目标是复制人脑。帮助我们的大脑识别视觉输入的不仅仅是随机的点,而是点的模式。这就是所谓的卷积和相关过程派上用场的地方。
卷积和相关
图像处理中的卷积和相关几乎是相同的过程,只是在实现上有一点小小的不同。两者都取一幅图像 I ,基于另一个矩阵产生一个矩阵 O (称为滤镜或特征图 ) F 。我的意思是
先说关联:
Visual representation of Correlation | Source: My Late Night PowerPoint Creations
让我们解释一下发生了什么。过滤器就像一个滑动窗口,一步一步地穿过数组,向右滑动直到到达行的末尾。然后向下滑动,从行的开始处开始。在每个位置,我们对滤波器 F 和输入图像 I 的相应窗口的点积求和。每个位置代表输出中的一个单元格。
那么卷积呢?
Source: Giffy
相关和卷积的唯一区别是卷积*与同一个滤波器 F 一起工作,只是旋转了 180 度。*
Visual representation of Convolution | Source: My Late Night PowerPoint Creations
但是这对我们有什么帮助呢?
通过使用这种过滤器,通过我们的图像,我们提取的不仅仅是一个像素,而是整个像素区域,使我们的模型能够映射更复杂的图像特征,如线条和形状。
例如,如果你给一个卷积层一个猫的图像,它将能够识别像鼻子和耳朵这样的小特征。然后通过添加更多的卷积层,它可以识别更大尺度的特征,如头部或尾部。
其工作方式是每个卷积层有几个滤波器,都用随机数初始化。这背后的目标是让每个过滤器激活不同的特征(一个特征训练检测鼻子,另一个特征检测眼睛,等等。).
通常在处理 多通道图像(如 RGB) 时,您的滤镜将是三维的,深度等于图像通道数。这样你就只关注 2D 进程了。
填充和步幅
卷积和相关的问题是角点像素没有得到太多的关注,它们只被处理一次。如果你想改变这一点,你可以添加一个填充。
Visual representation of Padding | Source: My Late Night PowerPoint Creations
现在,即使是角落也会像图像的其他部分一样被处理。
然而,有时我们不想对每个像素都给予太多的关注(在处理较大的图像时非常适用)。让每个过滤器通过每个可能的位置有时是多余的。这就是为什么我们可以配置一个步幅。
步幅告诉我们的过滤器在到达下一个位置时应该滑动多少。步幅为 2 将在每次移位时跳过一个位置,这减小了输出的大小并使得计算量更小。
Visual representation of Stride | Source: My Late Night PowerPoint Creations
没有步幅基本上意味着步幅为 1——过滤器覆盖了所有可能的位置而没有跳跃。
实施
首先让我们列出我们的参数:
- 滤镜数量——图层中有多少个滤镜
- 过滤器尺寸——我们的过滤器会有多大
- 填充 —我们将有多少零填充(我们将对这个使用元组格式 (x,y) ,其中 x 代表列零填充, y 代表行零填充)。
- 步幅 —只是一个简单的数字,显示一个滤镜每张幻灯片应该移动多少个位置
NB! 因为我们要用随机值初始化我们的过滤器,所以使用 相关性 或 卷积 实际上没有区别,所以为了简单起见,我们将使用相关性。
这里有一个非常迭代(for-loopy)的方法来实现卷积层:
虽然有点容易理解,但它太慢了,因为它缺乏矢量化(使用 for 循环而不是基于数组的操作)。这就是为什么我四处挖掘,找到了一些非常有用的库方法,帮助我优化我的层:
- skim age . util . view _ as _ windows—我用它来自动获取我的滤镜应该去的位置,而不是自己循环遍历它们。
- *NP . tensordot**——*我用它把窗口(我用上面提到的方法得到的)和滤镜相乘。
不幸的是,我找不到一种简单的方法来对 in_error 的计算进行矢量化(我得到的最接近的方法是使用scipy . signal . convolve _ 2d,,但它不适用于 stride),直到我意识到矢量化操作通常用于用低级语言编写的循环,所以我使用 Cython (一个库,它允许
更多关于 Cython 的信息,请访问他们的文档。
现在我们已经有了所有的拼图,让我们组装我们的优化卷积层:
说到优化,我们将看到的下一组层将帮助我们避免 GPU 融化。
池层
合并图层的目的是减少先前卷积图层输出的空间大小。这有助于我们的模型,原因有二:
- 它降低了所需的计算能力。
- 它创建输入的较低分辨率版本。这个过程也被称为下采样。这有所帮助的原因是卷积层的过滤器通常被绑定到图像中的准确位置。具有小的移动或失真可能导致不期望的不同输出。下采样图像仍然包含较大的结构特征,只是排除了可能妨碍模型性能的精细细节。
一种可以用来解决这个问题的 下采样 的替代方法是首先在 卷积层 上使用一个 更大的步幅 。
在大多数 CNN 模型中遇到的通常模式如下:
- 卷积层
- 活化层
- 汇集层
A typical CNN pattern | Source: jefkine.com
工作原理
汇集的工作方式有点类似于卷积和相关*。我们又一次有了一个窗口(称为池)滑过我们的输入。然而池不包含任何像过滤器/特征映射那样的数据。当一个池移动到一个位置时,它仅根据该位置的值计算结果(如平均值或最大值)。*
为了帮助您理解它是如何工作的,我们将实现最广泛使用的类型— Max Pooling Layer 。
最大池层
想法很简单—当池滑动到某个位置时,该位置的最大值存储在输出中。
Visual representation of Max Pooling | Source: My Late Night PowerPoint Creations
因素
这里的列表比卷积层的列表简单得多
- 池形状 —池的形状,用一个元组来描述,一个好的默认值是(2,2)
- 步距 —与卷积相同,一个好的默认值是 2(大多数情况下,匹配池的尺寸是好的)
履行
再次实现一个基类是一个好主意,因为一些操作对于所有的池层都是相同的(例如像初始化):
接下来是最大池:
我强烈建议您自己尝试实现平均池层。
在我们建立第一个 CNN 模型之前,我们需要重新格式化我们的数据,以便它可以被其他层使用,如全连接。这是需要的,因为当我们解决分类任务时,最后的非激活层应该总是完全连接的。因为如果全连接的输入不是 1D 数组,那么它将会是一团乱麻,我们必须首先展平(将 N-D 数组转换为 1D 数组)数据。
展平图层
这可能是实现起来最简单的一层。我们的正向传播需要展平输入,反向传播需要将其重新格式化回初始形式:
现在让我们建立我们的第一个 CNN…
CNN 模型
我们将使用本文中实现的所有层来构建一个简单的 CNN:
现在让我们看看它的表现如何:
它应该比我们的普通网表现更好,尽管如果你玩它并有耐心等待训练过程结束,它实际上可以取得更高的结果。这里有一些关于如何建立一个更好的神经网络模型的有用资源…
附加链接
人工神经网络(ann)的初学者很可能会问一些问题。这些问题包括什么…
towardsdatascience.com](/beginners-ask-how-many-hidden-layers-neurons-to-use-in-artificial-neural-networks-51466afa0d3e) [## EfficientNet:重新思考卷积神经网络的模型缩放
自从 AlexNet 赢得了 2012 年的 ImageNet 竞赛,CNN(卷积神经网络的简称)已经成为设计者
medium.com](https://medium.com/@nainaakash012/efficientnet-rethinking-model-scaling-for-convolutional-neural-networks-92941c5bfb95)
最后的话
感谢大家花时间阅读我的第一篇关于媒体的文章。我真的希望它能帮助你学到一些新的有用的东西,甚至可以帮助你开始学习数据科学和机器学习。
如果您有任何意见、想法或建议,我会非常乐意收到您的反馈,并会尽快回复。
图像参考
[## 感知器
一种用于分类的感知器学习算法的实现。分类器导入感知器…
rasbt.github.io](http://rasbt.github.io/mlxtend/user_guide/classifier/Perceptron/) [## 用于视觉识别的 CS231n 卷积神经网络
目录:引入神经网络而不诉诸大脑类比是可能的。在…一节中
cs231n.github.io](http://cs231n.github.io/neural-networks-1/) [## 教程:了解线性回归和回归误差度量
人类大脑的构造是为了识别我们周围世界的模式。例如,我们观察到如果我们练习…
www.dataquest.io](https://www.dataquest.io/blog/understanding-regression-error-metrics/) [## 为什么是随机梯度下降?
随机梯度下降(SGD)是数据科学中最流行和最常用的优化器之一。如果你曾经…
medium.com](https://medium.com/bayshore-intelligence-solutions/why-is-stochastic-gradient-descent-2c17baf016de) [## 深度学习的难点在于
深度学习的核心是一个困难的优化问题。如此之难以至于在引进后的几十年里…
www.oreilly.com](https://www.oreilly.com/radar/the-hard-thing-about-deep-learning/) [## 机器学习中的梯度下降算法(及其变体)简介
介绍优化始终是最终目标,无论你是处理一个现实生活中的问题或建立一个…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2017/03/introduction-to-gradient-descent-algorithm-along-its-variants/) [## уакл:Sinh cosh tanh . SVG
504 × 504 пиксела. 240 × 240 пиксела | 480 × 480 пиксела | 600 × 600 пиксела | 768 × 768 пиксела | 1024 × 1024 пиксела.
bg.m.wikipedia.org](https://bg.m.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Sinh_cosh_tanh.svg) [## 训练建筑分类器- II
这是 5 篇文章系列的第 2 部分:训练架构分类器:动机训练架构分类器…
hackernoon.com](https://hackernoon.com/training-an-architectural-classifier-ii-bf29eca3cfa6) [## 卷积神经网络中的反向传播
卷积神经网络(CNN)是多层感知器(MLPs)的生物启发变体…
www.jefkine.com](https://www.jefkine.com/general/2016/09/05/backpropagation-in-convolutional-neural-networks/)*