深度学习概览

2017-09-01 fishedee 数学

1 概述

深度学习概览

2 神经网络

2.1 结构

神经网络是这样的一个结构,输入层有多个输入神经元,然后将输入沿着边传播到隐含层中,每条边有附属的权值,隐含层神经元有自己的偏置。那么在某个隐含层的神经元中,该神经元的输出为输入神经元的加权乘积和与隐含层偏置的总和。然后隐含层的神经元输出到输出层中,以此类推,输出层的输出依然为隐含层神经元的的加权乘积和与输出层偏置的总和。

在一个特定的神经网络中,可以有多个隐含层。而且,由于每个神经元的权值和偏置不一定一样,所以对于不一样的输入数据,这些神经元的输出都不太一样。对于较多隐藏层的神经网络我们称为深度神经网络。

Screen Shot 2017-08-24 at 10.23.54 P

网络结构也可以分为两种,监督型和非监督型的,非监督型的从最开始的RBM和AE演化到DBN和SAE,监督型的从最开始的单个感知机,演化到多层感知机(MLP,CNN,RNN,RNTN)。而其他的稀疏自编码,ResNet,InceptionNet等等都是这些网络上的一些优化性改进而已。

2.2 步骤

显然,对于神经网络而言,最重要的是能恰当配置好隐藏层和输出层神经元的权值和偏置。幸好的是,这个配置是由机器来做,而不是人类。使用神经网络的步骤一般为:

  • 建立模型,按照业务场景建立网络结构,多少个输入神经元和输出神经元,多少层隐含层,层与层之间是全连接,还是部分连接等等。
  • 训练模型,对于已经标记好的大量数据,将它们扔到神经网络中,神经网络通过预测输出与实际输出的差值来自动调整隐藏层和输出层神经元权值和偏置。
  • 数据预测,对于新的数据,将他们直接扔到输入层,得到的输出就是预测输出。

2.3 应用

机器学习的主要用途为分类,聚类,回归,关联规则等等。现有的机器学习方法有SVM,logistic回归,决策树,随机森林等方法。但是,在需要高精度,难以提取特征的无结构化数据机器学习中,深度学习几乎是唯一的选择。

但是深度学习也有它的问题,它对训练数据很敏感,它的训练目标也是最小化训练数据的训练误差,所以容易受到噪音和过拟合的影响。因此,在一些高噪音的环境下,深度学习是失效的。例如,短期日内股票交易中,股票的波动可能是完全随机性的,上涨可能跟之前的股票走向有关,还可能跟随机性因素有关。所以,通过之前走向和未来走向扔进神经网络后,神经网络无法识别出哪些是因为随机性因素影响,哪些是真正可以使用的走向。高噪音让它无法收敛,或者只是收敛到一个过拟合的网络中。

3 判别模型

3.1 反向传播网络(BP)

使用梯度下降算法不断调整权重与偏置,从输出层的权重与偏置开始调整起,然后是隐藏层,最后是输入层

最大的问题是梯度消失,梯度在不断往后调整的过程中会越来越小,到输入层时几乎为0。导致梯度消失,输入层附近没有有效地调整权重与偏置。

3.2 限制波尔兹曼机(RBM)

限制波尔兹曼机的解决办法是,先从前面的层开始训练起,直至后面的层。

首先,建立一个三层网络,输入层,隐藏层1,和输出层。将输出层的结果调整为输入层一样的数据,然后训练隐藏层和输出层的权重与偏置。与此同时,要求隐藏层和输出层的权重与偏置尽可能一样。最后,丢弃输出层的权重与偏置,得到隐藏层1的权重与偏置。

这样做的原因是,将隐藏层1看成是特征提取机,输入层到隐藏层1的权重与偏置看成是提取特征,隐藏层1到虚拟输出层的的权重与偏置看成是特征复原。显然这两层的权重与偏置应该是要一样呀。通过这样的方法,我们可以将RBM看成是原始数据的特征提取机。而且,RBM的虚拟输出层是固定为输入数据,完全不需要数据人工标注,这是一个非常好的无监督学习方法。

最后,将隐藏层的输出作为BP的输入数据来训练,能得到更好的训练效果。毕竟提取数据特征来训练要简单得多。

3.3 深度信念网络(DBN)

既然我们可以用RBM来无监督提取一层原始数据的特征,为什么不在隐藏层的后面再加多一个RBM呢,也就是说,将RBM层叠就成为了传说中的深度信念网络DBN了。

一个典型的DBN就是输入数据后面层叠多个RBM,每个RBM单独训练,然后在最后一层的RBM后面加上一个传统的分类器就可以了,例如是BP,SVM等等。

3.4 自动编码机(AE)

和RBM一样,也是个自动特征提取器,甚至他们训练的结构都是一样的。唯一的区别是,RBM的优化模型是一个极大似然优化,AE是个最小损失函数优化。所以,RBM输出的是概率型结果,AE是个确定型结果。总体来说,AE限制更少,更优秀一点。

另外,对于同一个数据而言,同一个AE由于训练方式的不同可能会构造出完全不同的特征提取器。那么,如何去选择和度量更好的特征提取器了,答案就是稀疏自编码器,降噪自编码器和正则自编码器。

稀疏自编码器认为高维而稀疏的网络表达是最好的,然后我们指定一个稀疏性参数ρ,代表隐藏神经元的平均活跃程度(在训练集上取平均)。比如,当ρ=0.05时,可以认为隐层节点在95%的时间里都是被一直的,只有5%的机会被激活。那么,我们在损失函数中加入惩罚项,如果每次激活的隐含节点越多,惩罚项越大。

降噪自编码器认为一个能够从中恢复出原始信号的表达未必是最好的,能够对“被污染/破坏”的原始数据编码、解码,然后还能恢复真正的原始数据,这样的特征才是好的。那么,我们在训练时会随机加入一些数据噪音,而能够适应这样噪音的特征器才会被选取。

正则自编码器认为权值和偏置的数值越小,特征提取就越好。那么,我们在损失函数中加入惩罚项,如果节点的权值和偏置的数值越大,惩罚项就越大。

3.5 层叠自动编码机(SAE)

与层叠RBM就成为了DBN一样,我们一样可以层叠AE成为SAE,这就成为了一个深度的特征提取器。由于AE比RBM更优秀的缘故,一般SAE的效果都比DBN更加优秀。而这两个都是一样的无监督特征学习器,也就是个预训练器。

3.6 卷积神经网络(CNN)

卷积神经网络是从另外一个角度来解决BP的梯度消失的问题,那就是减少连接,和减少需要训练的权值和偏置的数量。

之前使用RBM提取特征时使用的是隐藏层全连接输入层的,可是提取图像特征时根本就不需要这么多,只需要提取这个点周边的8个点做加权和就可以了,这个加权和就是传说中的卷积。而且,这样的特征提取方式同一个特征应该是共用权值和偏置的。例如,我们opencv做边缘时,常用的卷积核就是

\[ \begin{bmatrix} -1 & 0 \\ 0 & 1\\ \end{bmatrix} \]

然后用这个卷积核对所有像素点都遍历一遍就可以了。同样的,我们在CNN时,提取同一种特征的神经元它们就是共享同一堆权值和偏置就可以了,唯一的区别就是它们映射的位置不一样而已。

当然仅仅只有一种特征是不够的,我们要多钟,所以我们建立了多个特征提取,同一个特征提取中所有神经元都是共享权值和偏置的。同一个特征提取中所有神经元被称为一个特征图。

Screen Shot 2017-08-23 at 12.38.53 A

就这样,我们得到了cnn的卷积层。一副32x32的图像能提取出8个特征图。

再然后,因为单个特征图的神经元数量还是太多了,我们做一个子抽样,将单个特征图邻近的神经元取最大值或平均值来取一个单独输出,就能大幅减少数量。

Screen Shot 2017-08-23 at 12.41.00 A

就这样,我们得到了子抽样层,也被称为池化层。卷积层和池化层两个合起来就是单次的特征提取过程。

Screen Shot 2017-08-23 at 12.41.49 A

跟DBN的一样,我们不断层叠卷积层和池化层,然后中途插入几个全连接层,就得到了一个卷积神经网络cnn了。由于卷积层减少了连接数量,而且单个特征图中共享共享权值和偏置,所以整个神经网络需要训练的权值和偏置其实很少,直接用bp的全局梯度下降训练就完事了。CNN的效果非常屌,成为一个真正的深度学习网络,大幅提高了ImageNet的识别率。

3.7 网络中网络(NIN)

Network In Network(NIN)结构是对CNN的一个重大优化,传统的CNN在卷积层后面直接加上池化层,没有对卷积的信息进行有效的非线性分析。所以,NIN的一个优化就是在卷积层后面加入了局部的全连接层,也就是MLPconv层。用代码来表示就是1x1的卷积核,相当amazing。

然后,在CNN最后的全连接层被更换为全局池化层(Global Average Pooling),避免过拟合,这样得出的网络所需的参数更少,收敛更快,泛化效果更好。

3.8 递归神经网络(RNN)

如果我们要处理一个问题,预测一个句子的分类,判断这个句子的主题是属于文学类,经济类还是科学类的。很显然,我们可以直接将多个word(每个word是一个向量)作为输入变量扔进神经网络中训练。最简单的,就是这个网络是一个全连接网络,可用,但是训练慢。进一步考虑的,我们可以用cnn的权重共享的想法,用一层神经元他们的权值与偏置都是相同的,然后这一层的神经元每个神经元映射到一个word上。

但是,我们还忽略了一个重要的问题,第2个word的词性不仅和这个word有关,还和这个word之前的word有关。例如“漂亮”在一般句子是个正面的词汇,但是“漂亮”前面的word如果是个”不”字,那么整个整体的词汇就是负面的。也就是说,映射到这个word的神经元的输入不仅是这个word,还需要之前的word的神经元的输出。

所以,即使我们用cnn的权重共享的思路,也不能很好地解决文本分析的问题。我们需要再进一步,将第一个word的输出连接到第二个word的输入中,将第二个word的输出连接到第三个word的输入中。以此类推,直至到最后一个word的输出取出来放到分类器中训练。那么,在前馈执行网络中,这个新的网络不能像cnn一样所有权重共享的神经元都能并发计算,它需要先执行第一个word的神经元h1计算,然后将第二个word和神经元h1的输出放入到神经元h2中计算,然后将第三个word和神经元h2的输出放入到神经元h3中计算,也就是只能串行计算。

更可怕的是,这只是只有一个特征图时的计算,当需要对这些word提取多个特征时,假设有(h,m,n)三个特征,第一个特征第一个神经元h1的输入就只有第一个word,第二个特征第一个神经元m1的输入就只有第一个word,第三个特征第一个神经元n1的输入就只有第一个word,那么,第一个特征第一个神经元h2的输入就不仅第二个word,还有h1,m1,n1的输出,第二个特征第二个神经元m2的输入就不仅第二个word,还有h1,m1,n1的输出,以此类推。也就是说,不同特征层的神经元还需要相互连接。就这样,不断错综复杂的同层互联的神经网络称为递归神经网络。它在cnn的权重共享的基础上,加入了同层互联和串行计算的特点。它很好地解决了这次的数据特征是不断依赖之前数据特征的问题。

Screen Shot 2017-08-24 at 9.51.18 P

但是,以上的神经网络有一个重要的缺陷,因为它是从cnn演化过来的,cnn的输入数量是固定的,也就是所有样本的输入数据都是定长的。但实际场景中文本分析的输入数据都是不定长的。解决办法很简单,由于之前的网络是串行计算的,计算完第一个word的输出后就传递给第二个word的神经元,而每个word的神经元都是权值共享的。那么,我们为什么只保留最后一个word的神经元就可以了,而前一个word的神经元输出我们持久化到另外一个位置就可以了。换句话说,我们的输入数据不是一个句子,而是一个word,然后不断将输入的word迭代到同一个神经元中,同一个神经元每次都是将上次本神经元的输出和新word作为输入。也就是将摊开的神经网络叠在了一起。那么,当这个句子结束了以后,我们清除这个网络的持久化记忆,下一个新句子开始时就不会接受上一个句子的神经元输出了。就这样,我们不仅保留了原来神经网络的功能,还实现了变长句子的输入问题。

就这样,我们从句子级别的神经网络转换到了单词级别的神经网络,由于转换后,同一层的神经网络相互交叉互联,所以这样的神经网络成为循环神经网络(rnn)。它的特点是,数据迭代输入(不是并在一起一次输入),同层循环连接和持久化。

有时候,我们需要像层叠AE成为SAE一样,我们也希望层叠RNN来实现更深维度的RNN特征提取。如果用原始的办法,每个句子输入后就只有一个独立特征数值(也就是N对1结构),无法再使用rnn了。解决办法就是我们将每一步神经元h1,h2的输出不仅传递到下一个神经元中,还将他们输出来,作为下一层RNN的输入(也就是N对N结构)。

最后还有一个优化,以上的循环神经网络中下一个word的输入是上一个word神经元的输出,也就是默认句子是右边word依赖左边word的,那有没有识别场景是需要左边word依赖右边word,或者这个word的输出是需要两边的依赖呢?这样的变动成为反向rnn,和双向rnn。

换个角度来看rnn,相当于rnn有了神经元的持久化功能,通过记忆上一次的输出值,然后作为这次的输入值来参与到神经元训练中。

由于rnn的出现,彻底改变了需要上下文分析的机器学习问题,是语音识别和文字识别的突破性进展。

3.9 长短期记忆网络(LSTM)

在大规模使用rnn后,大家发现了一个新的问题,rnn无法解决长期依赖的问题,也就是h3的输出不仅需要x3,也需要x0和x1。由于h3往前依赖2个位置的输出就可以了,所以rnn可以很容易识别出来。

但是当h_t需要的x0和x1时很遥远时,rnn的训练就很难长远地提前记忆这些输出,然后等到h_t时才拿出来加入预测。

解决这个问题的关键就是加入门电路,门电路不仅将上次的输出放入这次输入中(底下的线)参与预测,而且加入一条新的线路(顶部的线),直接将上次的输出穿过这次的神经元直通到下一次的神经元中,也就是不参与预测。换句话说,LSTM加入两个回环,一个回环是用作下一次的预测,另外一个回环是传递给下下一次的预测。

当然,类似LSTM的门电路还有GRU,它们本质上都是一样的,通过门电路的想法来解决长期依赖的问题。LSTM是RNN的一个非常重要的优化。

3.10 注意力机制(Attention)

Attention机制是一个前沿实现,在一定的角度上看,Attention是一个独立的神经网络结构,与CNN和RNN是平级的。Attention主要描述的是输入与输出之间的偏向相关性,在此之前,我们先来探讨一下Attention机制出现的环境。

最开始时,RNN只在最后一个状态时输出结果。也就是多输入单输出的结构,例如,输入多个单词,然后求输出的句子所属类别。

然后,RNN在遇到多输入多输出的环境下就出现问题了。例如,机器翻译的问题上,输入是多个单词,输出也是多个单词,而且,输入和输出单词的数量是不一样的。这样的情况下,人们发明了Encoder-Decoder结构,输入多个单词后,最后一个状态输出隐状态,然后隐状态经过decoder模型输出结果就可以了。

Encoder-Decoder结构还可以构造为以上的结构,就是将隐藏状态c依次放入到decoder的RNN输入中,让decoder输出多个单词。但是,这个结构对于复杂的长句子没有很好地解决,因为隐状态c的长度有限,保存的信息始终不够多,当输入的单词过多时,隐藏状态c的信息就会溢出,导致输出的信息很粗糙。

一个很直观的想法是,decoder的输入应该是每个输出单词的隐状态都是不一样的,这样才能输出丰富的信息。

那么每个输出的隐状态应该来源于哪里呢?我们从句子翻译的信息看,例如,“我爱中国”翻译为”I Love China”时,“I”的输出信息应该主要包含输入的”我“的信息,“Love”的输出信息应该主要包含输入的”爱”的信息,“China”的输出信息应该主要包含输入的“中”和“国”两个字的信息。也就是说,隐状态应该是包含输入encoder的中途输出信息,而不同隐状态也是来自于输入encoder的中途输出信息,只是加权权值不同而已。“I”跟“我爱中国”的信息都有关,但它着重的是“我”的信息。

所以,Attention的第一步是将encoder的中途信息都保存下来,然后,将decoder的\(h_0'\)信息和输入中途信息放入另外一个神经网络结构中,这个神经网络输出encoder的中途信息的各个权值\(a_{11},a_{12},a_{13},a_{14}\)等等,即

\[ a_{11},a_{12},a_{13},a_{14} = f(h_0',h_1,h_2,h_3,h_4) \]

然后计算第一个输出状态的隐状态\(c_1\)

\[ c_1 = h_1*a_{11}+h_2*a_{12}+h_3*a_{13}+h_4*a_{14} \]

这时候,我们就能算出输出\(y_1\)

\[ y_1 = g(c_1,h_0') \]

依次类推,第二个输出\(y_2\)的计算为:

\[ a_{21},a_{22},a_{23},a_{24} = f(h_1',h_1,h_2,h_3,h_4)\\ c_2 = h_1*a_{21}+h_2*a_{22}+h_3*a_{23}+h_4*a_{24}\\ y_2 = g(c_2,h_1') \]

注意,这里的f与g都是复用原来计算第一个输出时的f与g。这就是整个Attention机制了。

Attention机制的网络f可以看成是单词的重新排列映射问题,其输出权重,让高权重的输入优先影响到当前的输出中。网络g就是简单的输入与输出的翻译映射问题了。例如,“你是谁”,翻译为英文就是”Who Are You”,如果我们直接逐个字翻译,只有g网络,翻译出来的结果就是”You Are Who”,但是含有f网络后,f网络首先会将输入重排为“谁是你”,然后再逐字翻译为”Who Are You”,这就没有问题了。所以说,Attention主要描述的是输入与输出之间的偏向相关性。

所以,根据这个思路,Google做出来一个只含有Attention机制,没有RNN的神经网络做机器翻译《Attention Is All You Need》,结果发现性能超高,而且效果还非常好,达到了当时的state-of-the-art。这本质就是因为翻译问题可以简单地看为单词重排+逐词映射的问题,正好和Attention机制是匹配的。

同理,使用Attention机制可以用来做video的描述,首先使用cnn来抽取每一帧的特征,然后用Attention来确定输入的权重来生成输出的文字。

3.11 递归张量神经网络(RNTN)

Screen Shot 2017-08-24 at 10.19.32 P

呃,这个网络类型我真的不太懂它在干什么,只知道它能将非结构化数据转换为结构化数据,例如分析出文本中句法结构。

4 生成模型

4.1 自动编码机(AE)

自动编码机在之前的判别模型中已经介绍过了,每次训练完一层后,将编码器留下,解码器扔掉,就变为一个特征提取器了。可是,如果我们将编码器扔掉,解码器留下,会是什么?输入是一段很短的code,输出是一幅完整的image,显然,这就是一个生成模型。我们可以任意输入code,然后让机器生成我们想要的目标数据。就这样,我们得到了一个简单的自监督形式的生成器模型。

可问题是,当我们训练好这样的生成模型后,最大的问题是生成出来的图片特别的假,不直观。那是因为AE训练时的自监督使用的是MSE对比方式,像上图的两幅图,左图是原图,右图是生成图,即使右图看起来有个点,但是MSE对比时loss就是比较少(MSE对比就是逐个像素一一对比),所以AE训练时就会认为右图比较逼真。

当然AE也有它特别的应用,AE的输入是经过噪音处理后的图片,输出是原图片时,经过一段时间训练的AE就学会了处理去除噪音的方法。这种方法十分适用于只知道编码方法,但不知道解码方法的场景,例如是去噪音,去水印,去马赛克,去雾,去雨等等。

4.2 变分自动编码机(VAE)

变分自动编码机(VAE)从概率的角度解决了AE的问题,我们从直观上可以看出,当AE的code生成原图时,与这个code相差不大的其他code也应该生成和原图一样呀。那么,我们可以做像数据提升的方法,AE生成code以后,我们以这个code为中心,在它附近生成其他code,然后也强迫这些code也必须与原图相同不就好了么。这相当于一种避免过拟合,数据提升的办法。

那么,随机生成的这些code应该离原来的code有多远呢,差0.001,还是差0.01呢?答案是我也不知道,为什么不让神经网络也一并生成呢,这个差值的多少我们可以用方差来描述。因此,VAE除了跟AE一样生成code以外,它还会生成一个新向量code的方差。例如,AE编码code含义如果是(物种,颜色)两个维度的话,VAE就是(物种均值,颜色均值)和(物种方差,颜色方差),也就是上图中的蓝色和黄色的部分。然后VAE根据物种和颜色两个变量的均值和方差,并假设它们为正态分布,从中抽样出两个随机变量,随机的物种和随机的颜色,也就是上图中的绿色部分。最后将这两个随机变量看成解码code来解码为原图像。

可是,我们也应该注意到一个问题,训练时如果神经网络生成的方差都是0,那么就相当于没有随机的正态分布了,不就相当于原始的AE了么。解决办法就是,将方差也纳入到loss的考虑里面,方差越小的话,loss的惩罚就越大,以此来强迫神经网络尽可能生成方差更大,而且拟合度越好的生成模型。

Screen Shot 2017-08-31 at 9.52.06 P
Screen Shot 2017-08-31 at 9.52.19 P
Screen Shot 2017-08-31 at 9.52.23 P

所以loss为mse与kl散度的和。

实践证明,vae的生成模型相当平滑,以上是mnist数据库在二维code下的生成模型,可以看出生成图片在各个数值下都很平滑。

4.3 对抗生成网络(GAN)

对抗生成网络从另外一个角度来考虑生成的问题,它不像VAE一样企图将数据降维,让生成出来的数据在code上面连续变化。它只考虑一种场景,怎么让生成出来的数据更加逼真。它的方法是让Z(相当于原来的code)输入到生成模型(G)中,并且让生成模型(G)生成的图片和已有的图片X放入到判别模型(D)中,由于已知已有图片为逼真,生成图片不逼真,以此来训练判别模型(D),然后让G自己训练尽可能地欺骗D为逼真数据,而D反过来也不断训练提高G的判别能力,以此类推。通过这种左右手互搏的训练方法,最终让G和D不相上下,使得G网络成为一个相当逼真的生成模型。

训练的过程如下

  • 随机生成Z数据,并用刚初始化的G网络生成一堆数据X’
  • 然后将现有数据X和生成数据X’放入判别模型D,并设置现有数据X的输出为1,生成数据X’的输出为0,从而只训练判别模型D。
  • 固定判别模型D的权值与偏置不变,将第一步的随机数据Z扔进去生成模型G,并设置判别模型D的输出为1,从而只训练生成模型G。
  • 返回第一步,继续训练。

GAN思路十分神奇,在实践中主要遇到的问题是参数太多,收敛太难。所以GAN的部分优化转向了图像方面,因为图像处理有卷积层的话能共享权值,避免参数太多,所以产生了专门生成图像的GAN变种DCGAN。

4.4 条件对抗生成网络(cGAN)

普通的对抗生成网络中,输入到模型G的数据为随机噪音,也就是说我们无法控制输出图像的性质。如果说我们已经有了一堆有头发的照片照片和一堆无头发的真实照片,如何控制对抗生成网络来按照要求生成有头发或无头发的照片呢。答案是条件对抗生成网络,这个模型让原始的GAN从自监督学习走向了监督学习。

首先,生成模型G的输入除了随机噪音外,新增一项控制变量G(这个控制变量控制是否有头发,是否带眼镜等等)。然后判别模型D也增加一样的控制变量G。然后训练的方法如下

  • 正确的X+正确的控制变量,输出为1,正确的X+错误的控制变量,输出为0。从而训练判别模型D。
  • 生成的X’+正确的控制变量,输出为0,生成的X’+错误的控制变量,输出为0。从而训练判别模型D。
  • 固定判别模型D不动,生成的X’+正确的控制变量,输出为1,生成的X’+错误的控制变量,输出为0。从而生成模型G。
  • 返回第一步,继续训练。

另外一个cGAN的优化是在第三步训练生成模型G时,让控制变量0和1之间插入一些随机样本,然后也让输出插值,相当于做数据提升,从而提高生成模型G的泛化能力。

最后,要注意的是,第一步训练判别模型D时显然是个监督学习的过程。这个方法适用于有数据的一一标注样本时的数据生成。

跟GAN促发了DCGAN的变种一样,cGAN也促发了pix2pix的GAN变种,它使用了cGAN的监督学习方式,并且加入了卷积层权值共享想法,实现了图像的监督式学习,像图像超分辨率,图像修复都能做。

另外,cGAN的另外一个变种是期望让GAN自己无监督地学习控制变量,而不是人为标注,这个GAN的变种是InfoGAN,它能从人脸照片中自动识别出笑脸,眼镜等控制变量。

4.5 循环对抗生成网络(CycleGAN)

循环对抗生成网络(CycleGAN)试图从另外一个角度解决cGAN的问题,cGAN需要一一对应的标注样本才能有效地学习到生成模型。但是现实中我们也许很能找到这种样本,例如,我们只知道梵高的许多画像,但我们没有针对某一幅图像所对应的梵高风格的图像,所以我们无法使用cGAN来做图像风格转移。

循环对抗生成网络(CycleGAN)是建立两个生成模型,和两个判定模型。假设数据集分别为X和Y,从X生成到Y的生成模型为G,从Y生成到X的生成模型为F,并且两个数据集中都各自有自己的判定模型D_x和D_y,用来确定图像是否为自己风格的。

那么训练方法为:

  • 只使用生成模型G,判定模型D_y,数据集X和数据集Y,我们可以用原始的GAN方法来训练生成模型G,判定模型D_y。
  • 然后反过来,只使用生成模型F,判定模型D_x,数据集X和数据集Y,我们可以用原始的GAN方法来训练生成模型F,判定模型D_x。
  • 只使用生成模型F,生成模型G,我们要求F(G(x))生成出来的图像必须等于自身x,从而训练到生成模型F和生成模型G。
  • 只使用生成模型F,生成模型G,我们要求G(F(y))生成出来的图像必须等于自身y,从而训练到生成模型F和生成模型G。

以上四步就是训练方法了,注意到前两步就是原始GAN的方法,如果没有第三和第四步,我们训练出生成模型G可能只是个随机模型,也就是生成模型G生成出来的数据都和数据集Y是一样的,但是和数据集X是没有映射关系的。但是,我们有第三步和第四步后就强迫地要求了生成模型G在生成时不仅需要顾虑和数据集Y的相似性,还要顾虑和数据集X的映射性。

这个方法能很好地解决没有标注样本时如何训练图像风格变换,图像主体变换,图像修复等等。

5 配置

初始化 正则化 激活函数,sigmod,tanh,Relu 训练方法,梯度下降1. 批量梯度下降法BGD 2. 随机梯度下降法SGD 3. 小批量梯度下降法MBGD

学习率,先快后慢,ADADELTA

5.1 激活函数

激活函数是加在神经元输出后面的一个函数,例如,神经元本身的输出是\(y_1\)的,经过激活函数f后,就变为\(y_2=f(y_1)\)来输出的。激活函数的本质就是用来加入非线性因素的,解决线性模型所不能解决的问题。

为加入激活函数时,图形只能被线性划分

加入特定的激活函数后,图形的划分是非线形划分的。

\[ f(x) = x \]

Screen Shot 2017-08-24 at 11.29.41 P

linear线性激活函数是最简单的激活函数,相当于没有加激活函数。

Screen Shot 2017-08-24 at 11.32.42 P

sigmoid是一个很早期激活函数,优点是输出映射在(0,1)之间,单调连续,输出范围有限,优化稳定,可以用作输出层。缺点是,在大范围外\((-\infty,-10和(10,+\infty)\)导数几乎为0(这个称为软饱和特性),容易产生梯度消失的问题。

Screen Shot 2017-08-24 at 11.36.14 P

tanh是一个跟sigmoid激活函数,优点是输入范围大多在[-1,1]之间,输出范围也在(-1,1)之间,关于原点对称,可以用作输出层,收敛速度也很快。缺点是,和sigmoid一样容易导致梯度消失。

Screen Shot 2017-08-24 at 11.38.28 P

relu是一个比较新的激活函数,本质就是个取最大非负数的函数,优点是没有软饱和问题,在SGD中收敛速度飞快,而且很好地缓解梯度消失的问题,缺点是训练时有可能陷入都是负数,使得导数都为0,梯度永远为0,也就是一大批的神经元不可逆转的死掉了。

Screen Shot 2017-08-24 at 11.42.47 P

elu就是relu上的一个改进,让负数的数值导数也存在,但非常快地接近于0,一定程度上避免了relu的神经元死亡问题。同时保留了relu的快速训练的优点。当然代价就是计算量要大很多,因为有个指数操作。

Screen Shot 2017-08-24 at 11.45.02 P

softplus,比较少用

Screen Shot 2017-08-24 at 11.45.05 P

softsign,比较少用

softmax是sigmoid的一个推广,sigmoid是二类分类,softmax就是输入多个数值时转换为各个分类的概率值,计算超级简单,就是数值越大的那个输出越接近1,数值越小的那个输出越接近0。而且跟前面的激活函数不太一样的是,这个激活函数是输入多个x,输出多个y的,一般用来作多分类的输出函数。

最后,总结一下

  • 隐含层激活函数,以relu为主,elu为辅
  • 输出层激活函数,连续量用tanh和linear,离散量用sigmoid和softmax。

5.2 损失函数

损失函数主要分为三类,均方差损失函数(MSE,MAE,MAPE,MSLE),交叉熵损失函数和余弦夹角损失函数

Screen Shot 2017-08-25 at 9.07.11 P

MSE是常见的差值平方的损失计算。

Screen Shot 2017-08-25 at 9.07.17 P

MAE是较为准确的数值距离的损失计算,避免了差值平方时距离平方式增大。

Screen Shot 2017-08-25 at 9.11.38 P

MAPE是MAE的优化,避免某个数值太大导致对整体损失的权重太高。

MSLE是MSE的优化,和MAPE对MAE的优化一样,避免某个数值太大导致对整体损失的权重太高。

Screen Shot 2017-08-25 at 9.17.09 P

交叉熵函数是以熵的形式来定义误差,专门是用来解决sigmoid和softmax函数中软饱和问题的,当sigmoid作输出函数一般时用binary_crossentropy,当softmax作输出函数时一般使用categorical_crossentropy。

余弦值的范围在[-1,1]之间,值越趋近于1,代表两个向量的方向越趋近于0,他们的方向更加一致。相应的相似度也越高。也就是当输出值不是数值,也不是概率,而是特征向量时,使用余弦夹角损失函数就比较合适。

最后,总结一下

  • 输出层数据是数值时,使用(relu,elu,linear)+均方差损失函数
  • 输出层数据是概率时,使用(sigmoid,softmax)+交叉熵损失函数
  • 输出层数据是特征向量时,使用(relu,elu,linear)+余弦夹角损失函数

5.3 训练方法

无论是哪个类型的神经网络,在训练时总是离不开梯度下降算法,而梯度下降算法在学习率,动量,学习率衰,越过拐点等问题上有众多的优化分支,主要为BGD,SGD,MBGD,RMSprop和其他

Screen Shot 2017-08-25 at 10.35.10 P

批量梯度下降法(Batch Gradient Descent,简称BGD)是梯度下降法最原始的形式,它的具体思路是在更新每一参数时都使用所有的样本来进行更新。优点是梯度下降方向准确,缺点是训练速度超慢。

Screen Shot 2017-08-25 at 10.37.06 P

随机梯度下降法(Stochastic Gradient Descent,简称SGD)正是为了解决批量梯度下降法这一弊端而提出的,利用每个样本的损失函数对θθ求偏导得到对应的梯度来进行更新。优点是训练速度快,缺点是梯度下降方向不准确,容易收敛到局部解。

Screen Shot 2017-08-25 at 10.38.37 P

小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD)同时吸收了BGD和SGD的优势,算法的训练过程比较快,而且也要保证最终参数训练的准确率。

RMSprop通过初一周围梯度的幅度的平均值来使得权重和偏置平缓变化,避免剧烈变动,这个训练方法在RNN上尤其有效。

最后,总结一下

  • 一般情况的训练下都用MBGD,但很多库上都将SGD说是MBGD,允许SGD算法设置学习率,衰退率,动量率和批量大小。
  • 递归神经网络使用RMSprop,这类训练方法建议采用默认参数就可以了。

5.4 初始化数据

在训练神经网络前,一般需要将数据预处理

  • 归一化,由于很多激活函数都只在[-1,1]之间有明显的梯度,所以将数据归一化为均值为0,方差为1的数据则能较快地收敛。不过,如果你的网络激活函数主要是由relu组成的话,将数据归一化为[0,1]之间的数据会更为合适。
  • 生成噪音,为了避免数据只拟合到输入的训练数据集中,我们一般会将数据数据加入随机噪音来增强神经网络的泛化性能。例如,在图像识别中,让图像加入噪点,光照等的影响来增强泛化性能。
  • 数据变换,将输入数据进行变换来增强网络的泛化性能,例如自动将部分图像旋转,扭曲等,来增强网络对这类数据的识别。
  • 随机生成数据,为了弥补训练数据不足的问题,在特定场景下,我们可以换个思路,去考虑用随机数生成训练数据,然后用训练数据来训练网络,这样就能解决数据不足的问题。例如,做一个验证码识别的神经网络。

5.5 初始化权值

训练网络前,我们不仅需要初始化数据,还需要初始化权值和偏置。

权值初始化,要注意两点,权值不能全为0,这样容易导致梯度崩溃。另外,权值最好在[-1,1]之间,避免散落在较大数值中,导致sigmoid和tanh激活函数下的梯度消失的问题。

  • 均匀分布,\(W = np.random.uniform(low=-scale, high=scale, size=shape)\)
  • 高斯分布,激活函数为sigmoid或tanh时,\(w = np.random.randn(n) / sqrt(n),n为参数数目\),激活函数为relu时,\(w = np.random.randn(n) * sqrt(2.0/n),n为参数数目\)
  • fine-tune,使用已经训练好的网络权值来代入到当前网络中,以将之间网络特征提取器迁移到本场景上。对于大型神经网络来说,这招很好用。

偏置初始化,一般就是全为0。

5.6 过拟合

解决神经网络中过拟合问题

  • 三路数据分割,将数据分割为训练集,测试集和验证集。验证集数据较小用来选择模型,一旦模型确定后我们将训练集数据扔进去训练模型的参数,最后用训练集的分类器来计算测试集误差。如果分类器是过拟合的话,数据只能通过训练集,而不能有效泛化到测试集。
  • 正则化,在损失函数中人工加入一个惩罚项,惩罚项就是偏置和权值越大,惩罚项的数值越大。而神经网络的目标就是最小化损失函数,这就实现了在最小化拟合误差的同时,也平衡地最小化偏置和权值的数值。因为根据过拟合的现象,我们可以猜测出偏置和权值的数值越大,过拟合的现象出现就越明显。L1正则化就是\(\lambda \lvert \omega \rvert\),L2正则化就是\(\lambda \lvert \omega \rvert^2\)
  • 最大范数约束,严格来说,这也算是正则化的一种。如果偏置和权值的绝对值大于某个指定的阀值,就会被添加到惩罚项中。也就是\(\lvert \omega \rvert > a?b:0\)
  • 弃置(dropout),随机弃置一些神经元,如果拟合误差大幅提高,证明这个网络过度依赖于部分节点,鲁棒性差,因此我们会选择加入惩罚项,尽量避免这类网络。

神经网络中,三路数据分割,和dropout的效果是最好的。

5.7 性能评估

精确率是针对我们预测结果而言的,它表示的是预测为正的样本中有多少是真正的正样本。那么预测为正就有两种可能了,一种就是把正类预测为正类(TP)另一种就是把负类预测为正类(FP)。所以这个指标又称为查准率。

而召回率是针对我们原来的样本而言的,它表示的是样本中的正例有多少被预测正确了。那也有两种可能,一种是把原来的正类预测成正类(TP),另一种就是把原来的正类预测为负类(FN)。所以这个指标又称为查全率。

一般来说,精确率和召回率是两个相互矛盾的指标,召回率较高时精确率就偏低,精确率较高时召回率就偏低。但是,当召回率和精确率都很低时就证明这个模型就真的很有问题了。

5.8 速度

提高速度

  • 共享存储,CPU,GPU,FPGA,ASIC,速度从快到慢。
  • 分布式,数据并行,模型并行,管道并行

6 前沿模型

6.1 迁移学习

迁移学习是一种手段,可以在所需减少标注样本数据量的情况下达到要求的精确度。

  • fine-tune,将已经训练好的其他分类模型拿过来做当前分类模型的初始权重,已经再对少量样本进行微调权重就可以了。
  • bottleneck,除了fine-tune迁移全部权重外,bottleneck更进一步,只迁移部分权重(一般为特征提取层的权重),然后保持这些迁移权重不变,单独训练网络的其他权重。
  • 模拟,先在模拟环境中进行训练,然后才将真实样本放进去训练。例如,我们训练ocr模型时,先训练程序生成的随机图像,然后才将实际案例中的图像放进去训练。
  • 投射,已经有A环境的模型,如果我们需要B环境下的模型,我们可以寻求A环境和B环境的映射关系,从而达到无需训练B环境样本的目的。例如,我们已经得到用户关于音乐的喜好,如果我们需要找到用户关于电影的喜好。我们可以迂回地寻找音乐和电影的风格特征映射,从而无监督地做出一个推荐用户电影的模型。

6.2 强化学习

强化学习是学习模型的另外一个分支,是一种试错性的学习方法。

有多种的强化学习算法

7 库与平台

平台

  • H2O
  • GraphLab

  • Theano,Python的库,性能好,复杂,无法分布式。
  • DeepLearning4j,Java的库,性能好,具有丰富的可选网络类型,支持分布式。
  • Torch,Lua的库,性能好,容易嵌入到其他语言中,具有丰富的可选网络类型,支持超参数配置,不支持分布式。
  • Caffee,C++的库,性能好,具有丰富的可选网络类型,支持超参数配置,十分适用于CNN网络,而且有很多做好的model可以选
  • TensorFlow,全语言的库,性能好,功能强大,支持分布式,数据和模型并行,各种底层硬件支持。是目前最流行的深度学习库。

8 总结

深度学习是一个相当具有魔法的工具,它就像早期诞生的傅立叶变换一样,工程师们很喜欢它,对复杂问题能用一个简单的方法work,但是学术派都不愿意接受它,因为它缺少一个坚实的理论基础,难以有深入而且本质的发现。从另外一个角度看,恰好说明了我们人类的基础科学发展还有很遥远的路要走。

另外,深度学习的学习过程需要跳出纯粹的数学推导,要从直觉中去寻找这样做的原因,然后学会应用后再学会理论研究。

从本质上看,深度学习是使用连续的几何变换将空间X映射到空间Y的能力,给出了大量的人为标注的数据。无论是cnn,rnn,还是其他变种,它本质上都是利用标注数据来生成特征提取器,它并没有实现真正的认知智能,只是实现了感知智能而已。让人讽刺的是,最初人们在考虑如何识别人脸的这个感知智能问题上,他们希望的是发明更复杂的传感器,却没有想到这个根本上就是个计算问题而已。

参考资料

Deep Learning SIMPLIFIED视频 keras的文档 Jango的深度学习讲解 我是这样学习 GAN 的

相关文章