机器学习的本质

1 在CNN中,使用BP算法回溯错误,但是错误的定义是人之前给定好的

2 也就是说,只不过是机器以某种方式(CNN,Feature,Pooling,全连通图)获取到一个随机的概率,然后通过某种方法(BP)让这个概率符合我们给定的概率。

3 当足够接近我们的期望后,就说训练成功

4 训练成功意味着我们得到了一个好的卷积核(过滤器),这个过滤器完全是随机生成的,只要概率OK,则过滤器(二维数组)和各个边上的权重具体什么样无所谓。

5 使用这个向前的方法,可以对未知的输入进行预测,并取得不错的输出。

The above steps train the ConvNet – this essentially means that all the weights and parameters of the ConvNet have now been optimized to correctly classify images from the training set.

When a new (unseen) image is input into the ConvNet, the network would go through the forward propagation step and output a probability for each class (for a new image, the output probabilities are calculated using the weights which have been optimized to correctly classify all the previous training examples). If our training set is large enough, the network will (hopefully) generalize well to new images and classify them into correct categories.

卷积和池化

卷积


 

卷积是加权叠加


 

某一时刻的输出是之前很多次输入乘以各自的衰减系数之后的叠加而形成的某一点的输出。然后再把不同时刻的输出点放在一起,形成一个函数,就是卷积。

f(a)就是第a个巴掌,g(x-a)就是第a个巴掌在x的作用强度,乘起来再叠加


 

在图像处理中,用一个模版(卷积核)和一幅待处理图像进行卷积,就是一种积分(求和)运算,用来求两个曲线重叠区域面积,可以看作加权求和,可以进行消除噪声 特征增强。


 

【参考】http://blog.csdn.net/tiandijun/article/details/40080823

https://www.zhihu.com/question/22298352


 


 


 

http://www.cnblogs.com/zf-blog/p/6075286.html

http://blog.csdn.net/silence1214/article/details/11809947


 


 

The Convolution Step

ConvNets derive their name from the “convolution” operator. The primary purpose of Convolution in case of a ConvNet is to extract features from the input image. Convolution preserves the spatial relationship between pixels by learning image features using small squares of input data. We will not go into the mathematical details of Convolution here, but will try to understand how it works over images.

As we discussed above, every image can be considered as a matrix of pixel values. Consider a 5 x 5 image whose pixel values are only 0 and 1 (note that for a grayscale image, pixel values range from 0 to 255, the green matrix below is a special case where pixel values are only 0 and 1):

Also, consider another 3 x 3 matrix as shown below:

Then, the Convolution of the 5 x 5 image and the 3 x 3 matrix can be computed as shown in the animation in Figure 5 below:

Figure 5: The Convolution operation. The output matrix is called Convolved Feature or Feature Map. Source [7]

Take a moment to understand how the computation above is being done. We slide the orange matrix over our original image (green) by 1 pixel (also called ‘stride’) and for every position, we compute element wise multiplication (between the two matrices) and add the multiplication outputs to get the final integer which forms a single element of the output matrix (pink). Note that the 3×3 matrix “sees” only a part of the input image in each stride.

In CNN terminology, the 3×3(orange) matrix is called a ‘filter’ or ‘kernel’(过滤器/卷积核) or ‘feature detector’ and the matrix formed by sliding the filter over the image and computing the dot product is called the ‘Convolved Feature’ or ‘Activation Map’ or the ‘Feature Map‘. It is important to note that filters acts as feature detectors from the original input image.

It is evident from the animation above that different values of the filter matrix will produce different Feature Maps for the same input image. As an example, consider the following input image:

In the table below, we can see the effects of convolution of the above image with different filters. As shown, we can perform operations such as Edge Detection, Sharpen and Blur just by changing the numeric values of our filter matrix before the convolution operation [8] – this means that different filters can detect different features from an image, for example edges, curves etc. More such examples are available in Section 8.2.4 here.

Another good way to understand the Convolution operation is by looking at the animation in Figure 6 below:


 


 

特征图的大小由”深度””步长””补零”三个因素决定

深度是指使用多少个过滤器/卷积核来生成特征图,每个卷积核会产生特定的二维特征图,多个特征图按层排列形成深度。

The size of the Feature Map (Convolved Feature) is controlled by three parameters [4] that we need to decide before the convolution step is performed:

Figure 7


 


 

概述

前面的练习中,解决了一些有关低分辨率图像的问题,比如:小块图像,手写数字小幅图像等。在这部分中,我们将把已知的方法扩展到实际应用中更加常见的大图像数据集。


 

全联通网络

在稀疏自编码章节中,我们介绍了把输入层和隐含层进行”全连接”的设计。从计算的角度来讲,在其他章节中曾经用过的相对较小的图像(如在稀疏自编码的作业中用到过的 8×8 的小块图像,在MNIST数据集中用到过的28×28 的小块图像),从整幅图像中计算特征是可行的。但是,如果是更大的图像(如 96×96 的图像),要通过这种全联通网络的这种方法来学习整幅图像上的特征,从计算角度而言,将变得非常耗时。你需要设计 10 的 4 次方(=10000)个输入单元,假设你要学习 100 个特征,那么就有 10 的 6 次方个参数需要去学习。与 28×28 的小块图像相比较, 96×96 的图像使用前向输送或者后向传导的计算方式,计算过程也会慢 10 的 2 次方(=100)倍。


 

部分联通网络

解决这类问题的一种简单方法是对隐含单元和输入单元间的连接加以限制:每个隐含单元仅仅只能连接输入单元的一部分。例如,每个隐含单元仅仅连接输入图像的一小片相邻区域。(对于不同于图像输入的输入形式,也会有一些特别的连接到单隐含层的输入信号”连接区域”选择方式。如音频作为一种信号输入方式,一个隐含单元所需要连接的输入单元的子集,可能仅仅是一段音频输入所对应的某个时间段上的信号。)


 

网络部分连通的思想,也是受启发于生物学里面的视觉系统结构。视觉皮层的神经元就是局部接受信息的(即这些神经元只响应某些特定区域的刺激)。


 

卷积

自然图像有其固有特性,也就是说,图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。


 

更恰当的解释是,当从一个大尺寸图像中随机选取一小块,比如说 8×8 作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8×8 样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从 8×8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。


 

下面给出一个具体的例子:假设你已经从一个 96×96 的图像中学习到了它的一个 8×8 的样本所具有的特征,假设这是由有 100 个隐含单元的自编码完成的。为了得到卷积特征,需要对 96×96 的图像的每个 8×8 的小块图像区域都进行卷积运算。也就是说,抽取 8×8 的小块区域,并且从起始坐标开始依次标记为(1,1),(1,2),…,一直到(89,89),然后对抽取的区域逐个运行训练过的稀疏自编码来得到特征的激活值。在这个例子里,显然可以得到 100 个集合,每个集合含有 89×89 个卷积特征。


 

假设给定了

的大尺寸图像,将其定义为 xlarge。首先通过从大尺寸图像中抽取的

的小尺寸图像样本 xsmall 训练稀疏自编码,计算 f = σ(W(1)xsmall + b(1))(σ 是一个 sigmoid 型函数)得到了 k 个特征, 其中 W(1)b(1) 是可视层单元和隐含单元之间的权重和偏差值。对于每一个

大小的小图像 xs,计算出对应的值 fs = σ(W(1)xs + b(1)),对这些 fconvolved 值做卷积,就可以得到

个卷积后的特征的矩阵。


 

在接下来的章节里,我们会更进一步描述如何把这些特征汇总到一起以得到一些更利于分类的特征。


 

中英文对照

全联通网络 Full Connected Networks

稀疏编码 Sparse Autoencoder

前向输送 Feedforward

反向传播 Backpropagation

部分联通网络 Locally Connected Networks

连接区域 Contiguous Groups

视觉皮层 Visual Cortex

卷积 Convolution

固有特征 Stationary

池化 Pool


 

池化: 概述

在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96X96 像素的图像,假设我们已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) * (96 − 8 + 1) = 7921 维的卷积特征,由于有 400 个特征,所以每个样例 (example) 都会得到一个 892 * 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,并且容易出现过拟合 (over-fitting)。


 

为了解决这个问题,首先回忆一下,我们之所以决定使用卷积后的特征是因为图像具有一种”静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特定特征的平均值 (或最大值)。这些概要统计特征不仅具有低得多的维度 (相比使用所有提取得到的特征),同时还会改善结果(不容易过拟合)。这种聚合的操作就叫做池化 (pooling),有时也称为平均池化或者最大池化 (取决于计算池化的方法)。


 

最大池化:


 


 


 


 

layer1 edge

layer2 shape

layer3 face


 


 

Max is better

下图显示池化如何应用于一个图像的四块不重合区域。


 

池化的不变性

如果人们选择图像中的连续范围作为池化区域,并且只是池化相同(重复)的隐藏单元产生的特征,那么,这些池化单元就具有平移不变性 (translation invariant)。这就意味着即使图像经历了一个小的平移之后,依然会产生相同的 (池化的) 特征。在很多任务中 (例如物体检测、声音识别),我们都更希望得到具有平移不变性的特征,因为即使图像经过了平移,样例(图像)的标记仍然保持不变。例如,如果你处理一个MNIST数据集的数字,把它向左侧或右侧平移,那么不论最终的位置在哪里,你都会期望你的分类器仍然能够精确地将其分类为相同的数字。

(*MNIST 是一个手写数字库识别库: http://yann.lecun.com/exdb/mnist/)


 

形式化描述

形式上,在获取到我们前面讨论过的卷积特征后,我们要确定池化区域的大小(假定为

),来池化我们的卷积特征。那么,我们把卷积特征划分到数个大小为

的不相交区域上,然后用这些区域的平均(或最大)特征来获取池化后的卷积特征。这些池化后的特征便可以用来做分类。


 

中英文对照

特征 features

样例 example

过拟合 over-fitting

平移不变性 translation invariant

池化 pooling

提取 extract

物体检测 object detection

SIGMOID函数的意义?

神经网络中的SIGMOID函数的意义?


 

神经网络中的激活函数,其作用就是引入非线性。具体的非线性形式,则有多种选择。

sigmoid的优点在于输出范围有限,所以数据在传递的过程中不容易发散。当然也有相应的缺点,就是饱和的时候梯度太小。

sigmoid还有一个优点是输出范围为(0, 1),所以可以用作输出层,输出表示概率。


 


 

一种可能解释是如果对binary RBM的能量函数定义的概率分布求marginal(或者conditional),那么隐变量和显变量的marginal(或者conditional)就是sigmoid形式…

sigmoid在指数函数族(Exponential Family)里面是标准的bernoulli marginal,而exponential family是一个给定数据最大熵的函数族,在线性产生式模型(generative model)里面是属于「最优」的一类。直观理解是熵大的模型比熵小的更健壮(robust),受数据噪声影响小。

不过神经网络如果说最大熵就相当于是硬拉亲戚了。。


 

编辑于 2016-01-21


 

张金超

自然语言处理,机器翻译


 

我觉得可以从无穷级数的角度去理解,指数函数的无穷级数是各种分量的高阶组合。sigmoid中有指数项,且导数形式好,值域也好。


 

发布于 2016-07-24


 

匿名用户


 

因为Sigmoid的函数性质和神经学的神经元的突触一致,而且好求导。


 

发布于 2016-02-09


 

王彩玲

是有联系的,而且在很多的层面上。Sigmoid函数也是高斯分布的和,而高斯又是随机变量的和,世界本源也是随机的,大量的随机似乎有时候显示出一些规律,其实也是中心极限,这也是最大信息熵的来源,基础都是和费马原理。而要证明费马原理,证明费马原理,就需要证明可微可导的问题,那从哲学上,就需要说明人类认识的线性特征,这样就涉及到神经元对世界的反应方式。。。。这样就实现了循环证明,说明是自洽的


 

发布于 2016-10-18


 

高志华

不会写段子的厨子不是一个好的程序员


 

求导容易噻,反向传播多爽

编辑于 2017-04-29


 

Homunculus

装逼与打击装逼者是我上知乎的乐趣


 

哪有那么多玄乎的东西,不过是一个两头平中间陡,值域是0到1,关于0,1/2对称的函数罢了。就一个经验的东西,你选arctanx也一样用


 

发布于 2017-04-04


 

侍世腾

活到老,学到老


 

单向递增,输出在0-1之间


 

发布于 2016-05-04

tensorflow 101

tensorflow的计算被表示为一个有向图(directed graph)

每一个运算操作(operation)将作为一个节点(node),节点与节点之间的连接称为边(edge)

每一个节点可以有任意多个输入和任意多个输出

每一个节点描述了一种运算操作,节点可看作运算操作的实例化(instance)

边中流动(flow)的数据被称为张量(tensor)

数据通信的问题转变为发送节点和接收节点的实现问题


 


 

tensorflow支持单独执行子图,可以选择任意子图,并沿某些边输入数据,同时从另一些边获取输出结果。

tensorflow用节点名加port的形式指定数据:例如bar:0表示名为bar的节点的第1个输出。

Session的Run方法执行子图。

几个概念


 


 

这些都是什么?


 

在本篇文章,我们将介绍一些深度学习中的常见概念,以帮助大家快速了解这个神奇的领域。


 

梯度可视化。图中红色箭头为蓝色函数对应的梯度。


 

梯度? (Nabla)


 

梯度是一个函数的偏导数,以多个向量作为输入,并输出一个单一的数值(即神经网络中的代价函数)。当我们需要使函数输出增加时,梯度能够告诉我们输入变量在图中的应变化的方向。我们在深度学习中应用梯度,并使用梯度的反方向来降低我们算法的损失。


 

后向传播


 

也称为反向传播,是指在网络中正向传播输入数据之后,反向传播误差并根据误差调整网络权重的过程。这种方法在实际应用时使用了微积分中的链式法则。


 

Sigmoid σ


 

用于将网络权重映射至[0, 1]区间的激活函数。该函数在图中的曲线类似一个字母’S’,函数因此得名,在希腊语中sigma表示字母S。该函数也被称为logistic函数。


 

Geoffrey Hinton定义的ReLU计算公式


 

校正线性单元或ReLU


 

sigmoid函数的值域限制在[0, 1]区间内,而ReLU的值域为0到正无穷。这意味着,sigmoid更适合logistic回归,而ReLU能够更好地表示正数输出。ReLU不会产生梯度消失问题。


 

Tanh函数


 

Tanh


 

Tanh函数是一个可将你的网络权重初始化为[-1, 1]区间内实数的函数。假设你的数据已经规范化,那么我们会得到一个更大的梯度:因为数据以0为中心分布,函数的导数更高。为了验证这点,我们计算tanh函数的导数,并观察函数在[0, 1]区间内的输入。tanh函数的值域为[-1, 1]区间,而sigmoid函数的值域为[0, 1]区间。这也避免了在梯度中的偏差。


 

LSTM/GRU


 

通常应用于递归神经网络,也可扩展至其他场景使用,其充当小型”记忆单元”,能够保持输入数据间的状态,用于模型训练,同时,也可解决梯度消失问题,梯度消失问题会导致递归神经网络在进行大约7次迭代后失去先前输入数据的上下文。


 


 

阅读全文请点击:http://click.aliyun.com/m/9025/


 

理解LSTM

Recurrent Neural Networks

人类并不是每时每刻都从一片空白的大脑开始他们的思考。在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。

传统的神经网络并不能做到这点,看起来也像是一种巨大的弊端。例如,假设你希望对电影中的每个时间点的时间类型进行分类。传统的神经网络应该很难来处理这个问题——使用电影中先前的事件推断后续的事件。

RNN 解决了这个问题。RNN 是包含循环的网络,允许信息的持久化。


 

RNN 包含循环

在上面的示例图中,神经网络的模块,A,正在读取某个输入 x_i,并输出一个值 h_i。循环可以使得信息可以从当前步传递到下一步。

这些循环使得 RNN 看起来非常神秘。然而,如果你仔细想想,这样也不比一个正常的神经网络难于理解。RNN 可以被看做是同一神经网络的多次复制,每个神经网络模块会把消息传递给下一个。所以,如果我们将这个循环展开:


 

展开的 RNN


 

链式的特征揭示了 RNN 本质上是与序列和列表相关的。他们是对于这类数据的最自然的神经网络架构。

并且 RNN 也已经被人们应用了!在过去几年中,应用 RNN 在语音识别,语言建模,翻译,图片描述等问题上已经取得一定成功,并且这个列表还在增长。我建议大家参考 Andrej Karpathy 的博客文章——The Unreasonable Effectiveness of Recurrent Neural Networks 来看看更丰富有趣的 RNN 的成功应用。

而这些成功应用的关键之处就是 LSTM 的使用,这是一种特别的 RNN,比标准的 RNN 在很多的任务上都表现得更好。几乎所有的令人振奋的关于 RNN 的结果都是通过 LSTM 达到的。这篇博文也会就 LSTM 进行展开。

长期依赖(Long-Term Dependencies)问题

RNN 的关键点之一就是他们可以用来连接先前的信息到当前的任务上,例如使用过去的视频段来推测对当前段的理解。如果 RNN 可以做到这个,他们就变得非常有用。但是真的可以么?答案是,还有很多依赖因素。

有时候,我们仅仅需要知道先前的信息来执行当前的任务。例如,我们有一个语言模型用来基于先前的词来预测下一个词。如果我们试着预测 “the clouds are in the sky” 最后的词,我们并不需要任何其他的上下文 —— 因此下一个词很显然就应该是 sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN 可以学会使用先前的信息。


 

不太长的相关信息和位置间隔

但是同样会有一些更加复杂的场景。假设我们试着去预测”I grew up in France… I speak fluent French”最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France 的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。

不幸的是,在这个间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。


 

相当长的相关信息和位置间隔

在理论上,RNN 绝对可以处理这样的 长期依赖 问题。人们可以仔细挑选参数来解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。Bengio, et al. (1994)等人对该问题进行了深入的研究,他们发现一些使训练 RNN 变得非常困难的相当根本的原因。

然而,幸运的是,LSTM 并没有这个问题!

LSTM 网络

Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息。LSTM 由Hochreiter & Schmidhuber (1997)提出,并在近期被Alex Graves进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。

LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!

所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层。


 

标准 RNN 中的重复模块包含单一的层


 

LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于 单一神经网络层,这里是有四个,以一种非常特殊的方式进行交互。


 

LSTM 中的重复模块包含四个交互的层


 

不必担心这里的细节。我们会一步一步地剖析 LSTM 解析图。现在,我们先来熟悉一下图中使用的各种元素的图标。


 

LSTM 中的图标


 

在上面的图例中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。粉色的圈代表 pointwise 的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。

LSTM 的核心思想

LSTM 的关键就是细胞状态,水平线在图上方贯穿运行。

细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。


 

Paste_Image.png

LSTM 有通过精心设计的称作为”门”的结构来去除或者增加信息到细胞状态的能力。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个 pointwise 乘法操作。


 

Paste_Image.png


 

Sigmoid 层输出 0 到 1 之间的数值,描述每个部分有多少量可以通过。0 代表”不许任何量通过”,1 就指”允许任意量通过”!

LSTM 拥有三个门,来保护和控制细胞状态。

逐步理解 LSTM

在我们 LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。这个决定通过一个称为忘记门层完成。该门会读取 h_{t-1} 和 x_t,输出一个在 0 到 1 之间的数值给每个在细胞状态 C_{t-1} 中的数字。1 表示”完全保留”,0 表示”完全舍弃”。

让我们回到语言模型的例子中来基于已经看到的预测下一个词。在这个问题中,细胞状态可能包含当前主语的性别,因此正确的代词可以被选择出来。当我们看到新的主语,我们希望忘记旧的主语


 

决定丢弃信息


 

下一步是确定什么样的新信息被存放在细胞状态中。这里包含两个部分。第一,sigmoid 层称 “输入门层” 决定什么值我们将要更新。然后,一个 tanh 层创建一个新的候选值向量,\tilde{C}_t,会被加入到状态中。下一步,我们会讲这两个信息来产生对状态的更新。

在我们语言模型的例子中,我们希望增加新的主语的性别到细胞状态中,来替代旧的需要忘记的主语。


 

确定更新的信息

现在是更新旧细胞状态的时间了,C_{t-1} 更新为 C_t。前面的步骤已经决定了将会做什么,我们现在就是实际去完成。

我们把旧状态与 f_t 相乘,丢弃掉我们确定需要丢弃的信息。接着加上 i_t * \tilde{C}_t。这就是新的候选值,根据我们决定更新每个状态的程度进行变化。

在语言模型的例子中,这就是我们实际根据前面确定的目标,丢弃旧代词的性别信息并添加新的信息的地方。


 

更新细胞状态

最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。首先,我们运行一个 sigmoid 层来确定细胞状态的哪个部分将输出出去。接着,我们把细胞状态通过 tanh 进行处理(得到一个在 -1 到 1 之间的值)并将它和 sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。

在语言模型的例子中,因为他就看到了一个 代词,可能需要输出与一个 动词 相关的信息。例如,可能输出是否代词是单数还是负数,这样如果是动词的话,我们也知道动词需要进行的词形变化。


 

输出信息

LSTM 的变体

我们到目前为止都还在介绍正常的 LSTM。但是不是所有的 LSTM 都长成一个样子的。实际上,几乎所有包含 LSTM 的论文都采用了微小的变体。差异非常小,但是也值得拿出来讲一下。

其中一个流形的 LSTM 变体,就是由 Gers & Schmidhuber (2000) 提出的,增加了 “peephole connection”。是说,我们让 门层 也会接受细胞状态的输入。


 

peephole 连接

上面的图例中,我们增加了 peephole 到每个门上,但是许多论文会加入部分的 peephole 而非所有都加。

另一个变体是通过使用 coupled 忘记和输入门。不同于之前是分开确定什么忘记和需要添加什么新的信息,这里是一同做出决定。我们仅仅会当我们将要输入在当前位置时忘记。我们仅仅输入新的值到那些我们已经忘记旧的信息的那些状态 。


 

coupled 忘记门和输入门


 

另一个改动较大的变体是 Gated Recurrent Unit (GRU),这是由 Cho, et al. (2014) 提出。它将忘记门和输入门合成了一个单一的 更新门。同样还混合了细胞状态和隐藏状态,和其他一些改动。最终的模型比标准的 LSTM 模型要简单,也是非常流行的变体。


 

GRU


 

这里只是部分流行的 LSTM 变体。当然还有很多其他的,如Yao, et al. (2015) 提出的 Depth Gated RNN。还有用一些完全不同的观点来解决长期依赖的问题,如Koutnik, et al. (2014) 提出的 Clockwork RNN。

要问哪个变体是最好的?其中的差异性真的重要吗?Greff, et al. (2015) 给出了流行变体的比较,结论是他们基本上是一样的。Jozefowicz, et al. (2015) 则在超过 1 万种 RNN 架构上进行了测试,发现一些架构在某些任务上也取得了比 LSTM 更好的结果。


 

Jozefowicz等人论文截图

结论

刚开始,我提到通过 RNN 得到重要的结果。本质上所有这些都可以使用 LSTM 完成。对于大多数任务确实展示了更好的性能!

由于 LSTM 一般是通过一系列的方程表示的,使得 LSTM 有一点令人费解。然而本文中一步一步地解释让这种困惑消除了不少。

LSTM 是我们在 RNN 中获得的重要成功。很自然地,我们也会考虑:哪里会有更加重大的突破呢?在研究人员间普遍的观点是:”Yes! 下一步已经有了——那就是注意力!” 这个想法是让 RNN 的每一步都从更加大的信息集中挑选信息。例如,如果你使用 RNN 来产生一个图片的描述,可能会选择图片的一个部分,根据这部分信息来产生输出的词。实际上,Xu, et al.(2015)已经这么做了——如果你希望深入探索注意力可能这就是一个有趣的起点!还有一些使用注意力的相当振奋人心的研究成果,看起来有更多的东西亟待探索……

注意力也不是 RNN 研究领域中唯一的发展方向。例如,Kalchbrenner, et al. (2015) 提出的 Grid LSTM 看起来也是很有前途。使用生成模型的 RNN,诸如Gregor, et al. (2015) Chung, et al. (2015) 和 Bayer & Osendorfer (2015) 提出的模型同样很有趣。在过去几年中,RNN 的研究已经相当的燃,而研究成果当然也会更加丰富!

致谢

I’m grateful to a number of people for helping me better understand LSTMs, commenting on the visualizations, and providing feedback on this post.

I’m very grateful to my colleagues at Google for their helpful feedback, especially Oriol Vinyals,Greg CorradoJon ShlensLuke Vilnis, and Ilya Sutskever. I’m also thankful to many other friends and colleagues for taking the time to help me, including Dario Amodei, and Jacob Steinhardt. I’m especially thankful to Kyunghyun Cho for extremely thoughtful correspondence about my diagrams.

Before this post, I practiced explaining LSTMs during two seminar series I taught on neural networks. Thanks to everyone who participated in those for their patience with me, and for their feedback.

keras模块介绍

http://www.2cto.com/kf/201610/559189.html

keras的模块介绍


 


 

keras是一个开源是的python深度学习库,可以基于theano或者tenserflow,下面大体介绍下keras的几个重要模块。


 

重要的模块


 

1、优化器(optimizers)


 

优化器是调整每个节点权重的方法,看一个代码示例:


 

?


 

1

2

3

4

model = Sequential()

model.add(Dense(64, init=’uniform’, input_dim=10)) model.add(Activation(‘tanh’))

model.add(Activation(‘softmax’))

sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) model.compile(loss=’mean_squared_error’, optimizer=sgd)

可以看到优化器在模型编译前定义,作为编译时的两个参数之一


 

代码中的sgd是随机梯度下降算法


 

lr表示学习速率


 

momentum表示动量项


 

decay是学习速率的衰减系数(每个epoch衰减一次)


 

Nesterov的值是False或者True,表示使不使用Nesterov momentum


 

以上4个参数以后具体学习了再解析


 

除了sgd,还可以选择的优化器有RMSprop(适合递归神经网络)、Adagrad、Adadelta、Adam、Adamax、Nadam


 

2、目标函数(objectives)


 

目标函数又称损失函数(loss),目的是计算神经网络的输出样本标记的差的一种方法,代码示例:


 


 


 

1

2

3

4

model = Sequential()

model.add(Dense(64, init=’uniform’, input_dim=10)) model.add(Activation(‘tanh’))

model.add(Activation(‘softmax’))

sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) model.compile(loss=’mean_squared_error’, optimizer=sgd)

mean_squared_error就是损失函数的名称


 

可以选择的损失函数有:


 

mean_squared_error,mean_absolute_error,squared_hinge,hinge,binary_crossentropy,categorical_crossentropy


 

这里binary_crossentropy 和 categorical_crossentropy也就是logloss


 

3、激活函数(activations)


 

每一个神经网络层都需要一个激活函数,代码示例:


 


 

1

2

3

4

5

6

7

8

from keras.layers.core importActivation, Dense

model.add(Dense(64))

model.add(Activation(‘tanh’))

或把上面两行合并为:

model.add(Dense(64, activation=’tanh’))

可以选择的激活函数有:


 

linear、sigmoid、hard_sigmoid、tanh、softplus、relu、 softplus,softmax、softsign


 

还有一些高级激活函数,比如如PReLU,LeakyReLU等


 

4、参数初始化(Initializations)


 

这个模块的作用是在添加layer时调用init进行这一层的权重初始化,有两种初始化方法


 

4.1 通过制定初始化方法的名称:


 

示例代码:


 


 

1

model.add(Dense(64, init=’uniform’))

可以选择的初始化方法有:


 

uniform、lecun_uniform、normal、orthogonal、zero、glorot_normal、he_normal等


 

4.2 通过调用对象:


 

该对象必须包含两个参数:shape(待初始化的变量的shape)和name(该变量的名字),该可调用对象必须返回一个(Keras)变量,例如K.variable()返回的就是这种变量,示例代码:


 


 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

from keras importbackend as K

importnumpy as np

def my_init(shape, name=None):

value = np.random.random(shape)

returnK.variable(value, name=name)

model.add(Dense(64, init=my_init))

或者

from keras importinitializations

def my_init(shape, name=None):

returninitializations.normal(shape, scale=0.01, name=name)

model.add(Dense(64, init=my_init))

所以说可以通过库中的方法设定每一层的初始化权重,


 

也可以自己初始化权重,自己设定的话可以精确到每个节点的权重,


 

那么是否可以在这儿做文章优化特征呢?我觉得可以针对不同的task深入试验看看


 

5、层(layer)


 

keras的层主要包括:


 

常用层(Core)、卷积层(Convolutional)、池化层(Pooling)、局部连接层、递归层(Recurrent)、嵌入层( Embedding)、高级激活层、规范层、噪声层、包装层,当然也可以编写自己的层


 

5.1对于层的操作


 


 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

layer.get_weights() #返回该层的权重

layer.set_weights(weights)#将权重加载到该层

config = layer.get_config()#保存该层的配置

layer = layer_from_config(config)#加载一个配置到该层

#该层有一个节点时,获得输入张量、输出张量、及各自的形状:

layer.input

layer.output

layer.input_shape

layer.output_shape

#该层有多个节点时(node_index为节点序号):

layer.get_input_at(node_index)

layer.get_output_at(node_index)

layer.get_input_shape_at(node_index)

layer.get_output_shape_at(node_index)

5.2 Dense层(全连接层)


 


 

1

keras.layers.core.Dense(output_dim, init=’glorot_uniform’, activation=’linear’, weights=None, W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None, bias=True, input_dim=None)

output_dim:输出数据的维度


 

init:初始化该层权重的方法


 

activation:该层的激活函数


 

weights:numpy array的list。该list应含有一个形如(input_dim,output_dim)的权重矩阵和一个形如(output_dim,)的偏置向量


 

regularizer:正则项,w为权重的、b为偏执的,activity为输出的


 

constraints:约束项


 

bias:是否包含偏执向量,是布尔值


 

input_dim:输入数据的维度


 

5.3 dropout层


 

keras.layers.core.Dropout(p)


 

为输入数据施加Dropout。Dropout将在训练过程中每次更新参数时随机断开一定百分比(p)的输入神经元连接,Dropout层用于防止过拟合。


 

参考文章:http://blog.csdn.net/stdcoutzyx/article/details/49022443理解dropout


 

5.4 递归层(Recurrent)


 

递归层包含三种模型:LSTM、GRU和SimpleRNN


 

5.4.1抽象层,不能直接使用


 


 

1

keras.layers.recurrent.Recurrent(weights=None, return_sequences=False, go_backwards=False, stateful=False, unroll=False, consume_less=’cpu’, input_dim=None, input_length=None)

return_sequences:True返回整个序列,false返回输出序列的最后一个输出


 

go_backwards:True,逆向处理输入序列,默认为False


 

stateful:布尔值,默认为False,若为True,则一个batch中下标为i的样本的最终状态将会用作下一个batch同样下标的样本的初始状态


 

5.4.2全连接RNN网络


 


 

1

keras.layers.recurrent.SimpleRNN(output_dim, init=’glorot_uniform’, inner_init=’orthogonal’, activation=’tanh’, W_regularizer=None, U_regularizer=None, b_regularizer=None, dropout_W=0.0, dropout_U=0.0)

inner_init:内部单元的初始化方法


 

dropout_W:0~1之间的浮点数,控制输入单元到输入门的连接断开比例


 

dropout_U:0~1之间的浮点数,控制输入单元到递归连接的断开比例


 

5.4.3 LSTM层


 


 

1

keras.layers.recurrent.LSTM(output_dim, init=’glorot_uniform’, inner_init=’orthogonal’, forget_bias_init=’one’, activation=’tanh’, inner_activation=’hard_sigmoid’, W_regularizer=None, U_regularizer=None, b_regularizer=None, dropout_W=0.0, dropout_U=0.0)

forget_bias_init:遗忘门偏置的初始化函数,Jozefowicz et al.建议初始化为全1元素


 

inner_activation:内部单元激活函数


 

5.5 Embedding层


 


 

1

keras.layers.embeddings.Embedding(input_dim, output_dim, init=’uniform’, input_length=None, W_regularizer=None, activity_regularizer=None, W_constraint=None, mask_zero=False, weights=None, dropout=0.0)

只能作为模型第一层


 

mask_zero:布尔值,确定是否将输入中的’0’看作是应该被忽略的’填充’(padding)值,该参数在使用递归层处理变长输入时有用。设置为True的话,模型中后续的层必须都支持masking,否则会抛出异常


 

5.6 model层(最重要)


 

model层是最主要的模块,model层可以将上面定义了各种基本组件组合起来


 

model的方法:


 

model.summary() : 打印出模型概况


 

model.get_config() :返回包含模型配置信息的Python字典


 

model.get_weights():返回模型权重张量的列表,类型为numpy array


 

model.set_weights():从numpy array里将权重载入给模型


 

model.to_json:返回代表模型的JSON字符串,仅包含网络结构,不包含权值。可以从JSON字符串中重构原模型:


 


 

1

2

3

4

from models importmodel_from_json

json_string = model.to_json()

model = model_from_json(json_string)

model.to_yaml:与model.to_json类似,同样可以从产生的YAML字符串中重构模型


 


 

1

2

3

4

from models importmodel_from_yaml

yaml_string = model.to_yaml()

model = model_from_yaml(yaml_string)

model.save_weights(filepath):将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)


 

model.load_weights(filepath, by_name=False):从HDF5文件中加载权重到当前模型中, 默认情况下模型的结构将保持不变。如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重


 

keras有两种model,分别是Sequential模型和泛型模型


 

5.6.1 Sequential模型


 

Sequential是多个网络层的线性堆叠


 

可以通过向Sequential模型传递一个layer的list来构造该模型:


 


 

1

2

3

4

5

6

7

8

9

from keras.models importSequential

from keras.layers importDense, Activation

model = Sequential([

Dense(32, input_dim=784),

Activation(‘relu’),

Dense(10),

Activation(‘softmax’),

])

也可以通过.add()方法一个个的将layer加入模型中:


 


 

1

2

3

model = Sequential()

model.add(Dense(32, input_dim=784))

model.add(Activation(‘relu’))

还可以通过merge将两个Sequential模型通过某种方式合并


 

Sequential模型的方法:


 


 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

compile(self, optimizer, loss, metrics=[], sample_weight_mode=None)

fit(self, x, y, batch_size=32, nb_epoch=10, verbose=1, callbacks=[], validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None)

evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)

#按batch获得输入数据对应的输出,函数的返回值是预测值的numpy array

predict(self, x, batch_size=32, verbose=0)

#按batch产生输入数据的类别预测结果,函数的返回值是类别预测结果的numpy array或numpy

predict_classes(self, x, batch_size=32, verbose=1)

#本函数按batch产生输入数据属于各个类别的概率,函数的返回值是类别概率的numpy array

predict_proba(self, x, batch_size=32, verbose=1)

train_on_batch(self, x, y, class_weight=None, sample_weight=None)

test_on_batch(self, x, y, sample_weight=None)

predict_on_batch(self, x)

fit_generator(self, generator, samples_per_epoch, nb_epoch, verbose=1, callbacks=[], validation_data=None, nb_val_samples=None, class_weight=None, max_q_size=10)

evaluate_generator(self, generator, val_samples, max_q_size=10)

5.6.2 泛型模型


 

Keras泛型模型接口是:


 

用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径


 

适用于实现:全连接网络和多输入多输出模型


 

多输入多输出,官方例子给出:预测一条新闻的点赞转发数,主要输入是新闻本身,还可以加入额外输入,比如新闻发布日期,新闻作者等,具体的实现还是看官网文档吧:


 

http://keras-cn.readthedocs.io/en/latest/getting_started/functional_API/


 

所以感觉这个模型可以针对特定task搞一些创新哦


 

泛型模型model的属性:


 

model.layers:组成模型图的各个层


 

model.inputs:模型的输入张量列表


 

model.outputs:模型的输出张量列表


 

方法:类似序列模型的方法


 

补充get_layer


 

get_layer(self, name=None, index=None)


 

本函数依据模型中层的下标或名字获得层对象,泛型模型中层的下标依据自底向上,水平遍历的顺序。


 

name:字符串,层的名字


 

index: 整数,层的下标


 

函数的返回值是层对象