A. 人工神经网络概念梳理与实例演示
人工神经网络概念梳理与实例演示
神经网络是一种模仿生物神经元的机器学习模型,数据从输入层进入并流经激活阈值的多个节点。
递归性神经网络一种能够对之前输入数据进行内部存储记忆的神经网络,所以他们能够学习到数据流中的时间依赖结构。
如今机器学习已经被应用到很多的产品中去了,例如,siri、Google Now等智能助手,推荐引擎——亚马逊网站用于推荐商品的推荐引擎,Google和Facebook使用的广告排名系统。最近,深度学习的一些进步将机器学习带入公众视野:AlphaGo 打败围棋大师李世石事件以及一些图片识别和机器翻译等新产品的出现。
在这部分中,我们将介绍一些强大并被普遍使用的机器学习技术。这当然包括一些深度学习以及一些满足现代业务需求传统方法。读完这一系列的文章之后,你就掌握了必要的知识,便可以将具体的机器学习实验应用到你所在的领域当中。
随着深层神经网络的精度的提高,语音和图像识别技术的应用吸引了大众的注意力,关于AI和深度学习的研究也变得更加普遍了。但是怎么能够让它进一步扩大影响力,更受欢迎仍然是一个问题。这篇文章的主要内容是:简述前馈神经网络和递归神经网络、怎样搭建一个递归神经网络对时间系列数据进行异常检测。为了让我们的讨论更加具体化,我们将演示一下怎么用Deeplearning4j搭建神经网络。
一、什么是神经网络?
人工神经网络算法的最初构思是模仿生物神经元。但是这个类比很不可靠。人工神经网络的每一个特征都是对生物神经元的一种折射:每一个节点与激活阈值、触发的连接。
连接人工神经元系统建立起来之后,我们就能够对这些系统进行训练,从而让他们学习到数据中的一些模式,学到之后就能执行回归、分类、聚类、预测等功能。
人工神经网络可以看作是计算节点的集合。数据通过这些节点进入神经网络的输入层,再通过神经网络的隐藏层直到关于数据的一个结论或者结果出现,这个过程才会停止。神经网络产出的结果会跟预期的结果进行比较,神经网络得出的结果与正确结果的不同点会被用来更正神经网络节点的激活阈值。随着这个过程的不断重复,神经网络的输出结果就会无限靠近预期结果。
二、训练过程
在搭建一个神经网络系统之前,你必须先了解训练的过程以及网络输出结果是怎么产生的。然而我们并不想过度深入的了解这些方程式,下面是一个简短的介绍。
网络的输入节点收到一个数值数组(或许是叫做张量多维度数组)就代表输入数据。例如, 图像中的每个像素可以表示为一个标量,然后将像素传递给一个节点。输入数据将会与神经网络的参数相乘,这个输入数据被扩大还是减小取决于它的重要性,换句话说,取决于这个像素就不会影响神经网络关于整个输入数据的结论。
起初这些参数都是随机的,也就是说神经网络在建立初期根本就不了解数据的结构。每个节点的激活函数决定了每个输入节点的输出结果。所以每个节点是否能够被激活取决于它是否接受到足够的刺激强度,即是否输入数据和参数的结果超出了激活阈值的界限。
在所谓的密集或完全连接层中,每个节点的输出值都会传递给后续层的节点,在通过所有隐藏层后最终到达输出层,也就是产生输入结果的地方。在输出层, 神经网络得到的最终结论将会跟预期结论进行比较(例如,图片中的这些像素代表一只猫还是狗?)。神经网络猜测的结果与正确结果的计算误差都会被纳入到一个测试集中,神经网络又会利用这些计算误差来不断更新参数,以此来改变图片中不同像素的重要程度。整个过程的目的就是降低输出结果与预期结果的误差,正确地标注出这个图像到底是不是一条狗。
深度学习是一个复杂的过程,由于大量的矩阵系数需要被修改所以它就涉及到矩阵代数、衍生品、概率和密集的硬件使用问题,但是用户不需要全部了解这些复杂性。
但是,你也应该知道一些基本参数,这将帮助你理解神经网络函数。这其中包括激活函数、优化算法和目标函数(也称为损失、成本或误差函数)。
激活函数决定了信号是否以及在多大程度上应该被发送到连接节点。阶梯函数是最常用的激活函数, 如果其输入小于某个阈值就是0,如果其输入大于阈值就是1。节点都会通过阶梯激活函数向连接节点发送一个0或1。优化算法决定了神经网络怎么样学习,以及测试完误差后,权重怎么样被更准确地调整。最常见的优化算法是随机梯度下降法。最后, 成本函数常用来衡量误差,通过对比一个给定训练样本中得出的结果与预期结果的不同来评定神经网络的执行效果。
Keras、Deeplearning4j 等开源框架让创建神经网络变得简单。创建神经网络结构时,需要考虑的是怎样将你的数据类型匹配到一个已知的被解决的问题,并且根据你的实际需求来修改现有结构。
三、神经网络的类型以及应用
神经网络已经被了解和应用了数十年了,但是最近的一些技术趋势才使得深度神经网络变得更加高效。
GPUs使得矩阵操作速度更快;分布式计算结构让计算能力大大增强;多个超参数的组合也让迭代的速度提升。所有这些都让训练的速度大大加快,迅速找到适合的结构。
随着更大数据集的产生,类似于ImageNet 的大型高质量的标签数据集应运而生。机器学习算法训练的数据越大,那么它的准确性就会越高。
最后,随着我们理解能力以及神经网络算法的不断提升,神经网络的准确性在语音识别、机器翻译以及一些机器感知和面向目标的一些任务等方面不断刷新记录。
尽管神经网络架构非常的大,但是主要用到的神经网络种类也就是下面的几种。
3.1前馈神经网络
前馈神经网络包括一个输入层、一个输出层以及一个或多个的隐藏层。前馈神经网络可以做出很好的通用逼近器,并且能够被用来创建通用模型。
这种类型的神经网络可用于分类和回归。例如,当使用前馈网络进行分类时,输出层神经元的个数等于类的数量。从概念上讲, 激活了的输出神经元决定了神经网络所预测的类。更准确地说, 每个输出神经元返回一个记录与分类相匹配的概率数,其中概率最高的分类将被选为模型的输出分类。
前馈神经网络的优势是简单易用,与其他类型的神经网络相比更简单,并且有一大堆的应用实例。
3.2卷积神经网络
卷积神经网络和前馈神经网络是非常相似的,至少是数据的传输方式类似。他们结构大致上是模仿了视觉皮层。卷积神经网络通过许多的过滤器。这些过滤器主要集中在一个图像子集、补丁、图块的特征识别上。每一个过滤器都在寻找不同模式的视觉数据,例如,有的可能是找水平线,有的是找对角线,有的是找垂直的。这些线条都被看作是特征,当过滤器经过图像时,他们就会构造出特征图谱来定位各类线是出现在图像的哪些地方。图像中的不同物体,像猫、747s、榨汁机等都会有不同的图像特征,这些图像特征就能使图像完成分类。卷积神经网络在图像识别和语音识别方面是非常的有效的。
卷积神经网络与前馈神经网络在图像识别方面的异同比较。虽然这两种网络类型都能够进行图像识别,但是方式却不同。卷积神经网络是通过识别图像的重叠部分,然后学习识别不同部分的特征进行训练;然而,前馈神经网络是在整张图片上进行训练。前馈神经网络总是在图片的某一特殊部分或者方向进行训练,所以当图片的特征出现在其他地方时就不会被识别到,然而卷积神经网络却能够很好的避免这一点。
卷积神经网络主要是用于图像、视频、语音、声音识别以及无人驾驶的任务。尽管这篇文章主要是讨论递归神经网络的,但是卷积神经网络在图像识别方面也是非常有效的,所以很有必要了解。
3.3递归神经网络
与前馈神经网络不同的是,递归神经网络的隐藏层的节点里有内部记忆存储功能,随着输入数据的改变而内部记忆内容不断被更新。递归神经网络的结论都是基于当前的输入和之前存储的数据而得出的。递归神经网络能够充分利用这种内部记忆存储状态处理任意序列的数据,例如时间序列。
递归神经网络经常用于手写识别、语音识别、日志分析、欺诈检测和网络安全。
递归神经网络是处理时间维度数据集的最好方法,它可以处理以下数据:网络日志和服务器活动、硬件或者是医疗设备的传感器数据、金融交易、电话记录。想要追踪数据在不同阶段的依赖和关联关系需要你了解当前和之前的一些数据状态。尽管我们通过前馈神经网络也可以获取事件,随着时间的推移移动到另外一个事件,这将使我们限制在对事件的依赖中,所以这种方式很不灵活。
追踪在时间维度上有长期依赖的数据的更好方法是用内存来储存重要事件,以使近期事件能够被理解和分类。递归神经网络最好的一点就是在它的隐藏层里面有“内存”可以学习到时间依赖特征的重要性。
接下来我们将讨论递归神经网络在字符生成器和网络异常检测中的应用。递归神经网络可以检测出不同时间段的依赖特征的能力使得它可以进行时间序列数据的异常检测。
递归神经网络的应用
网络上有很多使用RNNs生成文本的例子,递归神经网络经过语料库的训练之后,只要输入一个字符,就可以预测下一个字符。下面让我们通过一些实用例子发现更多RNNs的特征。
应用一、RNNs用于字符生成
递归神经网络经过训练之后可以把英文字符当做成一系列的时间依赖事件。经过训练后它会学习到一个字符经常跟着另外一个字符(“e”经常跟在“h”后面,像在“the、he、she”中)。由于它能预测下一个字符是什么,所以它能有效地减少文本的输入错误。
Java是个很有趣的例子,因为它的结构包括很多嵌套结构,有一个开的圆括号必然后面就会有一个闭的,花括号也是同理。他们之间的依赖关系并不会在位置上表现的很明显,因为多个事件之间的关系不是靠所在位置的距离确定的。但是就算是不明确告诉递归神经网络Java中各个事件的依赖关系,它也能自己学习了解到。
在异常检测当中,我们要求神经网络能够检测出数据中相似、隐藏的或许是并不明显的模式。就像是一个字符生成器在充分地了解数据的结构后就会生成一个数据的拟像,递归神经网络的异常检测就是在其充分了解数据结构后来判断输入的数据是不是正常。
字符生成的例子表明递归神经网络有在不同时间范围内学习到时间依赖关系的能力,它的这种能力还可以用来检测网络活动日志的异常。
异常检测能够使文本中的语法错误浮出水面,这是因为我们所写的东西是由语法结构所决定的。同理,网络行为也是有结构的,它也有一个能够被学习的可预测模式。经过在正常网络活动中训练的递归神经网络可以监测到入侵行为,因为这些入侵行为的出现就像是一个句子没有标点符号一样异常。
应用二、一个网络异常检测项目的示例
假设我们想要了解的网络异常检测就是能够得到硬件故障、应用程序失败、以及入侵的一些信息。
模型将会向我们展示什么呢?
随着大量的网络活动日志被输入到递归神经网络中去,神经网络就能学习到正常的网络活动应该是什么样子的。当这个被训练的网络被输入新的数据时,它就能偶判断出哪些是正常的活动,哪些是被期待的,哪些是异常的。
训练一个神经网络来识别预期行为是有好处的,因为异常数据不多,或者是不能够准确的将异常行为进行分类。我们在正常的数据里进行训练,它就能够在未来的某个时间点提醒我们非正常活动的出现。
说句题外话,训练的神经网络并不一定非得识别到特定事情发生的特定时间点(例如,它不知道那个特殊的日子就是周日),但是它一定会发现一些值得我们注意的一些更明显的时间模式和一些可能并不明显的事件之间的联系。
我们将概述一下怎么用 Deeplearning4j(一个在JVM上被广泛应用的深度学习开源数据库)来解决这个问题。Deeplearning4j在模型开发过程中提供了很多有用的工具:DataVec是一款为ETL(提取-转化-加载)任务准备模型训练数据的集成工具。正如Sqoop为Hadoop加载数据,DataVec将数据进行清洗、预处理、规范化与标准化之后将数据加载到神经网络。这跟Trifacta’s Wrangler也相似,只不过它更关注二进制数据。
开始阶段
第一阶段包括典型的大数据任务和ETL:我们需要收集、移动、储存、准备、规范化、矢量话日志。时间跨度的长短是必须被规定好的。数据的转化需要花费一些功夫,这是由于JSON日志、文本日志、还有一些非连续标注模式都必须被识别并且转化为数值数组。DataVec能够帮助进行转化和规范化数据。在开发机器学习训练模型时,数据需要分为训练集和测试集。
训练神经网络
神经网络的初始训练需要在训练数据集中进行。
在第一次训练的时候,你需要调整一些超参数以使模型能够实现在数据中学习。这个过程需要控制在合理的时间内。关于超参数我们将在之后进行讨论。在模型训练的过程中,你应该以降低错误为目标。
但是这可能会出现神经网络模型过度拟合的风险。有过度拟合现象出现的模型往往会在训练集中的很高的分数,但是在遇到新的数据时就会得出错误结论。用机器学习的语言来说就是它不够通用化。Deeplearning4J提供正则化的工具和“过早停止”来避免训练过程中的过度拟合。
神经网络的训练是最花费时间和耗费硬件的一步。在GPUs上训练能够有效的减少训练时间,尤其是做图像识别的时候。但是额外的硬件设施就带来多余的花销,所以你的深度学习的框架必须能够有效的利用硬件设施。Azure和亚马逊等云服务提供了基于GPU的实例,神经网络还可以在异构集群上进行训练。
创建模型
Deeplearning4J提供ModelSerializer来保存训练模型。训练模型可以被保存或者是在之后的训练中被使用或更新。
在执行异常检测的过程中,日志文件的格式需要与训练模型一致,基于神经网络的输出结果,你将会得到是否当前的活动符合正常网络行为预期的结论。
代码示例
递归神经网络的结构应该是这样子的:
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder(
.seed(123)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT).iterations(1)
.weightInit(WeightInit.XAVIER)
.updater(Updater.NESTEROVS).momentum(0.9)
.learningRate(0.005)
.gradientNormalization(GradientNormalization.ClipElementWiseAbsoluteValue)
.(0.5)
.list()
.layer(0, new GravesLSTM.Builder().activation("tanh").nIn(1).nOut(10).build())
.layer(1, new RnnOutputLayer.Builder(LossFunctions.LossFunction.MCXENT)
.activation("softmax").nIn(10).nOut(numLabelClasses).build())
.pretrain(false).backprop(true).build();
MultiLayerNetwork net = new MultiLayerNetwork(conf);
net.init();
下面解释一下几行重要的代码:
.seed(123)
随机设置一个种子值对神经网络的权值进行初始化,以此获得一个有复验性的结果。系数通常都是被随机的初始化的,以使我们在调整其他超参数时仍获得一致的结果。我们需要设定一个种子值,让我们在调整和测试的时候能够用这个随机的权值。
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT).iterations(1)
决定使用哪个最优算法(在这个例子中是随机梯度下降法)来调整权值以提高误差分数。你可能不需要对这个进行修改。
.learningRate(0.005)
当我们使用随机梯度下降法的时候,误差梯度就被计算出来了。在我们试图将误差值减到最小的过程中,权值也随之变化。SGD给我们一个让误差更小的方向,这个学习效率就决定了我们该在这个方向上迈多大的梯度。如果学习效率太高,你可能是超过了误差最小值;如果太低,你的训练可能将会永远进行。这是一个你需要调整的超参数。
B. 【阅读笔记】改进卷积神经网络的14个小技巧
原文: https://mp.weixin.qq.com/s/Lh_lJNvV9BGhc6no2ln-_g
原题目误导性太大
1)架构要遵循应用
你也许会被 Google Brain 或者 DeepMind 这些奇特的实验室所发明的那些耀眼的新模型所吸引,但是其中许多在你的用例或者业务环境中要么是不可能实现,要么是实现起来非常不现实。你应该使用对你的特定应用最有意义的模型,这种模型或许比较简单,但是仍然很强大,例如 VGG。
2)网络路径的激增
每年的 ImageNet Challenge 的冠军都会使用比上一届冠军更加深层的网络。从 AlexNet 到 Inception,再到 ResNet,Smith 注意到了「网络中路径数量倍增」的趋势,并且「ResNet 可以是不同长度的网络的指数集合」。
3)争取简单
然而,更大的并不一定是更好的。在名为「Bigger is not necessarily better」的论文中,Springenberg 等人演示了如何用更少的单元实现最先进的结果。参考:https://arxiv.org/pdf/1412.6806.pdf
4)增加对称性
无论是在建筑上,还是在生物上,对称性被认为是质量和工艺的标志。Smith 将 FractalNet 的优雅归功于网络的对称性。
5)金字塔式的形状
你也许经常在表征能力和减少冗余或者无用信息之间权衡。卷积神经网络通常会降低激活函数的采样,并会增加从输入层到最终层之间的连接通道。
6)过度训练
另一个权衡是训练准确度和泛化能力。用类似 drop-out 或者 drop-path 的方法进行正则化可以提高泛化能力,这是神经网络的重要优势。请在比你的实际用例更加苛刻的问题下训练你的网络,以提高泛化性能。
7)全面覆盖问题空间
为了扩展你的训练数据和提升泛化能力,请使用噪声和数据增强,例如随机旋转、裁剪和一些图像操作。
8)递增的特征构造
随着网络结构越来越成功,它们进一部简化了每一层的「工作」。在非常深层的神经网络中,每一层仅仅会递增的修改输入。在 ResNets 中,每一层的输出和它的输入时很相似的,这意味着将两层加起来就是递增。实践中,请在 ResNet 中使用较短的跳变长度。
9)标准化层的输入
标准化是另一个可以使计算层的工作变得更加容易的方法,在实践中被证明可以提升训练和准确率。批量标准化(batch normalization)的发明者认为原因在于处理内部的协变量,但是 Smith 认为,「标准化把所有层的输入样本放在了一个平等的基础上(类似于一种单位转换),这允许反向传播可以更有效地训练」。
10)输入变换
研究表明,在 Wide ResNets 中,性能会随着连接通道的增加而增强,但是你需要权衡训练代价与准确度。AlexNet、VGG、Inception 和 ResNets 都在第一层使用了输入变换以让输入数据能够以多种方式被检查。
11)可用的资源决指引着层的宽度
然而,可供选择的输出数量并不是显而易见的,这依赖于你的硬件能力以及期望的准确度。
12)Summation Joining
Summation 是一种常用的合并分支的方式。在 ResNets 中,使用总和作为连接的机制可以让每一个分支都能计算残差和整体近似。如果输入跳跃连接一直存在,那么 summation 会让每一层学到正确地东西(例如与输入的差别)。在任何分支都可以被丢弃的网络(例如 FractalNet)中,你应该使用这种方式类保持输出的平滑。
13)下采样变换
在池化的时候,利用级联连接(concatenation joining)来增加输出的数量。当使用大于 1 的步长时,这会同时处理连接并增加连接通道的数量。
14)用于竞争的 Maxout
Maxout 被用在你只需要选择一个激活函数的局部竞争网络中。使用求和以及平均值会包含所有的激活函数,所以不同之处在于 maxout 只选择一个「胜出者」。Maxout 的一个明显的用例是每个分支具有不同大小的内核,而 Maxout 可以包含尺度不变性。
1)使用调优过的预训练网络
「如果你的视觉数据和 ImageNet 相似,那么使用预训练网络会帮助你学习得更快」,机器学习公司 Diffbot 的 CEO Mike Tung 解释说。低水平的卷积神经网络通常可以被重复使用,因为它们大多能够检测到像线条以及边缘这些模式。将分类层用你自己的层替换,并且用你特定的数据去训练最后的几个层。
2)使用 freeze-drop-path
Drop-path 会在训练的迭代过程中随机地删除一些分支。Smith 测试了一种相反的方法,它被称为 freeze-path,就是一些路径的权重是固定的、不可训练的,而不是整体删除。因为下一个分支比以前的分支包含更多的层,并且正确的内容更加容易近似得到,所以网络应该会得到更好的准确度。
3)使用循环的学习率
关于学习率的实验会消耗大量的时间,并且会让你遇到错误。自适应学习率在计算上可能是非常昂贵的,但是循环学习率不会这样。使用循环学习率(CLR)时,你可以设置一组最大最小边界,在边界范围内改变学习率。Smith 甚至还在论文《Cyclical Learning Rates for Training Neural Networks》中提供了计算学习率的最大值和最小值的方法。参考:https://arxiv.org/pdf/1506.01186.pdf
4)在有噪声的标签中使用 bootstrapping
在现实中,很多数据都是混乱的,标签都是主观性的或者是缺失的,而且预测的对象可能是训练的时候未曾遇到过的。Reed 等人在文章《TRAINING DEEP NEURAL NETWORKS ON NOISY LABELS WITH BOOTSTRAPPING》中描述了一种给网络预测目标注入一致性的方法。直观地讲,这可以奏效,通过使网络利用对环境的已知表示(隐含在参数中)来过滤可能具有不一致的训练标签的输入数据,并在训练时清理该数据。参考:https://arxiv.org/pdf/1412.6596
5)采用有 Maxout 的 ELU,而不是 ReLU
ELU 是 ReLU 的一个相对平滑的版本,它能加速收敛并提高准确度。与 ReLU 不同,ELU 拥有负值,允许它们以更低的计算复杂度将平均单位激活推向更加接近 0 的值,就像批量标准化一样参考论文《FAST AND ACCURATE DEEP NETWORK LEARNING BY EXPONENTIAL LINEAR UNITS (ELUS)》,https://arxiv.org/pdf/1511.07289.pdf。如果您使用具有全连接层的 Maxout,它们是特别有效的。
C. 神经网络,流形和拓扑
本文翻译自colah的博客中的文章《Neural Networks, Manifolds, and Topology》
链接:http://colah.github.io/posts/2014-03-NN-Manifolds-Topology/
发布于2014年4月6日
关键词:拓扑,神经网络,深度学习,流形假设(manifold hypothesis)
最近,深度神经网络给人们带来很大的振奋,引起了极大的兴趣,因为其在像计算机视觉等领域中取得的突破性成果。[1]
但是,人们对其仍存在一些担忧。一个是要真正理解一个神经网络在做什么是一件十分具有挑战的事情。如果一个人将其训练得很好,它可以取得高质量的结果,但是要理解其是如何做到这一点很难。如果网络出现故障,很难了解哪里出现了问题。
虽然,总体上来说要理解深度神经网络的行为具有挑战性,但事实证明,探索低维深度神经网络要容易得多,低维深度神经网络是指每层中只有少量神经元的网络。事实上,我们可以创建可视化来完全理解这种网络的行为和训练过程。这种观点将使我们能够更深入地了解神经网络的行为,并观察到神经网络和一个称为拓扑的数学领域之间的联系。
从中可以得到许多有趣的东西,包括能够对某些特定数据集进行分类的神经网络复杂度的基本下界。
让我们从一个非常简单的数据集开始,在平面上有两条曲线。网络将学习把点归类为属于一个或另一个。
对于这个问题,可视化神经网络行为的明显方法 - 或者任何分类算法 - 就是简单地看一下它如何对每个可能的数据点进行分类。
我们将从最简单的神经网络类别开始,只有一个输入层和一个输出层。这样的网络只是试图通过用直线划分它们来分离这两类数据。
那种网络不是很有趣。现代神经网络通常在其输入和输出之间具有多个层,称为“隐藏”层。至少有一个。
和前面一样,我们可以通过查看它对域中不同点的划分来可视化该网络的行为。它使用比直线更复杂的曲线将数据分离。
对于每一层,网络都会转换数据,创建一个新的表示。[2] 我们可以查看每个表示中的数据以及网络如何对它们进行分类。当我们到达最终表示时,网络将只绘制一条穿过数据的线(或者,在更高维度下,绘制一个超平面)。
在之前的可视化中,我们以“原始”表示形式查看了数据。当我们看输入层时,你可以想到这一点。现在我们将在第一层转换后查看它。你可以把它想象成我们在看隐藏层。
每个维度对应于层中神经元的发射。
在上一节中概述的方法中,我们通过查看与每个层对应的表示来学习理解网络。这给了我们一个离散的表示序列。
棘手的部分是理解我们如何从一个到另一个。值得庆幸的是,神经网络层具有很好的属性,使这很容易实现。
在神经网络中使用各种不同类型的层。我们将讨论tanh(双曲正切)层作为一个具体示例。 tanh层 tanh(Wx + b) 包括:
1. 经过“权重”矩阵 W 的线性变换
2. 经过矢量 b 的平移
3. 点式地应用tanh。
我们可以将其视为一个连续的转换,如下所示:
其他标准层的过程大致相同,包括仿射变换,然后逐点应用单调激活函数。
我们可以应用这种技术来理解更复杂的网络。例如,以下网络使用四个隐藏层对两个略微纠缠的螺旋进行分类。随着时间的推移,我们可以看到它从“原始”表示转变为它为了对数据进行分类而学到的更高级别的表示。虽然螺旋最初是缠绕的,但最终它们是线性可分的。
另一方面,以下网络也使用多个层,无法对两个更纠缠的螺旋进行分类。
值得明确指出的是,这些任务只是有些挑战,因为我们使用的是低维神经网络。如果我们使用更广泛的网络,所有这一切都会非常容易。
(Andrej Karpathy基于ConvnetJS做了一个很好的演示,它允许您通过这种对训练的可视化来交互式地探索网络!)
每一层都伸展并占据空间,但它永远不会削减,折断或折叠它。直觉上,我们可以看到它保留了拓扑属性。例如,如果一个集合之前是连通的那其之后也是连通的(反之亦然)。
像这样不会影响拓扑的变换,称为同胚。在形式上,它们是双向连续函数的双射。
定理 :如果权重矩阵W是非奇异的,则具有 N 个输入和 N 个输出的层是同胚。 (虽然需要注意域和范围。)
证明 :让我们一步一步考虑:
1. 假设W具有非零行列式。然后它是具有线性逆的双射线性函数。线性函数是连续的。因此,乘以 W 是同胚。
2. 平移是同胚的。
3. tanh(和sigmoid和softplus但不是ReLU)是具有连续逆的连续函数。如果我们对我们考虑的域和范围保持谨慎,它们就是双射的。逐点应用它们是同胚。
因此,如果 W 具有非零行列式,则我们的层是同胚。 ∎
如果我们将这些层中任意多个组合在一起,这个结果就会继续存在。
考虑一个二维数据集,有两个类A和B⊂R2:
A={x|d(x,0)<1/3}
B={x|2/3<d(x,0)<1}
声明 :如果没有具有3个或更多隐藏单位的层,神经网络就无法对此数据集进行分类,无论深度如何。
如前所述,使用S形单元或softmax层进行分类等同于尝试找到在最终表示中分离A和B的超平面(或在这种情况下为线)。由于只有两个隐藏单元,网络在拓扑上无法以这种方式分离数据,并且注定要在此数据集上失败。
在下面的可视化中,我们观察到网络训练时的隐藏表示以及分类线。正如我们所看到的那样,它正在努力学习如何做到这一点。
最终,它会被拉入一个相当低效的局部最小值。 虽然,它实际上能够达到~ 80% 的分类准确度。
这个例子只有一个隐藏层,但无论如何都会失败。
证明 :每一层都是同胚,或者层的权重矩阵具有行列式0.如果它是一个同胚,A仍然被B包围,并且一条线不能将它们分开。 但是假设它有一个行列式为0:那么数据集会在某个轴上折叠。 由于我们处理与原始数据集同胚的某些东西,A被B包围,并且在任何轴上折叠意味着我们将有一些A和B混合的点并且变得无法区分。∎
如果我们添加第三个隐藏单元,问题就变得微不足道了。 神经网络学习以下表示:
通过这种表示,我们可以使用超平面分离数据集。
为了更好地了解正在发生的事情,让我们考虑一个更简单的1维数据集:
A=[−1/3,1/3]
B=[−1,−2/3]∪[2/3,1]
如果不使用两个或更多隐藏单元的层,我们就无法对此数据集进行分类。 但是如果我们使用有两个单元的层,我们学会将数据表示为一条很好的曲线,允许我们用一条线来将不同的类分隔开来:
发生了什么? 一个隐藏单元在x > -1/2时学会开火,一个在x > 1/2时学会开火。当第一个开火但第二个没开火时,我们知道我们在A中。
这与现实世界的数据集,比如图像数据有关吗? 如果你真的认真对待流形假设,我认为值得考虑。
流形假设是自然数据在其嵌入空间中形成低维流形。 理论上[3]和实验上[4]都有理由认为这是真的。 如果你相信这一点,那么分类算法的任务就是从根本上分离出一堆纠结的流形。
在前面的例子中,一个类完全包围了另一个类。 然而,狗图像流形似乎不太可能被猫图像流形完全包围。 但是,正如我们将在下一节中看到的那样,还有其他更合理的拓扑情况可能仍然存在问题。
另一个值得考虑的有趣数据集是两个链接的圆环, A 和 B .
与我们考虑的先前数据集非常相似,如果不使用n+1维,即第4维,则无法分离此数据集。
链接是在结理论中研究的,这是一个拓扑领域。 有时当我们看到一个链接时,它是否是一个非链接(一堆东西纠结在一起,但可以通过连续变形分开)并不是很明显。
如果使用仅有3个单元的层的神经网络可以对其进行分类,那么它就是非链接。 (问题:理论上,所有非链接是否都可以被只有3个单元的网络进行分类?)
从这个结的角度来看,我们对神经网络产生的连续可视化的表示不仅仅是一个很好的动画,它还是一个解开链接的过程。在拓扑中,我们将其称为原始链接和分离链接之间的环境同位素(ambient isotopy)。
形式上,流形A和B之间的环境同位素是连续函数F:[0,1]×X→Y,使得每个Ft是从X到其范围的同胚,F0是恒等函数,F1将A映射到B。也就是说,Ft连续地从A向自身映射转换到A向B映射。
定理 :在输入和网络层表示之间存在环境同位素,如果:a) W 不是奇异的,b)我们愿意置换隐藏层中的神经元,并且c)存在多于1个隐藏单元。
证明 :同样,我们分别考虑网络的每个阶段:
1. 最难的部分是线性变换。 为了使这成为可能,我们需要 W 有一个正的行列式。 我们的前提是它不是零,如果它是负的,我们可以通过切换两个隐藏的神经元来翻转符号,那么我们可以保证行列式是正的。 正行列式矩阵的空间是路径连通的,因此存在 p :[ 0,1 ] → GLn (R)5,使得 p(0) = Id 且 p(1) = W 。 我们可以用函数 x → p(t)x 连续地从恒等函数转换到 W 变换,在每个时间点 t 将 x 乘以连续转换矩阵 p(t) 。
2. 我们可以用函数 x → x + tb 不断地从恒等函数转换到b转换。
3. 通过函数: x → (1- t)x +tσ(x) ,我们可以不断地从恒等函数过渡到σ的逐点使用。∎
我想可能有兴趣自动发现这种环境同位素并自动证明某些链接的等价性,或某些链接是可分离的。知道神经网络能否击败现有技术水平将会很有趣。
(显然确定结是否平凡是NP问题。这对神经网络来说不是好兆头。)
到目前为止我们谈到的那种链接似乎不太可能出现在现实世界的数据中,但是有更高的维度的拓展。在现实世界的数据中可能存在这样的事情似乎是合理的。
链接和结是一维流形,但我们需要4个维度才能解开所有这些。类似地,人们可能需要更高维度的空间以能够解开n维流形。所有n维流形都可以在 2n + 2 维中解开。[6]
(我对结理论知之甚少,真的需要更多地了解有关维度和链接的知识。如果我们知道流形可以嵌入到n维空间中,而不是流形的维数,我们有什么限制? )
一个神经网络要做的自然的事情,非常简单的路线,是试图将流形分开,并尽可能地拉伸缠绕的部分。 虽然这不会接近真正的解决方案,但它可以实现相对较高的分类准确度并且是诱人的局部最小值。
它会在它试图拉伸的区域中表现为 非常高的衍生物 (very high derivatives)和近乎不连续性。我们知道这些事情会发生.[7] 在数据点处惩罚层的衍生物的收缩惩罚是对抗这种情况的自然方式.[8]
由于这些局部极小值从试图解决拓扑问题的角度来看是绝对无用的,拓扑问题可能提供了探索解决这些问题的良好动机。
另一方面,如果我们只关心实现良好的分类结果,似乎我们可能不在乎。如果数据流形的一小部分被另一个流形钩住,对我们来说这是一个问题吗?尽管存在这个问题,似乎我们也应该能够获得主观上来看不错的分类结果。
(我的直觉是试图欺骗这个问题是一个坏主意:很难想象它不会是一个死胡同。特别是在一个优化问题中,局部最小值是一个大问题,选择一个架构,不能真正解决问题似乎是表现不佳的秘诀。)
我对标准神经网络层的思考越多 - 即是,通过仿射变换后跟一个逐点激活函数 - 我感觉更加失去理智。 很难想象这些对于操纵流形真的很有益。
或许有一种非常不同的层可以用来组成更传统的层?
我自然想到的是学习一个矢量场,这个矢量场带有我们想要改变流形的方向:
然后根据它来变形空间:
人们可以在固定点学习矢量场(只需从训练集中取一些固定点作为锚点)并以某种方式进行插值。 上面的矢量场的形式如下:
其中v0和v1是向量,f0(x)和f1(x)是n维高斯。 这受到径向基函数的启发。
我也开始思考线性可分性对于神经网络的需求可能是巨大的,虽然可能是不合理的。在某些方面,感觉自然要做的就是使用k近邻(k-NN)。然而,k-NN的成功在很大程度上取决于它对数据进行分类的表示,因此在k-NN能够很好地工作之前需要一个好的表示。
作为第一个实验,我训练了一些MNIST网络(两层卷积网,没有丢失),达到了约1%的测试误差。然后我丢弃了最终的softmax层并使用了k-NN算法。我能够始终如一地将测试误差降低0.1-0.2%。
尽管如此,还是觉得哪里有些问题。网络仍在尝试进行线性分类,但由于我们在测试时使用k-NN,因此能够从错误中恢复一点。
由于1/距离的加权,k-NN在它所作用的表示方面是可微的。因此,我们可以直接为k-NN分类训练一个网络。这可以被认为是一种“最近邻”层,可以作为softmax的替代品。
我们不希望为每个小批量提供整个训练集,因为这在计算上非常昂贵。我认为一个很好的方法是根据小批量的其他元素的类别对小批量的每个元素进行分类,给每个元素一个权重1 /(与分类目标的距离)。[9]
遗憾的是,即使使用复杂的架构,使用k-NN也只会降低5-4%的测试错误 - 使用更简单的架构会导致更糟糕的结果。但是,我花了很少的精力去调整超参数。
尽管如此,我在美学上仍然喜欢这种方法,因为看起来我们“要求”网络做的事情要合理得多。我们希望相同流形的点比其他点更接近,而流形可以通过超平面分离。这应该对应于扩张不同类别流形之间的空间并使各个流形收缩。感觉就像简化。
数据的拓扑属性(例如链接)可能使得无法使用低维网络线性分离类,无论深度如何。即使在技术上可行的情况下,例如螺旋,这样做也是非常具有挑战性的。
为了使用神经网络准确地对数据进行分类,有时需要宽层。此外,传统的神经网络层似乎不能很好地表示对流形的重要操作;即使我们巧妙地手工设置权重,紧凑地表示我们想要的变换也是一项挑战。新的层,特别是受机器学习的流形观点驱动的,可能是有用的补充。
(这是一个正在开发的研究项目。它是作为公开进行研究的实验而发布的。我很高兴收到你对这些想法的反馈:你可以内联或最后发表评论。对于拼写错误,技术错误或你想要的澄清看到添加,我们鼓励你在github上发出pull请求。)
感谢Yoshua Bengio, Michael Nielsen, Dario Amodei, Eliana Lorch, Jacob Steinhardt, and Tamsyn Waterhouse的评论和鼓励。
1. This seems to have really kicked off with Krizhevsky et al. , (2012) , who put together a lot of different pieces to achieve outstanding results. Since then there’s been a lot of other exciting work. ↩
2. These representations, hopefully, make the data “nicer” for the network to classify. There has been a lot of work exploring representations recently. Perhaps the most fascinating has been in Natural Language Processing: the representations we learn of words, called word embeddings, have interesting properties. See Mikolov et al. (2013) , Turian et al. (2010) , and, Richard Socher’s work . To give you a quick flavor, there is a very nice visualization associated with the Turian paper. ↩
3. A lot of the natural transformations you might want to perform on an image, like translating or scaling an object in it, or changing the lighting, would form continuous curves in image space if you performed them continuously. ↩
4. Carlsson et al. found that local patches of images form a klein bottle. ↩
5. GLn(R)is the set of invertible n×n matrices on the reals, formally called the general linear group of degree n. ↩
6. This result is mentioned in Wikipedia’s subsection on Isotopy versions . ↩
7. See Szegedy et al. , where they are able to modify data samples and find slight modifications that cause some of the best image classification neural networks to misclasify the data. It’s quite troubling. ↩
8. Contractive penalties were introced in contractive autoencoders. See Rifai et al. (2011) . ↩
9. I used a slightly less elegant, but roughly equivalent algorithm because it was more practical to implement in Theano: feedforward two different batches at the same time, and classify them based on each other. ↩
D. 人工神经网络BP算法源代码与演示程序怎么用
在matlab里建立一个.m的M文件,把代码输进去,保存,运行就可以了。
演示程序是在command 里打demo就可以了找到了 . 你邮箱多少,我只有简单的BP神经网络程序。
E. 神经网络、流形和拓扑
译者:树石
最近,由于在诸如计算机视觉领域取得了突破性成果,深层神经网络引起了广泛的关注和兴趣。
然而,该领域仍然存在一些顾虑。比如, 要了解神经网络能够做什么相当具有挑战性 。如果一个网路被训练得很好,输出高品质的结果,但了解它是如何做到的具有挑战性。如果网络出现故障,也很难理解什么地方出了错。
虽然通常理解深层神经网络的行为比较困难, 探索低维度深层神经网络相对容易的多 ——在每一层只有几个神经元的网络。事实上,我们可以通过创建可视化效果来理解网络的行为和对网络的培训。这种方法将让我们 获取对神经网络行为的深层直觉,并观察到神经网络和拓扑学之间的联系 。
另外,还探讨了一些有趣的事情,包括对某些数据集进行分类的神经网络的最低复杂性。
让我们从一个非常简单的数据集开始:在一个平面上的两条曲线。该网络将学习如何将线上的点归类为这一个还是另外一个。
将神经网络(或任何分类算法)的行为可视化,显而易见的方法是简单地看它是如何对每一个可能的数据点进行分类。
我们将先从最简单的神经网络开始,只有一个输入层和一个输出层的网络。这样的网络只是试图通过画一条线将两个类数据的分离。
诸如此类的网络不是很有趣。现代神经网络一般在输入和输出之间,具有称为“隐藏”层的多个层次。至少包含一个隐藏层。
与以前一样,我们可以通过查看它对其领域不同点进行的处理来观察这个网络的行为。数据分割通过一条曲线来完成,而不是直线。
通过神经网络的每一层,数据被转换,创建了一个新的 表示 (represention)。我们可以看一下在这些表示中的数据以及网络是如何划分他们的。当我们到达最后一层的表示时,网络只需要绘制一条线(或者,在更高维度里绘制一个超平面)。
在前面的可视化中,我们看到其“原始”表示的数据,你可以将其视为输入层。现在我们将看看经过第一层转化后,你可以认为这是我们看到了隐藏层。
每个维度对应于该层中神经元的兴奋。
在上一节中所概述的方法,我们知道通过查看每层的表示来了解网络。这给了我们一个离散的表示列表。
最棘手的部分是了解我们是如何从一个表示到另一个的。值得庆幸的是,神经网络层具有很好的性能,使这一点变得很容易。
神经网络由多种不同类型的层构成。我们将谈论一个具体的例子:双曲正切层(tanh)。一个双曲正切层tanh(Wx+b)由以下组成:
我们可以观察到这是一个连续变换,具体如下:
这个故事和其它标准层大体相同,由一个映射变换之后单调激活函数的逐点应用。
我们可以用这种技术来了解更复杂的网络。例如,下面的网络划分两个被略微缠结的螺旋,使用四个隐藏层。随着时间的推移,我们可以看到它的“原始”表示转移到更高层次为了对数据进行分类。而螺旋最初是纠结的,最终他们是线性可分的。
另一方面,以下的网络,也是使用多个层,分类两个螺旋没有成功,反而更加缠结。
这里值得明确指出,这些任务将变得有些困难,如果我们使用的是低维神经网络。如果我们使用更广泛的网络,这一切都将是相当容易的。
( Andrei Karpathy有 很好的演示 基于ConvnetJS,让您可以交互式地浏览网络,就像上面的这种可视化培训! )
每一层都会拉伸和挤压空间,但它永远不会切割、断裂和褶皱它。直观地说,我们可以看到它保留了拓扑性质。例如,一组数据将在转化后保持连接,如果它之前是连接的(反之亦然)。
这样的转换,不影响拓扑结构,被称为同胚。在形式上,他们是连续函数的双向映射。
定理 :具有N个输入和N个输出的层是同胚,如果权重矩阵W是非奇异的。(虽然需要小心它的值域和范围。)
证明 :让我们一步步考虑:
因此,如果W所有因子都是非零的,我们的层就是同胚的。∎
这一结果始终正确,如果我们将任意多个这些层组合在一起。
考虑包含两个类的二维数据集
![][01]
[01]: http://latex.codecogs.com/svg.latex?,A,B subsetmathbb{R}^2
A = {x | d(x,0) < 1/3}
B = {x | 2/3 < d(x,0) < 1}
如前面提到的,用一个S形函数或SOFTMAX层分类相当于试图找到一个超平面(或在这种情况下是一条线)在最终表示中分隔A与B。只有两个隐藏层的网络对于分离这组数据在拓扑上是无能的,并注定要失败。
在下面的可视化图中,我们观察到网络训练隐藏的表示,通过试图使用一条直线来分类。我们可以看到,它在努力学习某种方式来做到这一点是不断挣扎而且困难重重。
最后,它被拉到一个相当低效的拟合。虽然它实际上能够实现〜80%分类精度。
这个例子只有一个隐藏层,但无论如何它都会失败。
证明 :要么每层是一个同胚,要么该层的权重矩阵具有0因子。如果该层是同胚的,A被B所环绕,一个直线不能将它们分开。但是,假设它具有一个0因子:那么数据集将在某些轴上崩塌。因为我们正在处理的东西同胚于原始数据集,A被B所包围,在任一轴崩塌于意味着我们将有一些A中的点和B中的点混合,从而无法完成A与B的区分。∎
如果我们增加第三个隐藏层,问题就变得微不足道。神经网络学习以下表示:
用这个表示,我们可以用一个超平面分开数据集。
为了更好的理解这是怎么做到的,让我们考虑一个更简单的一维数据集:
![][02]
[02]: http://latex.codecogs.com/svg.latex?,A=[- frac{1}{3},,frac{1}{3}]
![][03]
[03]: http://latex.codecogs.com/svg.latex?,B=[-1,- frac{2}{3}]cup[frac{2}{3},1]
如果不使用两个或多个隐藏单元层,我们不能将此数据集进行分类。但是,如果我们使用一个带有两层的网络,我们就学会将数据转化成一个很好的曲线,让我们能用一条线将数据分开:
发生了什么?一个隐藏单元学习当x>-1/2时兴奋,另一个单元学习当x>1/2时兴奋。当第一个兴奋,而不是第二个时,我们知道数据属于A。
这个假说和现实世界的数据集相关吗,比如图像数据?如果你认真对待流形假说,我觉得他值得思考。
流形假说是指自然数据在它的嵌入空间构成了较低维度的数据流形。同时具有理论和实验的理由相信这一假说是真的。如果你相信这一点,那么分类算法的任务是从根本上分离一堆纠结的流形。
在前面的例子中,一个类完全被另一个类包围。然而,这似乎并不可能,比如狗的图像流形完全被猫的图像流形包围。因为我们将在下一节中看到其他更合理的拓扑情况。
另一个有趣的数据集要考虑的是两个链接的tori,A和B。
就像之前的数据集,这个数据不能被分离,如果不使用n+1维,即4个维度。
链接在结点理论(knot theory)中被讨论,拓扑学的一个领域。有时,当我们看到一个链接,并不能一眼看出它是否真正相连(一堆被缠结在一起的事情,但可以通过连续变形分开)。
如果仅仅使用3个层次的神经网络就能够对其进行分类,那么它就是一个未链接(unlink)。(问:理论上是否能将所有未链接都通过只有3个层次的网络进行分类?)
从这个结的角度看,我们通过神经网络产生的连续可视化不仅仅是一个漂亮的动画,它是解开链接的程序。在拓扑学中,我们把它称为原始链接和分离环之间一个环境同痕(an ambient isotopy)。
形式上,流形A和B之间的一个环境同痕是一个连续函数F:[0,1]× X→Y,使得每个Ft是一个从X到它自己范围的同胚,F0是一个标识函数,并F1是从A到B的一个映射。也就是,Ft是从A到自身的映射到从A到B的映射的连续转换。
定理 :在输入和网络层之间具有环境同痕,如果:
证明 :同样,我们分别考虑网络的每个阶段:
我想这也许是十分有趣的,通过程序自动发现这样的环境同痕并自动证明某些链接的等价性,或者某些环节是可分离的。这将很有趣知道,如果神经网络是否可以各种情况。
(显然,确定结点是否重要是一个NP,这不太适用于神经网络。)
我们已经谈到的这类链接,到目前为止似乎不太可能是现实世界的数据,但他们是更高维的生成。这似乎是合理的。
链接和结点是1维流形,但我们需要4个维度才能够解开他们。类似地,可能需要更高维度的空间,以便能够解开n维流形。所有n维流形可在2n+2维度上解开。
(我对于结点理了解不多,确实需要更多地了解维度和链接。如果我们知道一个流形可以被嵌入到n维空间,而不是流形的维度,我们有什么限制? )
很自然的想法,一个神经网络试图直接将流形从纠结尽可能薄的部分拉出。虽然这不会在任何情况下都是一个好的解决方案,但是大多情况它可以实现较高的分类准确率,到达一个诱人的最低点(local miminum)。
它试图拉伸具有高延展性的空间,并锐化靠近中断处。我们知道这些事情发生。压缩的处罚,在对数据点衍生层的处罚,都是很自然的做法。
由于这些局部最小点对于解决这种拓扑问题完全无用,拓扑问题值得很好的探索。
在另一方面,如果我们只关心取得了良好的分类结果,好像我们可能并不关心。如果很小的一个数据流形的点陷入另一个流形,会是一个问题吗?看起来我们应该能够得到很好的分类结果,尽管有这个问题。
(我的直觉是,像这样欺骗自己是一个坏主意:这是很难想象它不会是死路一条。特别是,针对一个局部最小很重要的优化问题,选择这种方式不能真正解决问题,这似乎是糟糕的表现。)
我越思考标准的神经网络层 - 即用映射变换后逐点激活功能 - 我就越不抱幻想。很难想象,他们能够很好地操纵流形。
也许这可能是有意义的,我们采用一个非常不同的层,而不是传统的神经网络层?
非常自然的感觉是,通过一个矢量场的学习,我们希望流形移动方向:
然后再对他变形空间:
人们可以学会在固定点的矢量场(只是需要从训练集合选取一些固定点作为锚),并以某种方式介入。上面的矢量场的形式是:
![][04]
[04]: http://latex.codecogs.com/svg.latex?,F(x)= frac{v_0f_0(x)+v_1f_1(x)}{1+f_0(x)+f_1(x)}
其中,v0和v1是矢量,F0(X)和F1(X)是n维高斯函数。这一点来自于径向基函数(radial basis functions)的灵感。
我也开始觉得线性可分可能是一个巨大的,也可能不合理的,神经网络的需求。在某些方面,非常自然的会想到使用K-近邻(K-NN)。然而,K-NN的成功在很大程度上取决于它所分类的数据表示(represention),因此,人们在K-NN之前,需要一种良好的表示。
作为第一个实验中,我训练了一些MNIST网络(两层卷积网,没有下降现象)到达〜1%测试误差。然后我放弃了最后的SOFTMAX层而使用K-NN算法,我能够始终如一地降低0.1-0.2%的测试误差。
不过,这并不完全觉得是正确的事情。该网络还在试图做线性分类,但由于我们使用K-NN测试,它能够从它所犯的错误中恢复一些。
K-NN有区别于相对于它的网络层次,因为会用到(1 /距离值)加权。因此,我们可以直接训练网络K-NN分类。这可以被认为是一种“k-NN”层替SOFTMAX。
我们不希望为每个小批量数据遍历整个训练集,因为这将非常消耗计算资源。我认为一个很好的办法是根据小批次的其它元素对每个小批次的元素进行分类,赋予每一个元素(1 /从分类目标的距离)的权重。
可悲的是,即使有完善的体系结构,采用K-NN只下到5-4%检测错误 - 使用简单的架构会得到更坏的结果。不过,我已经很少把努力放在高维参数上了。
不过,我真的很喜欢这个方法,因为它好像就是我们“要求”网络运行的更加合理。我们希望在同一流形的点比其它的点更加接近,相对于由一个超平面被分离的其他流形。这相对需要拉伸不同类别流形之间的空间,同时收缩每一个流形。这感觉就像是在简化问题。
具有拓扑性质的数据,例如链接,可能导致无法使用低维网络进行线性分类,无论深度有多大。即使在技术上是可能的情况下,例如螺旋,也是非常具有挑战性的。
为了使神经网络准确的分类数据,多个层次有时是必要的 。此外,传统的神经网络层似乎并不能很好的处理流形数据;即使我们巧妙的手工设置权重,想要紧凑的表达我们想要的转换也是非常困难的。新建层次,特别使用流形相关的机器学习,可能是有用的补充。
(这是一个发展中的研究项目。相关研究信息会在网上公布。我会很高兴听听您对这些想法的反馈:您可以发表评论。对于错别字,技术错误,或任何澄清,我们鼓励你发一个请求在GitHub上。)
致谢
谢谢Yoshua Bengio,迈克尔·尼尔森,达里奥 Amodei,埃利安娜洛奇,雅各布斯坦哈特和Tamsyn Waterhouse的意见和鼓励。
F. 轻松体验TensorFlow 第一个神经网络:基本分类(Part 1)
关于 Jupyter Notebook 的使用,可以参考如下链接,有详细的步骤和截图:
Jupyter Notebook神器-免费体验来自微软的Azure Notebook
基于Jupyter Notebook 快速体验Python和plot()绘图方法
基于Jupyter Notebook 快速体验matplotlib.pyplot模块中绘图方法
TensorFlow 基本分类(basic classification)演示的完整代码,可以访问:
上述命令运行时间较长,请耐心等待。
pip list 命令用来查看当前环境下的Python 包,grep 命令用来查找和筛选。中间的竖线表示 pipe(管道),将pip list 命令的输出作为 grep 命令的输入。
pip 前面的感叹号是cell 中运行 Linux 命令的方式,在命令行中运行则不需要加感叹号。
上述命令的输出,表示当前环境已经安装好了 TensorFlow 包。如果没有安装,可以通过如下命令安装:
安装TensorFlow命令,说明如下:
本地安装TensorFlow,截图如下。
TensorFlow 安装完成:
下面训练了一个神经网络模型,来对服装图像进行分类,例如运动鞋和衬衫。需要使用tf.keras,这是一个用于在TensorFlow 中构建和训练模型的高级API。
下面使用Fashion MNIST 数据集,其中包含了10个类别中共70,000张灰度图像。图像包含了低分辨率(28 x 28像素)的单个服装物品,图片链接如下所示:
Fashion-MNIST是一个替代MNIST手写数字集的图像数据集。 它是由Zalando(一家德国的 时尚 科技 公司)旗下的研究部门提供。其涵盖了来自10种类别的共7万个不同商品的正面图片。Fashion-MNIST的大小、格式和训练集/测试集划分与原始的MNIST完全一致。60000/10000的训练测试数据划分,28x28的灰度图片。可以直接用它来测试你的机器学习和深度学习算法性能,且不需要改动任何的代码。
MNIST是 Mixed National Institute of Standards and Technology database 的简写。
下面使用60,000张图像来训练网络和10,000张图像来评估网络模型学习图像分类任务的准确程度。
可以直接从TensorFlow 使用Fashion MNIST,只需导入并加载数据。
加载数据集并返回四个NumPy数组:
图像是28x28 NumPy数组,像素值介于0到255之间。labels是一个整数数组,数值介于0到9之间。
下面是图像类别和标签的对应关系:
每个图像都映射到一个标签。由于类别名称不包含在数据集中,因此把他们存储在这里以便在绘制图像时使用:
以下显示训练集中有60,000个图像,每个图像表示为28 x 28像素:
训练集中有 60000个标签,并且每个标签都是0-9 之间的整数。
测试集和训练集类似,有10000个图像和对应的10000个图像标签。
在训练网络之前必须对数据进行预处理。 如果检查训练集中的第一个图像,将看到像素值落在0到255的范围内:
代码说明:
plt.figure() 创建一个新的figure。
plt.colorbar() 方法用来显示当前image 的颜色方案。
在发送到神经网络模型之前,我们将这些值缩放到0到1的范围(归一化处理)。为此,我们将像素值值除以255。重要的是,对训练集和测试集要以相同的方式进行预处理:
显示训练集中的前25个图像,并在每个图像下方显示类别名。验证数据格式是否正确,我们是否已准备好构建和训练网络。
代码说明:
plt.xticks([])和plt.yticks([]) - 以空list 作为xticks() 方法的参数,查看数据集中图像隐藏坐标轴。
plt.xlabel() 方法可以在 x 轴的下方显示指定文本。
plt.subplot(5,5,1) 方法 - 表示5行5列共25个位置,最后一个参数1 表示Axes的位置,第一行的位置编号为:1-5,第二行的位置编号为:6-10,依此类推。
上述代码遍历了25 个位置(for i in range(25)),批量显示多张图。针对每一个位置,设置隐藏x和y轴,不显示网关线(grid),在对应的位置显示图像以及类别(label)。
需要注意的地方:Axes 位置的起始值是1,不是常见的0。
对TensorFlow 深度学习有兴趣的同学,可以访问如下链接。
G. 初识卷积神经网络
按照上文中介绍的神经网络,如果处理一张图片的话,参数有多大呢?假设图像的大小为1200 * 1200,下一层的神经元个数为10^5,不难得出参数量为 1200 * 1200 * 10^5 = 1.44 * 10^12。可以看出一层的参数量就是很大了,如果再多加几层,那参数量大的应该是超出了内存的承受范围,这从研究和工程的角度都是不允许的。而且参数太多,很容易造成过拟合。
怎么解决这个问题呢?经过研究,从稀疏连接、参数共享和平移不变性三个方面来进行改进。
可能有些人不懂这种稀疏连接是怎么实现的?先来说说卷积操作,以一个二维矩阵为输入(可以看作是一个单通道图片的像素值),卷积产生的稀疏连接根本原因就是这块的核函数,一般的核函数的大小远小于输入的大小。
以下图例:卷积操作可以看做是一种滑窗法,首先,输入维度是4×4,输入中红色部分,先和核函数中的元素对应相乘,就是输出中左上角的元素值s1,即 s1 = a×k1+b×k2+e×k3+f×k4。
参数共享是指在一个模型的多个函数中使用相同的参数,它是卷积运算带来的固有属性。
在全连接中,计算每层的输出时,权重矩阵中的元素只作用于某一个输入元素一次;
而在卷积神经网络中,卷积核中的每一个元素将作用于每一个局部输入的特定位置上。根据参数共享的思想,我们只需要学习一组参数集合,而不需要针对每一个位置的每一个参数来进行优化学习,从而大大降低了模型的存储需求。
如果一个函数的输入做了一些改变,那么输出也跟着做出同样的改变,这就时平移不变性。
平移不变性是由参数共享的物理意义所得。在计算机视觉中,假如要识别一个图片中是否有一只猫,那么无论这只猫在图片的什么位置,我们都应该识别出来,即就是神经网络的输出对于平移不变性来说是等变的。
根据稀疏连接、参数共享和平移不变性三个思想,卷积核就应运而生了。看下图,有个直观的感受。
上图就是在一个通道上做的卷积,但现实中,图片一般是由3个通道构成(R\G\B),卷积核也由二维的平面生成了三维立体。具体的样子如下图:
如上图所示,Filter W0 即为卷积核,其大小为(3 * 3 * 3),每个3*3的二维平面会和图片的相应的通道进行卷积,3个通道的结果相加后加上统一的偏置b0,结果即为Output Volume 第一个通道的第一个位置的数。
从上图还可以看出 Input Volume 四周加了0,这个0叫做padding,一般是为了卷积划动的过程中包含原有的所有数;而多通道卷积核计算过程和卷积核计算过程,不太一样的是多通道卷积核计算过程每次滑2下,这个滑动的距离叫做步长-stride。
所以通过输入大小和卷积核大小,我们可以推断出最终的结果的大小。比如上图卷积核计算过程,输入大小为5 * 5,卷积核为3 * 3,那么卷积核在原图上每次滑动一格,横向滑3次,纵向也是3次,最终结果为 3 * 3。在多通道卷积核计算过程中,每次滑动为2格,横向滑3次,纵向也是3次,最终结果也为 3*3。可以推断出,最终大小的公式为:(输入大小 - 卷积核大小)/ 滑动步长。
在卷积核计算过程,可以看出经过卷积后的大小变小了,那能不能经过卷积计算且大小不变呢?这里,引出了 padding 的另一个作用,保证输入和输出的大小一致。比方输出的 5*5 加 padding,那么四周就被0围绕了,这时的输入大小就变为7 * 7, 再经过 3 * 3的卷积后,按照上边推断出的公式,可以得出 最终的大小为 5 * 5,这时与输入大小保持了一致。
池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。
简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。
池化层用的方法有Max pooling 和 average pooling,而实际用的较多的是Max pooling。下图演示一下Max pooling。
对于每个2 * 2的窗口选出最大的数作为输出矩阵的相应元素的值,比如输入矩阵第一个2 * 2窗口中最大的数是1,那么输出矩阵的第一个元素就是1,如此类推。
全连接层的部分就是将之前的结果展平之后接到最基本的神经网络了。
根据上边的介绍,可以得出,卷积核的通道数目和输入的图像的通道数目是保持一致的,而输出的通道数目是和卷积核数目是一致的。这样参数量可以得出,假设输入的通道为5,卷积核大小为 3 * 3 ,输出的通道数目为10,那么参数量为:3 * 3 * 5 * 10,其中3 * 3 * 5是1个卷积核的参数个数,3 * 3 * 5 * 10 是 10个卷积核的参数个数,也就总共的参数个数。
在卷积中,滑动一次会经过多次的点乘,只经过一次的加法,所以加法的计算量可以忽略不计。其中,滑动一次会的点乘次数和卷积核的大小有关系,比方 3 * 3的卷积,则是经过了 3 * 3 = 9次点积。一共滑动多少次和输出大小有关系,比方 输出的结果也为 3 * 3,那么就是滑动了9次。这样就可以得出输入和输出单通道时计算量 3 * 3 * 3 * 3 = 81。那么对于输入多通道时,卷积核也需要增加相应的通道数目,此时应该在刚才的计算量上乘以通道的数目,得出输入多通道的一个卷积核的计算量。这样,对于输出多通道,总的计算量则是乘以多个卷积核即可。
H. 神经网络从何而来
【嵌牛导读】神经网络从何而来?这里说的『从何而来』,并不仅仅是从技术上去介绍一个方法的创造或发展,而更想探讨方法背后所蕴含的思想基础与演变之路。
【嵌牛鼻子】神经网络、深度学习
【嵌牛提问】神经网络的由来?
【嵌牛正文】深度学习与神经网络是近几年来计算机与人工智能领域最炙手可热的话题了。为了蹭这波热度,博主也打算分享一些自己的经验与思考。第一篇文章想探讨一个非常基础的问题:神经网络从何而来?这里说的『从何而来』,并不仅仅是从技术上去介绍一个方法的创造或发展,而更想探讨方法背后所蕴含的思想基础与演变之路。
首先,需要为『神经网络』正一下名。在人工智能领域,我们通常所说的神经网络(Neural Networks)全称是人工神经网络(Artificial Neural Network),与之对应的是我们用肉长成的生物神经网络(Biology Neural Network)。众所周知,人工神经网络受生物神经网络的启发而产生,并在几十年间不断进步演化。可要论人类对人工智能的探索历史,却远远长于这几十年。为了深刻了解神经网络出现的背景,我们有必要从更早的历史开始说起。
简单说,人工智能想做的事情就是去总结和提炼人类思考的过程,使之能够机械化、可重复。从各种神话、传说来看,我们的祖先在几千年前就对这件事儿充满了好奇与遐想。到两千多年前,一大批伟大的哲学家在希腊、中国和印度相继诞生,并将人类对这一问题的认识推向了新的高度。为避免本文成为枯燥的哲学史,这里不想举太多的例子。伟大的希腊哲学家亚里士多德在他的《前分析篇》中提出了著名的三段论(sollygism),类似于:
所有希腊人是人
所有人终有一死
因此所有希腊人终有一死
虽然这是我们现在已经无比熟悉的推理模式,但是要在2000年前从无到有系统总结出一系列这样的命题与推理模式,却着实不易。有了『三段论』这种的武器,人们对问题的认识与决策就能从感性真正走向理性,做到可以重复。此外,我们熟悉的欧式几何也是当时这种逻辑推理学派的代表。欧式几何以一系列的公理为基础,基于一套严密的逻辑推理体系,最终得到结论的证明,现在仍然是每个学生需要反复训练的思维体操。
随着时间的演进,认知哲学与逻辑学也在不断的发展。在17世纪时,以笛卡尔、莱布尼茨为代表的哲学家进一步提出通过数学的方式对逻辑推演进行标准化,这也是对人脑推理与思考的再次抽象,为后续以后基于数字电路的人工智能打下了基础。之后,数理逻辑进一步发展,而到了20世纪中期,数理逻辑又一次取得了巨大的突破,哥德尔不完备理论、图灵机模型等的相继提出,科学家们既认识到了数理逻辑的局限性,也看到了将推理机械化的无限可能性,一种新的计算方式呼之欲出。
在图灵机的思想指导下,第一台电子计算机很快被设计出来,为人工智能的真正实现提供了物质上的基础。其实回望人工智能历史上的历次重大飞跃,硬件技术的发展无不扮演者重要的作用。很多看似有效的算法都苦于没有足够强大的计算平台支持无疾而终,而计算能力的提升也可以促进科学家们们摆脱束缚,在算法的研究道路上天马行空。深度学习这些年的迅猛发展,很大程度就是得益于大规模集群和图形处理器等技术的成熟,使得用复杂模型快速处理大规模数据成为可能。
1956年达特茅斯会议上,斯坦福大学科学家约翰·麦卡锡(John McCarthy)正式提出了『人工智能』这一概念, 标志着一个学科的正式诞生,也标志着人工智能的发展开始进入了快车道。如果说逻辑符号操作是对人类思维的本质的抽象,那么利用电子计算机技术来模拟人类的符号推理计算也是一个自然而然的想法。在艾伦·纽威尔(Alan Newell)和赫伯特·西蒙(Herbert A.Simon)等大师的推动下,以逻辑推演为核心符号主义(symbolicism)流派很快占据了人工智能领域的重要地位。符号主义在很多领域取得了成功,比如在80年代风靡一时的专家系统,通过知识库和基于知识库的推理系统模拟专家进行决策,得到了广泛的应用。而本世纪初热炒的语义网络以及当下最流行的知识图谱,也可以看做这一流派的延续与发展。
符号主义最大的特点是知识的表示直观,推理的过程清晰,但是也存在着许多局限性。除去在计算能力方面的困扰,一个很大的问题就在于虽然我们可以通过逻辑推理解决一些复杂的问题,但是对一些看似简单的问题,比如人脸识别,却无能为力。当看到一张人脸的照片,我们可以毫不费力的识别出这个人是谁,可这个过程并不需要做什么复杂的推理,它在我们的大脑中瞬间完成,以至于我们对这个过程的细节却一无所知。看起来想通过挖掘一系列严密的推理规则解决这类问题是相对困难的,这也促使很多人去探索与人脑工作更加贴合的解决方案。实际上在符号主义出现的同时,人工智能的另一重要学派联结主义(Connectionism)也开始蓬勃发展,本文的『主角』神经网络终于可以登场了。
在文章的一开始就提到,我们现在所说的人工神经网络是受生物神经网络启发而设计出来的。在1890年,实验心理学先驱William James在他的巨著《心理学原理》中第一次详细论述人脑结构及功能。其中提到神经细胞受到刺激激活后可以把刺激传播到另一个神经细胞,并且神经细胞激活是细胞所有输入叠加的结果。这一后来得到验证的假说也成为了人工神经网络设计的生物学基础。基于这一假说,一系列模拟人脑神经计算的模型被相继提出,具有代表性的有Hebbian Learning Rule, Oja's Rule和MCP Neural Model等,他们与现在通用的神经网络模型已经非常相似,例如在Hebbian Learning模型中,已经可以支持神经元之间权重的自动学习。而在1958年,Rosenblatt将这些模型付诸于实施,利用电子设备构建了真正意义上的第一个神经网络模型:感知机(Perceptron)。Rosenblatt现场演示了其学习识别简单图像的过程,在当时的社会引起了轰动,并带来了神经网络的第一次大繁荣。此后的几十年里,神经网络又经历了数次起起伏伏,既有春风得意一统天下的岁月,也有被打入冷宫无人问津的日子,当然,这些都是后话了。
本文更想讨论这样一个问题:神经网络产生的动机仅仅是对生物学中对神经机制的模仿吗?在神经网络产生的背后,还蕴含着一代代科学家怎么样的思想与情怀呢?事实上,在神经网络为代表的一类方法在人工智能中又被称为联结主义(Connectionism)。关于联结主义的历史,一般的文献介绍按照惯例会追溯到希腊时期哲学家们对关联性的定义与研究,例如我们的老朋友亚里士多德等等。然而当时哲学家研究的关联其实并不特指神经元之间的这种关联,比如前文提到的符号推理本身也是一种形式关联,在希腊哲学中并没有对这两者进行专门的区分。所以硬要把这些说成是连接主义的思想起源略微有一些牵强。
前文提到,在数理逻辑发展过程中,17世纪的欧陆理性主义起到了重要的作用。以笛卡尔、莱布尼茨等为代表的哲学家,主张在理性中存在着天赋观念,以此为原则并严格按照逻辑必然性进行推理就可以得到普遍必然的知识。与此同时,以洛克、休谟等哲学家为代表的英国经验主义,则强调人类的知识来自于对感知和经验归纳。这一定程度上是对绝对的真理的一种否定,人类的认识是存在主观的,随经验而变化的部分的。如果在这个思想的指导下,我们与其去寻找一套普世且完备的推理系统,不如去构造一套虽不完美但能够随着经验积累不断完善的学习系统。而休谟甚至提出了放弃揭示自然界的因果联系和必然规律,而是依据“习惯性联想”去描绘一连串的感觉印象。这其实和神经网络设计的初衷是非常类似的:重视经验的获得与归纳(通过样本进行学习),但对模型本身的严谨性与可解释行则没有那么关注,正如有时候我们愿意把神经网络模型看做是一个『黑箱』。
然而单单一个『黑箱』是不能成为经验的学习与整理的系统的,我们还需要去寻找构建『黑箱』的一种方法论。现代哲学发展到20世纪初期时,在维特根斯坦和罗素等哲学家的倡导下,产生了逻辑经验主义学派。依托当时逻辑学的迅猛发展,这一主义既强调经验的作用,也重视通过严密的逻辑推理来得到结论,而非简单的归纳。在数理逻辑领域颇有建树的罗素有一位大名鼎鼎的学生诺伯特·维纳,他创立的控制论与系统论、信息论一道,为信息科学的发展提供了坚实的理论基础。而神经网络模型的创立也深受这『三论』的影响。前文提到MCP神经元模型的两位创始人分别是罗素和维纳的学生。作为一个系统,神经网络接受外部的输入,得到输出,并根据环境进行反馈,对系统进行更新,直到达到稳定状态。这个过程,同样也是神经网络对环境信息传递的接受和重新编码的过程。如果如果把神经网络当做一个『黑盒』,那么我们首先关心该是这个黑盒的输入与输出,以及如何根据环境给黑盒一个合理的反馈,使之能够进行调整。而黑盒内部的结构,则更多的成为了形式的问题。我们借鉴生物神经网络构造这个黑盒,恰好是一个好的解决方案,但这未必是唯一的解决方案或者说与人类大脑的神经元结构存在必然的联系。比如在统计学习领域中最著名的支持向量机(Support Vector Machines),最终是作为一种特殊的神经网络而提出的。可当其羽翼丰满之后,则和神经网络逐渐脱离关系,开启了机器学习的另一个门派。不同的模型形式之间可以互相转化,但是重视经验(样本),强调反馈的思想却一直保留下来。
前面说了这些,到底神经网络从何而来呢?总结下来就是三个方面吧:1.对理性逻辑的追求,对样本实证的重视,为神经网络的诞生提供了思想的基础。2.生物学与神经科学的发展为神经网络形式的出现提供了启发。3.计算机硬件的发展与计算能力的提升使神经网络从理想变成了现实。而这三方面的发展也催生着神经网络的进一步发展与深度学习的成熟:更大规模的数据,更完善的优化算法使网络能够学习到更多更准确的信息;对人脑的认识的提升启发设计出层次更深,结构更高效的网络结构;硬件存储与计算能力提升使海量数据的高效训练成为可能。而未来神经网络给我们带来的更多惊喜,也很大可能源自于这三个方面,让我们不妨多一些期待吧。
I. 一文读懂神经网络
要说近几年最引人注目的技术,无疑的,非人工智能莫属。无论你是否身处科技互联网行业,随处可见人工智能的身影:从 AlphaGo 击败世界围棋冠军,到无人驾驶概念的兴起,再到科技巨头 All in AI,以及各大高校向社会输送海量的人工智能专业的毕业生。以至于人们开始萌生一个想法:新的革命就要来了,我们的世界将再次发生一次巨变;而后开始焦虑:我的工作是否会被机器取代?我该如何才能抓住这次革命?
人工智能背后的核心技术是深度神经网络(Deep Neural Network),大概是一年前这个时候,我正在回老家的高铁上学习 3Blue1Brown 的 Neural Network 系列视频课程,短短 4 集 60 多分钟的时间,就把神经网络从 High Level 到推导细节说得清清楚楚,当时的我除了获得新知的兴奋之外,还有一点新的认知,算是给头脑中的革命性的技术泼了盆冷水:神经网络可以解决一些复杂的、以前很难通过写程序来完成的任务——例如图像、语音识别等,但它的实现机制告诉我,神经网络依然没有达到生物级别的智能,短期内期待它来取代人也是不可能的。
一年后的今天,依然在这个春运的时间点,将我对神经网络的理解写下来,算是对这部分知识的一个学习笔记,运气好的话,还可以让不了解神经网络的同学了解起来。
维基网络这样解释 神经网络 :
这个定义比较宽泛,你甚至还可以用它来定义其它的机器学习算法,例如之前我们一起学习的逻辑回归和 GBDT 决策树。下面我们具体一点,下图是一个逻辑回归的示意图:
其中 x1 和 x2 表示输入,w1 和 w2 是模型的参数,z 是一个线性函数:
接着我们对 z 做一个 sigmod 变换(图中蓝色圆),得到输出 y:
其实,上面的逻辑回归就可以看成是一个只有 1 层 输入层 , 1 层 输出层 的神经网络,图中容纳数字的圈儿被称作 神经元 ;其中,层与层之间的连接 w1、w2 以及 b,是这个 神经网络的参数 ,层之间如果每个神经元之间都保持着连接,这样的层被称为 全连接层 (Full Connection Layer),或 稠密层 (Dense Layer);此外,sigmoid 函数又被称作 激活函数 (Activation Function),除了 sigmoid 外,常用的激活函数还有 ReLU、tanh 函数等,这些函数都起到将线性函数进行非线性变换的作用。我们还剩下一个重要的概念: 隐藏层 ,它需要把 2 个以上的逻辑回归叠加起来加以说明:
如上图所示,除输入层和输出层以外,其他的层都叫做 隐藏层 。如果我们多叠加几层,这个神经网络又可以被称作 深度神经网络 (Deep Neural Network),有同学可能会问多少层才算“深”呢?这个没有绝对的定论,个人认为 3 层以上就算吧:)
以上,便是神经网络,以及神经网络中包含的概念,可见,神经网络并不特别,广义上讲,它就是
可见,神经网络和人脑神经也没有任何关联,如果我们说起它的另一个名字—— 多层感知机(Mutilayer Perceptron) ,就更不会觉得有多么玄乎了,多层感知机创造于 80 年代,可为什么直到 30 年后的今天才爆发呢?你想得没错,因为改了个名字……开个玩笑;实际上深度学习这项技术也经历过很长一段时间的黑暗低谷期,直到人们开始利用 GPU 来极大的提升训练模型的速度,以及几个标志性的事件:如 AlphaGo战胜李世石、Google 开源 TensorFlow 框架等等,感兴趣的同学可以翻一下这里的历史。
就拿上图中的 3 个逻辑回归组成的神经网络作为例子,它和普通的逻辑回归比起来,有什么优势呢?我们先来看下单逻辑回归有什么劣势,对于某些情况来说,逻辑回归可能永远无法使其分类,如下面数据:
这 4 个样本画在坐标系中如下图所示
因为逻辑回归的决策边界(Decision Boundary)是一条直线,所以上图中的两个分类,无论你怎么做,都无法找到一条直线将它们分开,但如果借助神经网络,就可以做到这一点。
由 3 个逻辑回归组成的网络(这里先忽略 bias)如下:
观察整个网络的计算过程,在进入输出层之前,该网络所做的计算实际上是:
即把输入先做了一次线性变换(Linear Transformation),得到 [z1, z2] ,再把 [z1, z2] 做了一个非线性变换(sigmoid),得到 [x1', x2'] ,(线性变换的概念可以参考 这个视频 )。从这里开始,后面的操作就和一个普通的逻辑回归没有任何差别了,所以它们的差异在于: 我们的数据在输入到模型之前,先做了一层特征变换处理(Feature Transformation,有时又叫做特征抽取 Feature Extraction),使之前不可能被分类的数据变得可以分类了 。
我们继续来看下特征变换的效果,假设 为 ,带入上述公式,算出 4 个样本对应的 [x1', x2'] 如下:
再将变换后的 4 个点绘制在坐标系中:
显然,在做了特征变换之后,这两个分类就可以很容易的被一条决策边界分开了。
所以, 神经网络的优势在于,它可以帮助我们自动的完成特征变换或特征提取 ,尤其对于声音、图像等复杂问题,因为在面对这些问题时,人们很难清晰明确的告诉你,哪些特征是有用的。
在解决特征变换的同时,神经网络也引入了新的问题,就是我们需要设计各式各样的网络结构来针对性的应对不同的场景,例如使用卷积神经网络(CNN)来处理图像、使用长短期记忆网络(LSTM)来处理序列问题、使用生成式对抗网络(GAN)来写诗和作图等,就连去年自然语言处理(NLP)中取得突破性进展的 Transformer/Bert 也是一种特定的网络结构。所以, 学好神经网络,对理解其他更高级的网络结构也是有帮助的 。
上面说了,神经网络可以看作一个非线性函数,该函数的参数是连接神经元的所有的 Weights 和 Biases,该函数可以简写为 f(W, B) ,以手写数字识别的任务作为例子:识别 MNIST 数据集 中的数字,数据集(MNIST 数据集是深度学习中的 HelloWorld)包含上万张不同的人写的数字图片,共有 0-9 十种数字,每张图片为 28*28=784 个像素,我们设计一个这样的网络来完成该任务:
把该网络函数所具备的属性补齐:
接下来的问题是,这个函数是如何产生的?这个问题本质上问的是这些参数的值是怎么确定的。
在机器学习中,有另一个函数 c 来衡量 f 的好坏,c 的参数是一堆数据集,你输入给 c 一批 Weights 和 Biases,c 输出 Bad 或 Good,当结果是 Bad 时,你需要继续调整 f 的 Weights 和 Biases,再次输入给 c,如此往复,直到 c 给出 Good 为止,这个 c 就是损失函数 Cost Function(或 Loss Function)。在手写数字识别的列子中,c 可以描述如下:
可见,要完成手写数字识别任务,只需要调整这 12730 个参数,让损失函数输出一个足够小的值即可,推而广之,绝大部分神经网络、机器学习的问题,都可以看成是定义损失函数、以及参数调优的问题。
在手写识别任务中,我们既可以使用交叉熵(Cross Entropy)损失函数,也可以使用 MSE(Mean Squared Error)作为损失函数,接下来,就剩下如何调优参数了。
神经网络的参数调优也没有使用特别的技术,依然是大家刚接触机器学习,就学到的梯度下降算法,梯度下降解决了上面迭代过程中的遗留问题——当损失函数给出 Bad 结果时,如何调整参数,能让 Loss 减少得最快。
梯度可以理解为:
把 Loss 对应到 H,12730 个参数对应到 (x,y),则 Loss 对所有参数的梯度可以表示为下面向量,该向量的长度为 12730:
$$
abla L(w,b) = left[
frac{partial L}{partial w_1},
frac{partial L}{partial w_2},...,
frac{partial L}{partial b_{26}}
ight] ^ op
$$
所以,每次迭代过程可以概括为
用梯度来调整参数的式子如下(为了简化,这里省略了 bias):
上式中, 是学习率,意为每次朝下降最快的方向前进一小步,避免优化过头(Overshoot)。
由于神经网络参数繁多,所以需要更高效的计算梯度的算法,于是,反向传播算法(Backpropagation)呼之欲出。
在学习反向传播算法之前,我们先复习一下微积分中的链式法则(Chain Rule):设 g = u(h) , h = f(x) 是两个可导函数,x 的一个很小的变化 △x 会使 h 产生一个很小的变化 △h,从而 g 也产生一个较小的变化 △g,现要求 △g/△x,可以使用链式法则:
有了以上基础,理解反向传播算法就简单了。
假设我们的演示网络只有 2 层,输入输出都只有 2 个神经元,如下图所示:
其中 是输入, 是输出, 是样本的目标值,这里使用的损失函数 L 为 MSE;图中的上标 (1) 或 (2) 分别表示参数属于第 (1) 层或第 (2) 层,下标 1 或 2 分别表示该层的第 1 或 第 2 个神经元。
现在我们来计算 和 ,掌握了这 2 个参数的偏导数计算之后,整个梯度的计算就掌握了。
所谓反向传播算法,指的是从右向左来计算每个参数的偏导数,先计算 ,根据链式法则
对左边项用链式法则展开
又 是输出值, 可以直接通过 MSE 的导数算出:
而 ,则 就是 sigmoid 函数的导数在 处的值,即
于是 就算出来了:
再来看 这一项,因为
所以
注意:上面式子对于所有的 和 都成立,且结果非常直观,即 对 的偏导为左边的输入 的大小;同时,这里还隐含着另一层意思:需要调整哪个 来影响 ,才能使 Loss 下降得最快,从该式子可以看出,当然是先调整较大的 值所对应的 ,效果才最显著 。
于是,最后一层参数 的偏导数就算出来了
我们再来算上一层的 ,根据链式法则 :
继续展开左边这一项
你发现没有,这几乎和计算最后一层一摸一样,但需要注意的是,这里的 对 Loss 造成的影响有多条路径,于是对于只有 2 个输出的本例来说:
上式中, 都已经在最后一层算出,下面我们来看下 ,因为
于是
同理
注意:这里也引申出梯度下降的调参直觉:即要使 Loss 下降得最快,优先调整 weight 值比较大的 weight。
至此, 也算出来了
观察上式, 所谓每个参数的偏导数,通过反向传播算法,都可以转换成线性加权(Weighted Sum)计算 ,归纳如下:
式子中 n 代表分类数,(l) 表示第 l 层,i 表示第 l 层的第 i 个神经元。 既然反向传播就是一个线性加权,那整个神经网络就可以借助于 GPU 的矩阵并行计算了 。
最后,当你明白了神经网络的原理,是不是越发的认为,它就是在做一堆的微积分运算,当然,作为能证明一个人是否学过微积分,神经网络还是值得学一下的。Just kidding ..
本文我们通过
这四点,全面的学习了神经网络这个知识点,希望本文能给你带来帮助。
参考:
J. 神经网络浅谈
人工智能技术是当前炙手可热的话题,而基于神经网络的深度学习技术更是热点中的热点。去年谷歌的Alpha Go 以4:1大比分的优势战胜韩国的李世石九段,展现了深度学习的强大威力,后续强化版的Alpha Master和无师自通的Alpha Zero更是在表现上完全碾压前者。不论你怎么看,以深度学习为代表的人工智能技术正在塑造未来。
下图为英伟达(NVIDIA)公司近年来的股价情况, 该公司的主要产品是“图形处理器”(GPU),而GPU被证明能大大加快神经网络的训练速度,是深度学习必不可少的计算组件。英伟达公司近年来股价的飞涨足以证明当前深度学习的井喷之势。
好,话不多说,下面简要介绍神经网络的基本原理、发展脉络和优势。
神经网络是一种人类由于受到生物神经细胞结构启发而研究出的一种算法体系,是机器学习算法大类中的一种。首先让我们来看人脑神经元细胞:
一个神经元通常具有多个树突 ,主要用来接受传入信息,而轴突只有一条,轴突尾端有许多轴突末梢,可以给其他多个神经元传递信息。轴突末梢跟其他神经元的树突产生连接,从而传递信号。
下图是一个经典的神经网络(Artificial Neural Network,ANN):
乍一看跟传统互联网的拓扑图有点类似,这也是称其为网络的原因,不同的是节点之间通过有向线段连接,并且节点被分成三层。我们称图中的圆圈为神经元,左边三个神经元组成的一列为输入层,中间神经元列为隐藏层,右边神经元列为输出层,神经元之间的箭头为权重。
神经元是计算单元,相当于神经元细胞的细胞核,利用输入的数据进行计算,然后输出,一般由一个线性计算部分和一个非线性计算部分组成;输入层和输出层实现数据的输入输出,相当于细胞的树突和轴突末梢;隐藏层指既不是输入也不是输出的神经元层,一个神经网络可以有很多个隐藏层。
神经网络的关键不是圆圈代表的神经元,而是每条连接线对应的权重。每条连接线对应一个权重,也就是一个参数。权重具体的值需要通过神经网络的训练才能获得。我们实际生活中的学习体现在大脑中就是一系列神经网络回路的建立与强化,多次重复的学习能让回路变得更加粗壮,使得信号的传递速度加快,最后对外表现为“深刻”的记忆。人工神经网络的训练也借鉴于此,如果某种映射关系出现很多次,那么在训练过程中就相应调高其权重。
1943年,心理学家McCulloch和数学家Pitts参考了生物神经元的结构,发表了抽象的神经元模型MP:
符号化后的模型如下:
Sum函数计算各权重与输入乘积的线性组合,是神经元中的线性计算部分,而sgn是取符号函数,当输入大于0时,输出1,反之输出0,是神经元中的非线性部分。向量化后的公式为z=sgn(w^T a)(w^T=(w_1,w_2,w_3),a=〖(a_1,a_2,a_3)〗^T)。
但是,MP模型中,权重的值都是预先设置的,因此不能学习。该模型虽然简单,并且作用有限,但已经建立了神经网络大厦的地基
1958年,计算科学家Rosenblatt提出了由两层神经元组成(一个输入层,一个输出层)的神经网络。他给它起了一个名字–“感知器”(Perceptron)
感知器是当时首个可以学习的人工神经网络。Rosenblatt现场演示了其学习识别简单图像的过程,在当时引起了轰动,掀起了第一波神经网络的研究热潮。
但感知器只能做简单的线性分类任务。1969年,人工智能领域的巨擘Minsky指出这点,并同时指出感知器对XOR(异或,即两个输入相同时输出0,不同时输出1)这样的简单逻辑都无法解决。所以,明斯基认为神经网络是没有价值的。
随后,神经网络的研究进入低谷,又称 AI Winter 。
Minsky说过单层神经网络无法解决异或问题,但是当增加一个计算层以后,两层神经网络不仅可以解决异或问题,而且具有非常好的非线性分类效果。
下图为两层神经网络(输入层一般不算在内):
上图中,输出层的输入是上一层的输出。
向量化后的公式为:
注意:
每个神经元节点默认都有偏置变量b,加上偏置变量后的计算公式为:
同时,两层神经网络不再使用sgn函数作为激励函数,而采用平滑的sigmoid函数:
σ(z)=1/(1+e^(-z) )
其图像如下:
理论证明: 两层及以上的神经网络可以无限逼近真实的对应函数,从而模拟数据之间的真实关系 ,这是神经网络强大预测能力的根本。但两层神经网络的计算量太大,当时的计算机的计算能力完全跟不上,直到1986年,Rumelhar和Hinton等人提出了反向传播(Backpropagation,BP)算法,解决了两层神经网络所需要的复杂计算量问题,带动了业界使用两层神经网络研究的热潮。
但好景不长,算法的改进仅使得神经网络风光了几年,然而计算能力不够,局部最优解,调参等一系列问题一直困扰研究人员。90年代中期,由Vapnik等人发明的SVM(Support Vector Machines,支持向量机)算法诞生,很快就在若干个方面体现出了对比神经网络的优势:无需调参;高效;全局最优解。
由于以上原因,SVM迅速打败了神经网络算法成为主流。神经网络的研究再一次进入低谷, AI Winter again 。
多层神经网络一般指两层或两层以上的神经网络(不包括输入层),更多情况下指两层以上的神经网络。
2006年,Hinton提出使用 预训练 ”(pre-training)和“微调”(fine-tuning)技术能优化神经网络训练,大幅度减少训练多层神经网络的时间
并且,他给多层神经网络相关的学习方法赋予了一个新名词–“ 深度学习 ”,以此为起点,“深度学习”纪元开始了:)
“深度学习”一方面指神经网络的比较“深”,也就是层数较多;另一方面也可以指神经网络能学到很多深层次的东西。研究发现,在权重参数不变的情况下,增加神经网络的层数,能增强神经网络的表达能力。
但深度学习究竟有多强大呢?没人知道。2012年,Hinton与他的学生在ImageNet竞赛中,用多层的卷积神经网络成功地对包含一千类别的一百万张图片进行了训练,取得了分类错误率15%的好成绩,这个成绩比第二名高了近11个百分点,充分证明了多层神经网络识别效果的优越性。
同时,科研人员发现GPU的大规模并行矩阵运算模式完美地契合神经网络训练的需要,在同等情况下,GPU的速度要比CPU快50-200倍,这使得神经网络的训练时间大大减少,最终再一次掀起了神经网络研究的热潮,并且一直持续到现在。
2016年基于深度学习的Alpha Go在围棋比赛中以4:1的大比分优势战胜了李世石,深度学习的威力再一次震惊了世界。
神经网络的发展历史曲折荡漾,既有被捧上神坛的高潮,也有无人问津的低谷,中间经历了数次大起大落,我们姑且称之为“三起三落”吧,其背后则是算法的改进和计算能力的持续发展。
下图展示了神经网络自发明以来的发展情况及一些重大时间节点。
当然,对于神经网络我们也要保持清醒的头脑。由上图,每次神经网络研究的兴盛期持续10年左右,从最近2012年算起,或许10年后的2022年,神经网络的发展将再次遇到瓶颈。
神经网络作为机器学习的一种,其模型训练的目的,就是使得参数尽可能的与真实的模型逼近。理论证明,两层及以上的神经网络可以无限逼近真实的映射函数。因此,给定足够的训练数据和训练时间,总能通过神经网络找到无限逼近真实关系的模型。
具体做法:首先给所有权重参数赋上随机值,然后使用这些随机生成的参数值,来预测训练数据中的样本。假设样本的预测目标为yp ,真实目标为y,定义值loss,计算公式如下:
loss = (yp -y) ^2
这个值称之为 损失 (loss),我们的目标就是使对所有训练数据的损失和尽可能的小,这就转化为求loss函数极值的问题。
一个常用方法是高等数学中的求导,但由于参数不止一个,求导后计算导数等于0的运算量很大,所以常用梯度下降算法来解决这样的优化问题。梯度是一个向量,由函数的各自变量的偏导数组成。
比如对二元函数 f =(x,y),则梯度∇f=(∂f/∂x,∂f/∂y)。梯度的方向是函数值上升最快的方向。梯度下降算法每次计算参数在当前的梯度,然后让参数向着梯度的反方向前进一段距离,不断重复,直到梯度接近零时截止。一般这个时候,所有的参数恰好达到使损失函数达到一个最低值的状态。下图为梯度下降的大致运行过程:
在神经网络模型中,由于结构复杂,每次计算梯度的代价很大。因此还需要使用 反向传播 (Back Propagation)算法。反向传播算法利用了神经网络的结构进行计算,不一次计算所有参数的梯度,而是从后往前。首先计算输出层的梯度,然后是第二个参数矩阵的梯度,接着是中间层的梯度,再然后是第一个参数矩阵的梯度,最后是输入层的梯度。计算结束以后,所要的两个参数矩阵的梯度就都有了。当然,梯度下降只是其中一个优化算法,其他的还有牛顿法、RMSprop等。
确定loss函数的最小值后,我们就确定了整个神经网络的权重,完成神经网络的训练。
在神经网络中一样的参数数量,可以用更深的层次去表达。
由上图,不算上偏置参数的话,共有三层神经元,33个权重参数。
由下图,保持权重参数不变,但增加了两层神经元。
在多层神经网络中,每一层的输入是前一层的输出,相当于在前一层的基础上学习,更深层次的神经网络意味着更深入的表示特征,以及更强的函数模拟能力。更深入的表示特征可以这样理解,随着网络的层数增加,每一层对于前一层次的抽象表示更深入。
如上图,第一个隐藏层学习到“边缘”的特征,第二个隐藏层学习到“边缘”组成的“形状”的特征,第三个隐藏层学习到由“形状”组成的“图案”的特征,最后的隐藏层学习到由“图案”组成的“目标”的特征。通过抽取更抽象的特征来对事物进行区分,从而获得更好的区分与分类能力。
前面提到, 明斯基认为Rosenblatt提出的感知器模型不能处理最简单的“异或”(XOR)非线性问题,所以神经网络的研究没有前途,但当增加一层神经元后,异或问题得到了很好地解决,原因何在?原来从输入层到隐藏层,数据发生了空间变换,坐标系发生了改变,因为矩阵运算本质上就是一种空间变换。
如下图,红色和蓝色的分界线是最终的分类结果,可以看到,该分界线是一条非常平滑的曲线。
但是,改变坐标系后,分界线却表现为直线,如下图:
同时,非线性激励函数的引入使得神经网络对非线性问题的表达能力大大加强。
对于传统的朴素贝叶斯、决策树、支持向量机SVM等分类器,提取特征是一个非常重要的前置工作。在正式训练之前,需要花费大量的时间在数据的清洗上,这样分类器才能清楚地知道数据的维度,要不然基于概率和空间距离的线性分类器是没办法进行工作的。然而在神经网络中,由于巨量的线性分类器的堆叠(并行和串行)以及卷积神经网络的使用,它对噪声的忍耐能力、对多通道数据上投射出来的不同特征偏向的敏感程度会自动重视或忽略,这样我们在处理的时候,就不需要使用太多的技巧用于数据的清洗了。有趣的是,业内大佬常感叹,“你可能知道SVM等机器学习的所有细节,但是效果并不好,而神经网络更像是一个黑盒,很难知道它究竟在做什么,但工作效果却很好”。
人类对机器学习的环节干预越少,就意味着距离人工智能的方向越近。神经网络的这个特性非常有吸引力。
1) 谷歌的TensorFlow开发了一个非常有意思的神经网络 入门教程 ,用户可以非常方便地在网页上更改神经网络的参数,并且能看到实时的学习效率和结果,非常适合初学者掌握神经网络的基本概念及神经网络的原理。网页截图如下:
2) 深度学习领域大佬吴恩达不久前发布的《 神经网络和深度学习 》MOOC,现在可以在网易云课堂上免费观看了,并且还有中文字幕。
3) 《神经网络于深度学习》(Michael Nielsen著)、《白话深度学习与TensorFlow》也是不错的入门书籍。