首先,讨论一下Deep Learning的一些起源文章,在2006年以前,深度的神经网络一直没有很好地训练方法,有一些问题(比如前文所说的“梯度消亡”的问题),结果不好。2006年,发了3篇重要的初创文章,改变了这一局面,并开始了Deep Learning这个领域的大发展。这3篇文章是:
Hinton,G. E., Osindero, S. and Teh, Y.,Afast learning algorithm for deep belief nets.Neural Computation 18:1527-1554, 2006
Yoshua Bengio, Pascal Lamblin, Dan Popovici and HugoLarochelle,Greedy LayerWise Training of DeepNetworks, in J. Platt et al. (Eds), Advances in Neural Information Processing Systems 19 (NIPS 2006), pp. 153-160, MIT Press, 2007
Marc’Aurelio Ranzato, Christopher Poultney, Sumit Chopra and YannLeCun Efficient Learning of SparseRepresentations with an Energy-Based Model, in J. Platt et al. (Eds), Advances in Neural InformationProcessing Systems (NIPS 2006), MIT Press, 2007
(Google上搜蓝色标题的3篇paper可以查到原文。)
首先被研究出来的是DBN(DeepBelief Networks)模型(基于RBM模型),这是Hinton开创的,就是上面第1篇论文。然后Bengio详细分析了DBN,并提出了一种训练效率比较DBN要高,更加generalization,结果与DBN近似的模型:auto-encoders,就是上面第2篇论文。然后YannLeCun等人进一步提出Sparse auto-encoders 模型,就是上面第3篇论文。我觉得分层训练,Pretraining是整个技术的核心突破。
另外,Bengio在2003年发表了一篇论文“ANeural Probabilistic Language Model”,提出了一种基于神经网络的语言模型用于NLP(自然语言处理),这是很重要的论文,后面被NLP领域广泛引用,包括Google的word2vec,包括MT(机器翻译)领域的一些文章。这些模型也是Deep Learning领域的模型。
还有,Yann LeCun在1998年做的CNN(Convolutionalneural networks卷积神经网络),(CNN最早是1980由 Kunihiko Fukushima提出来的),这个模型在图像处理领域应用非常广泛,特别是在银行领域的手写数字识别,效果很好。这也是典型的Deep learning模型中的一种,后面详细说明。
下面介绍一下DBN相关的模型。DBN的基础是RBM模型,先说一下RBM模型(受限波尔兹满机)。
波尔兹曼分布是一种能量分布函数,Wiki解释如下:在统计力学的领域。任何(宏观)物理系统的温度都是组成该系统的分子和原子的运动的结果。这些粒子有一个不同速度的范围,而任何单个粒子的速度都因与其它粒子的碰撞而不断变化。然而,对于大量粒子来说,处于一个特定的速度范围的粒子所占的比例却几乎不变,如果系统处于或接近处于平衡。麦克斯韦-玻尔兹曼分布具体说明了这个比例,对于任何速度范围,作为系统的温度的函数。示意如下图:
为什么要采用波尔兹满分布(Boltzmann),是我比较疑惑的问题,一个前辈告诉我,因为波尔兹满分布是自然界很普遍的现象,但我的疑惑还没有完全解开。
BM(波尔兹满机)是基于统计力学波尔兹曼分布的一种2层网络模型(分为可见层和隐藏层),是Hinton和Sejnowski在1986年提出的,后来Smolensky提出了简化版的RBM(受限波尔兹曼机),如下图:
RBM的层内无连接,层间全连接是BM的一种简化模型,主要为了求解方便。而且,RBM具有很好的性质,在给定可见层单元状态,各隐单元的**条件独立,反之,在给定隐单元状态时,可见层单元的**也是条件独立,而且通过Gibbs采样可以得到服从RBM表示的随机样本,(Roux和Bengio从理论上证明,只要隐单元数据足够多,RBM能够拟合任意离散分布。)。另外,经过简化后的RBM模型就是一个条件随机场模型(无向图模型),如下图:
用Gibbs采样,使用马尔科夫链蒙特卡洛方法,可以模拟RBM模型的样本分布,即用一个训练样本初始化可见层状态V0 ,交替进行如下采样:
不过,Gibbs采样需要很多采样步数,特别是特征维度高时计算量很大,Hinton在2002年提出CD算法(Contrastive Divergence 对比散度算法),简单说,Hinton指出,用一个训练样本初始化可见层状态V0后,只需要K步Gibbs采样就可以得到足够好的近似值,通常K=1。 CD算法是RBM的快速学习方法,对RBM模型发展的起了重要的推动作用。
此外,RBM还有挺多参数,比如学习率,动量学习率,权衰减,隐单元个数,W和b的初始值等。附件的文章《受限波尔兹曼机简介》有对该模型和算法实现过程的详细说明。
RBM的隐层h,其实是对可见层v进行重构,所以也是对样本数据的特征自学习,或者说是Representation Learning,示意如下图:
多层的RBM叠加在一起,就组成了DBN的深度网络,如下图所示(来自Hinton的论文):
同样,DBN的训练,也分为Pretraining,和fineTurning(BP算法)两个步骤,与AutoEncoder类似。我感觉DBN更多地考虑了特征之间的相互依赖性(马尔科夫链),在各个维度的特征是不同类型的数据时(如离网预测的数据),效果会更好,这是与AutoEncoder不同的地方,AutoEncoder更适合所有维度的特征是同一类型的数据。
Theano中DBN代码要点说明:
# construct the RBM class
rbm = RBM(input=x, n_visible=28 * 28,
n_hidden=n_hidden, numpy_rng=rng, theano_rng=theano_rng)
默认参数:
deftest_rbm(learning_rate=0.1, training_epochs=15,
dataset='mnist.pkl.gz', batch_size=20,
n_chains=20, n_samples=10, output_folder='rbm_plots',
n_hidden=500):
运行参数:
test_rbm(training_epochs=3,n_hidden=160)
经过0,1,2三次迭代后,分别得到的0~9的手写数字图像特征:
DBN基于离网预测的数据进行测试:
# Construct an RBM that shared weights with this layer
rbm_layer = RBM(numpy_rng=numpy_rng,
theano_rng=theano_rng,
input=layer_input,
n_visible=input_size,
n_hidden=hidden_layers_sizes[i],
W=sigmoid_layer.W, #权值与隐层一致,实际上是一层
hbias=sigmoid_layer.b)
self.rbm_layers.append(rbm_layer)
# We now need to add a logistic layer on top of the MLP 隐层最后一层的输出是LR的输入
self.logLayer = LogisticRegression(
input=self.sigmoid_layers[-1].output,
n_in=hidden_layers_sizes[-1],
n_out=n_outs)
self.params.extend(self.logLayer.params)
#这里返回cost,最后的LR分类器的权值W,b,最后一个隐层的权值W,b
train_fn = theano.function(inputs=[index],
outputs=[self.finetune_cost, self.logLayer.W, self.logLayer.b,self.sigmoid_layers[self.n_layers-1].W,self.sigmoid_layers[self.n_layers-1].b],
updates=updates,
givens={self.x: train_set_x[index * batch_size:
(index + 1) * batch_size],
self.y: train_set_y[index * batch_size:
(index + 1) * batch_size]})
#construct the Deep Belief Network
dbn = DBN(numpy_rng=numpy_rng, n_ins=dimension, #输入层,输入个数为特征维数
hidden_layers_sizes=[10, 10, 10], #3个隐层,每层10个神经元
n_outs=2) #输出层,2分类softMax
#得到模型参数
minibatch_avg_cost, LR_W, LR_b,lastHiddenlyer_W, lastHiddenlyer_b = train_fn(minibatch_index)
# 模型训练参数(k是动量学习率,不能用0.5):
test_DBN(finetune_lr=0.1,pretraining_epochs=10, pretrain_lr=0.01, k=1, training_epochs=10,batch_size=500)
调整这些训练参数测试,对DBN模型训练很重要,不同的DBN结构(层数,神经元数等),不同的参数组合,训练结果会有很大区别。所以,不同的人使用DBN,可能会做出区别很大的结果。Deep Learning的调参训练,也是个很高深的学问。我曾经问过Hinton的学生,有没有什么rule可以用于设计DNN的结构,得到的答案是要看数据的情况去设计。