此文基于周莫烦大神@莫烦的视频,文章以及各种论文以及自己的一些心得。
1.2.1 卷积神经网络 CNN
卷积和神经网络
卷积神经网络是近些年逐步兴起的一种人工神经网络结构, 因为利用卷积神经网络在图像和语音识别方面能够给出更优预测结果, 这一种技术也被广泛的传播可应用. 卷积神经网络最常被应用的方面是计算机的图像识别, 不过因为不断地创新, 它也被应用在视频分析, 自然语言处理, 药物发现, 等等. 近期最火的 Alpha Go, 让计算机看懂围棋, 同样也是有运用到这门技术.
我们来具体说说卷积神经网络是如何运作的吧, 举一个识别图片的例子, 我们知道神经网络是由一连串的神经层组成,每一层神经层里面有存在有很多的神经元. 这些神经元就是神经网络识别事物的关键. 每一种神经网络都会有输入输出值, 当输入值是图片的时候, 实际上输入神经网络的并不是那些色彩缤纷的图案,而是一堆堆的数字. 就比如说这个. 当神经网络需要处理这么多输入信息的时候, 也就是卷积神经网络就可以发挥它的优势的时候了. 那什么是卷积神经网络呢?
我们先把卷积神经网络这个词拆开来看. “卷积” 和 “神经网络”. 卷积也就是说神经网络不再是对每个像素的输入信息做处理了,而是图片上每一小块像素区域进行处理, 这种做法加强了图片信息的连续性. 使得神经网络能看到图形, 而非一个点. 这种做法同时也加深了神经网络对图片的理解. 具体来说, 卷积神经网络有一个批量过滤器, 持续不断的在图片上滚动收集图片里的信息,每一次收集的时候都只是收集一小块像素区域, 然后把收集来的信息进行整理, 这时候整理出来的信息有了一些实际上的呈现, 比如这时的神经网络能看到一些边缘的图片信息, 然后在以同样的步骤, 用类似的批量过滤器扫过产生的这些边缘信息, 神经网络从这些边缘信息里面总结出更高层的信息结构,比如说总结的边缘能够画出眼睛,鼻子等等. 再经过一次过滤, 脸部的信息也从这些眼睛鼻子的信息中被总结出来. 最后我们再把这些信息套入几层普通的全连接神经层进行分类, 这样就能得到输入的图片能被分为哪一类的结果了.
我们截取一段 google 介绍卷积神经网络的视频, 具体说说图片是如何被卷积的. 下面是一张猫的图片, 图片有长, 宽, 高 三个参数. 对! 图片是有高度的! 这里的高指的是计算机用于产生颜色使用的信息. 如果是黑白照片的话, 高的单位就只有1, 如果是彩色照片, 就可能有红绿蓝三种颜色的信息, 这时的高度为3. 我们以彩色照片为例子. 过滤器就是影像中不断移动的东西, 他不断在图片收集小批小批的像素块, 收集完所有信息后, 输出的值, 我们可以理解成是一个高度更高,长和宽更小的”图片”. 这个图片里就能包含一些边缘信息. 然后以同样的步骤再进行多次卷积, 将图片的长宽再压缩, 高度再增加, 就有了对输入图片更深的理解. 将压缩,增高的信息嵌套在普通的分类神经层上,我们就能对这种图片进行分类了.
池化
研究发现, 在每一次卷积的时候, 神经层可能会无意地丢失一些信息. 这时, 池化 (pooling) 就可以很好地解决这一问题. 也就是说在卷集的时候, 我们不压缩长宽, 尽量地保留更多信息, 压缩的工作就交给池化了,这样的一项附加工作能够很有效的提高准确性. 有了这些技术,我们就可以搭建一个属于我们自己的卷积神经网络啦.
流行的CNN结构
比较流行的一种搭建结构是这样, 从下到上的顺序, 首先是输入的图片(image), 经过一层卷积层 (convolution), 然后在用池化(pooling)方式处理卷积的信息, 这里使用的是 max pooling 的方式. 然后在经过一次同样的处理, 把得到的第二次处理的信息传入两层全连接的神经层 (fully connected),这也是一般的两层神经网络层,最后在接上一个分类器(classifier)进行分类预测.
1.2.2 循环神经网络 RNN
序列数据
CNN的局限在于他只能接受一个指定大小的输入,然后输出一个指定大小的结果。不仅如此,这个模型还使用了指定好的层数。然而,RNN的核心问题就是,它能够让我们操作序列数据。
你可能会想,处理序列的输入输出很少见,但是很重要的一点是,即使你的输入是固定的,那么用RNN来训练也是可以的。
我们想象现在有一组序列数据 data 0,1,2,3. 在当预测 result0 的时候,我们基于的是 data0, 同样在预测其他数据的时候, 我们也都只单单基于单个的数据. 每次使用的神经网络都是同一个 NN. 不过这些数据是有关联 顺序的 , 就像在厨房做菜, 酱料 A要比酱料 B 早放, 不然就串味了. 所以普通的神经网络结构并不能让 NN 了解这些数据之间的关联.
处理序列数据的神经网络
那我们如何让数据间的关联也被 NN 加以分析呢? 想想我们人类是怎么分析各种事物的关联吧, 最基本的方式,就是记住之前发生的事情. 那我们让神经网络也具备这种记住之前发生的事的能力. 再分析 Data0 的时候, 我们把分析结果存入记忆. 然后当分析 data1的时候, NN会产生新的记忆, 但是新记忆和老记忆是没有联系的. 我们就简单的把老记忆调用过来, 一起分析. 如果继续分析更多的有序数据 , RNN就会把之前的记忆都累积起来, 一起分析.
我们再重复一遍刚才的流程, 不过这次是以加入一些数学方面的东西. 每次 RNN 运算完之后都会产生一个对于当前状态的描述 , state. 我们用简写 S( t) 代替, 然后这个 RNN开始分析 x(t+1) , 他会根据 x(t+1)产生s(t+1), 不过此时 y(t+1) 是由 s(t) 和 s(t+1) 共同创造的. 所以我们通常看到的 RNN 也可以表达成这种样子.
下面的图能更清晰的解释这个原理:
RNN 的运用
RNN 的形式不单单这有这样一种, 他的结构形式很自由. 如果用于分类问题, 比如说一个人说了一句话, 这句话带的感情色彩是积极的还是消极的. 那我们就可以用只有最后一个时间点输出判断结果的RNN.
又或者这是图片描述 RNN, 我们只需要一个 X 来代替输入的图片, 然后生成对图片描述的一段话.或者是语言翻译的 RNN, 给出一段英文, 然后再翻译成中文.
有了这些不同形式的 RNN, RNN 就变得强大了. 有很多有趣的 RNN 应用. 比如之前提到的, 让 RNN 描述照片. 让 RNN 写学术论文, 让 RNN 写程序脚本, 让 RNN 作曲. 我们一般人甚至都不能分辨这到底是不是机器写出来的.
1.2.3 循环神经网络 LSTM RNN
colah.github.io/posts/2015-08-Understanding-LSTMs/
RNN 的弊端
之前我们说过, RNN 是在有顺序的数据上进行学习的. 为了记住这些数据, RNN 会像人一样产生对先前发生事件的记忆. 不过一般形式的 RNN 就像一个老爷爷, 有时候比较健忘. 为什么会这样呢?
想像现在有这样一个 RNN, 他的输入值是一句话: ‘我今天要做红烧排骨, 首先要准备排骨, 然后…., 最后美味的一道菜就出锅了’, shua ~ 说着说着就流口水了. 现在请 RNN 来分析, 我今天做的到底是什么菜呢. RNN可能会给出“辣子鸡”这个答案. 由于判断失误, RNN就要开始学习 这个长序列 X 和 ‘红烧排骨’ 的关系 , 而RNN需要的关键信息 ”红烧排骨”却出现在句子开头,
再来看看 RNN是怎样学习的吧. 红烧排骨这个信息原的记忆要进过长途跋涉才能抵达最后一个时间点. 然后我们得到误差, 而且在 反向传递 得到的误差的时候, 他在每一步都会 乘以一个自己的参数 W. 如果这个 W 是一个小于1 的数, 比如0.9. 这个0.9 不断乘以误差, 误差传到初始时间点也会是一个接近于零的数, 所以对于初始时刻, 误差相当于就消失了. 我们把这个问题叫做梯度消失或者梯度弥散 Gradient vanishing. 反之如果 W 是一个大于1 的数, 比如1.1 不断累乘, 则到最后变成了无穷大的数, RNN被这无穷大的数撑死了, 这种情况我们叫做梯度爆炸, Gradient exploding. 这就是普通 RNN 没有办法回忆起久远记忆的原因.
LSTM(Long Short Term Memory)
LSTM 就是为了解决这个问题而诞生的. LSTM 和普通 RNN 相比, 多出了三个控制器. (输入控制, 输出控制, 忘记控制). 现在, LSTM RNN 内部的情况是这样.
他多了一个控制全局的记忆, 我们用粗线代替. 为了方便理解, 我们把粗线想象成电影或游戏当中的 主线剧情. 而原本的 RNN 体系就是 分线剧情. 三个控制器都是在原始的 RNN 体系上, 我们先看 输入方面 , 如果此时的分线剧情对于剧终结果十分重要, 输入控制就会将这个分线剧情按重要程度 写入主线剧情 进行分析. 再看 忘记方面, 如果此时的分线剧情更改了我们对之前剧情的想法, 那么忘记控制就会将之前的某些主线剧情忘记, 按比例替换成现在的新剧情. 所以 主线剧情的更新就取决于输入 和忘记 控制. 最后的输出方面, 输出控制会基于目前的主线剧情和分线剧情判断要输出的到底是什么.基于这些控制机制, LSTM 就像延缓记忆衰退的良药, 可以带来更好的结果.
更理论的论述如下:
从上图可以看出,RNN和LSTMs的结构大体是相同的,稍微不同的地方是重复模块部分。取而代之RNN的一个神经网络层的是四个。
LSTM的关键点事它具有cell state.
Cell state就像一条输送带。它能直接跑到链条的终端,对信息来说,保持不变的直接从上游传到下游事很容易的事情。但是LSTM有能力将信息删除或者添加进入cell state.
Gate就是一种途径去控制信息的加入或删除。它是由sigmoid神经元组成。因为sigmoid的输出是在0到1之间,所以,它能衡量到底有多少的数据要进入cell state。1就代表让所有的信息进入,0就代表全都不进去。
LSTM有三个这样的Gate.
1. forget gate layer
对于LSTM来说,第一步就是决定什么样的信息我们要从cell state中舍弃。
它是由sigmoid神经元组成。因为sigmoid的输出是在0到1之间,所以,它能衡量到底有多少的数据要从cell state忘记。1就代表让所有的信息记住,0就代表全部忘记。
2. input gate layer
第二步,就要决定什么样的新信息要存在cell state当中。这个由两部分组成,第一部分是由sigmoid层决定什么信息我们要更新,第二部分是由tanh层生成一个新信息的向量,来加入到state当中去。
所以到目前为止,我们将老的状态乘以ft, 也就是forget gate计算得出来多少以前的数据要留下来,然后加上新的多少的数据要记住,即it*Ct,如下图:
3. output gate layer
最后,我们要决定我们要输出什么。这个输出将基于当前的cell state,但是必须是一个过滤的版本。首先,我们用sigmoid层来决定有多少的信息我们将输出,然后,我们将cell state通过tanh层(目的是将值压缩到-1到1之间),最后将sigmoid的输出乘以tanh的结果就是我们最终的输出内容。
总的来说,cell state是一条主线,会一直延续下去,但是output gate的输出只是作为下一层的输入,所以称为分线。
1.2.4 RNN应用:Character-Level Language Models
karpathy.github.io/2015/05/21/rnn-effectiveness/
我们现在将在一个有趣的应用程序:这将训练RNN字符级语言模型。也就是说,我们将给RNN一个巨大的文本块,并要求它模拟下一个字符在给定一系列先前字符的序列中的概率分布。这将允许我们一次生成一个字符的新文本。
作为一个工作实例,假设我们只有四个可能的字母“helo”的词汇,并且希望在训练序列“hello”上训练RNN。该训练序列实际上是4个单独的训练样本的来源:1.“e”的概率应该可能给定为“h”的上下文,2.“l”应该可能在“he”的上下文中,3 。“l”也应该是给定“hel”的上下文,最后4.“o”应该可能给出“hell”的上下文。
具体地,我们将使用1-of-k编码(即,除了在词汇中的字符的索引处的单个字符之外的所有零)将每个字符编码到向量中,并且一次一个地将它们馈送到RNN,使用step功能。然后我们将观察4维输出向量的序列(每个字符一维),我们将其解释为RNN当前分配给序列中下一个字符的每个字符的置信度。如图:
例如,我们看到在第一时间步骤中,当RNN看到字符“h”时,其分配到下一个字母是“h”的置信度为1.0,到字母“e”是2.2,到“l”是-3.0,到“o”是4.1。因为在我们的训练数据(字符串“hello”)下一个正确的字符是“e”,我们想增加其置信度(绿色),降低所有其他字母(红色)的置信度。类似地,我们在4个时间步长中的每一个都有一个期望的目标字符,我们希望网络分配更大的置信度。由于RNN完全由可微分操作组成,我们可以运行反向传播算法(这只是来自微积分的链式规则的递归应用),以找出在什么方向我们应该调整每一个权重以增加正确目标的分数(绿色粗体数字)。然后,我们可以执行参数更新,其在该梯度方向上微调每个重量很小的量。如果我们在参数更新之后向RNN馈送相同的输入,我们将发现正确字符的分数(例如,第一时间步长中的“e”)将稍高(例如2.3而不是2.2),并且分数不正确的字符会稍微降低。然后,我们重复这个过程多次,直到网络收敛,其预测最终与训练数据一致,因为正确的字符总是预测下一步。
在测试时,我们将一个字符馈入RNN,并获得可能接下来的字符的分布。我们从这个分布中采样,并立即喂它以获得下一个字母。重复这个过程。
1.2.5 自编码 Auto Encoder
压缩与解压
有一个神经网络, 它在做的事情是接收一张图片, 然后给它打码, 最后再从打码后的图片中还原. 太抽象啦? 行, 我们再具体点.
假设刚刚那个神经网络是这样, 对应上刚刚的图片, 可以看出图片其实是经过了压缩,再解压的这一道工序. 当压缩的时候, 原有的图片质量被缩减, 解压时用信息量小却包含了所有关键信息的文件恢复出原本的图片. 为什么要这样做呢?
原来有时神经网络要接受大量的输入信息, 比如输入信息是高清图片时, 输入信息量可能达到上千万, 让神经网络直接从上千万个信息源中学习是一件很吃力的工作. 所以, 何不压缩一下, 提取出原图片中的最具代表性的信息, 缩减输入信息量, 再把缩减过后的信息放进神经网络学习. 这样学习起来就简单轻松了. 所以, 自编码就能在这时发挥作用. 通过将原数据白色的X 压缩, 解压 成黑色的X, 然后通过对比黑白 X ,求出预测误差, 进行反向传递, 逐步提升自编码的准确性. 训练好的自编码中间这一部分就是能总结原数据的精髓. 可以看出, 从头到尾, 我们只用到了输入数据 X, 并没有用到 X 对应的数据标签, 所以也可以说自编码是一种非监督学习. 到了真正使用自编码的时候. 通常只会用到自编码前半部分.
编码器 Encoder
这部分也叫作 encoder 编码器. 编码器能得到原数据的精髓, 然后我们只需要再创建一个小的神经网络学习这个精髓的数据,不仅减少了神经网络的负担, 而且同样能达到很好的效果.
这是一个通过自编码整理出来的数据, 他能从原数据中总结出每种类型数据的特征, 如果把这些特征类型都放在一张二维的图片上, 每种类型都已经被很好的用原数据的精髓区分开来. 如果你了解 PCA 主成分分析, 再提取主要特征时, 自编码和它一样,甚至超越了 PCA. 换句话说, 自编码 可以像 PCA 一样给特征属性降维.