标签:[] init os.path nump reg const out ptr 网络
栈式去噪自编码器是栈式自动编码器的扩展[Bengio07],并且它在[Vincent08]里有介绍。
这次教程建立在之前的去噪自编码器Denoising Autoencoders。如果你对自编码器没什么了解,建议你先了解一下。
通过把上一层去噪自编码器找到的隐藏输入(output code)当作下一层的输入,我们可以把去噪自编码器以栈的形式构成一个深度网络。这种无监督预训练的结构在一层里同时实现。每一层当作一个去噪自编码器,通过重构输入(上一层的输出)最小化损失。一旦前面 层被训练好,我们就可以训练第 层,因为我们下载可以计算输出的code,或者说是前一层的隐藏表达。
一旦所有层都预训练好,整个网络进入训练的第二个阶段 fine-tunning。这里我们考虑有监督的 fine-tunning,因为我们想在一个有监督训练中最小化预测错误。首先我们在网络的最顶端加一个logistic回归层(更精确的说,是在输出层的输出code前)。然后我们训练整个网络,正如我们训练一个多层感知机一样。这里,我们只需要考虑每一层自编码器的编码部分。在训练中使用目标分类,这步是有监督的。(详情请看Multilayer Perceptron)
复用之前定义的类,栈式自编码器在Theano里面很容易实现。我们可以看到栈式自编码器有两部分:一系列的自编码器和一个MLP。在预训练的阶段,我们使用第一部分,例如我们使用一系列自编码器加入我们的模型中,然后每个自编码器单独训练。在训练的第二阶段,我们使用第二部分。这两部分是相连的,因为
1 class SdA(object): 2 """栈式去噪自编码器 类 3 4 通过堆积几个dA来组成展示去噪自编码器。第i个dA的隐藏层被当作第i+1层的输入。 5 第一层dA把SdA的输入当作输入,最后的dA表示输出。在预训练之后,SdA被当作是 6 普通MLP,dAs只用来初始化权值。 7 """ 8 9 def __init__( 10 self, 11 numpy_rng, 12 theano_rng=None, 13 n_ins=784, 14 hidden_layers_sizes=[500, 500], 15 n_outs=10, 16 corruption_levels=[0.1, 0.1]): 17 self.sigmoid_layers = [] 18 self.dA_layers = [] 19 self.params = [] 20 self.n_layers = len(hidden_layers_sizes) 21 22 assert self.n_layers > 0 23 24 if not theano_rng: 25 theano_rng = RandomStreams(numpy_rng.randint(2 ** 30)) 26 27 self.x = T.matrix(‘x‘) # 输入被光栅化的图片 28 self.y = T.ivector(‘y‘) # 1维数组表示[int]标签
self.sigmoid_layers 会储存MLP部分的sigmoid层,self.dA_layers 会储存和MLP有关的去噪自编码。
接下来,我们构造 n_layers 个sigmoid层和 n_layers 去噪自动编码器,其中 n_layers 是我们模型的深度。我们使用Multilayer Perceptron介绍的 HiddenLayer 类,只有一个地方改了,就是我们使用sigmoid 代替之前的 tanh 非线性激活函数。我们链接sigmoid层来构建一个MLP,并且构建去噪自编码器,每个的编码部分与对应的sigmoid层共享权值和偏置项。
1 for i in range(self.n_layers): 2 # 构建sigmoid层 3 4 # 输入的size,要么是前一层隐藏层的数量 5 # 要么是SdA的输入 6 if i == 0: 7 input_size = n_ins 8 else: 9 input_size = hidden_layers_sizes[i-1] 10 11 # 本层的输入要么是上一层隐藏层的激活 12 # 要么是SdA的输入 13 if i == 0: 14 layer_input = self.x 15 else: 16 layer_input = self.sigmoid_layers[-1].output 17 18 sigmoid_layer = HiddenLayer(rng=numpy_rng, 19 input=layer_input, 20 n_in=input_size, 21 n_out=hidden_layers_sizes[i], 22 activation=T.nnet.sigmoid) 23 24 # 添加层 25 self.sigmoid_layers.append(sigmoid_layer) 26 27 self.params.extend(sigmoid_layers.params) 28 29 dA_layer = dA(numpy_rng=numpy_rng, 30 theano_rng=theano_rng, 31 input=layer_input, 32 n_visible=input_size, 33 n_hidden=hidden_layers_sizes[i], 34 W=sigmoid_layer.W, 35 bhid=sigmoid_layer.b) 36 self.dA_layers.append(dA_layer)
现在我们需要做的就是在sigmoid层之上加一个logistic层。我们使用之前在Classifying MNIST digits using Logistic Regression介绍的 LogisticRegression 类。
1 self.logLayer = LogisticRegression( 2 input=self.sigmoid_layers[-1].output, 3 n_in=hidden_layers_sizes[-1], 4 n_out=n_outs) 5 6 self.params.extend(self.logLayer.params) 7 # 构建一个实现单步微调的函数 8 9 # 计算训练第二步需要的损失函数 10 self.finetune_cost = self.logLayer.negative_log_likelihood(self.y) 11 # 计算给定参数的模型梯度 12 # 符号变量指向小批量样本得到的损失 13 self.errors = self.logLayer.errors(self.y)
SdA 类也提供了一个方法在层里为去噪自编码器生成训练函数。他们返回一个list,其中第 i 个元素是一个函数,实现对应 i 层的 dA 的训练。
1 def pretraining_functions(self, train_set_x, batch_size): 2 """生成一列表的函数,每一个实现dA对应层的训练。 3 函数要求输入小批量的下标,训练一个dA只需要迭代, 4 调用对应的函数。 5 """ 6 7 index = T.lscalar(‘index‘)
为了可以在训练的时候改变被破坏的等级或学习率,我们使用Theano变量。
1 def pretraining_functions(self, train_set_x, batch_size): 2 """生成一列表的函数,每一个实现dA对应层的训练。 3 函数要求输入小批量的下标,训练一个dA只需要迭代, 4 调用对应的函数。 5 """ 6 7 index = T.lscalar(‘index‘) 8 9 corruption_level = T.scalar(‘corruption‘) 10 learning_rate = T.scaler(‘lr‘) 11 12 batch_begin = index * batch_size 13 batch_end = batch_begin + batch_size 14 15 pretrain_fns = [] 16 for dA in self.dA_layers: 17 cost, updates = dA.get_cost_updates(corruption_level, learning_rate) 18 19 fn = theano.function( 20 inputs=[index, 21 theano.In(corruption_level, value=0.2), 22 theano.In(learning_rate, value=0.1) 23 ], 24 outputs=cost, 25 updates=updates, 26 givens={ 27 self.x: train_set_x[batch_begin: batch_end] 28 }) 29 30 pretrain_fns.append(fn) 31 32 return pretrain_fns
现在每一个函数 pretrain_fns[i] 以 index,corruption 和 lr 为参数。注意,参数的名字是传给Theano时构造的名字,不是Python的变量(learning_rate, corruption_level)。当我们使用Theano的时候必须记住。
同样地我们为了构建函数而新建在finetuning时候的方法( train_fn, valid_score, test_score)。
1 def build_finetune_functions(self, datasets, batch_size, learning_rate): 2 3 (train_set_x, train_set_y) = datasets[0] 4 (valid_set_x, valid_set_t) = datasets[1] 5 (test_set_x, train_set_y) = datasets[2] 6 7 n_valid_batches = valid_set_x.get_value(borrow=True).shape[0] 8 n_valid_batches //= batch_size 9 n_test_batches = test_set_x.get_value(borrow=True).shape[0] 10 n_test_batches //= batch_size 11 12 index = T.lscalar(‘index‘) 13 14 gparams = T.grad(self.finetune_cost, self.params) 15 updates = [ 16 (param, param - gparam * learning_rate) 17 for param, gparam in zip(self.params, gparams) 18 ] 19 20 train_fn = theano.function( 21 inputs=[index], 22 outputs=self.finetune_cost, 23 updates=updates, 24 givens={ 25 self.x: train_set_x[index * batch_size: (index+1) * batch_size], 26 self.y: train_set_y[index * batch_size: (index+1) * batch_size] 27 }, 28 name=‘train‘) 29 30 test_score_i = theano.function( 31 [index], 32 self.errors, 33 givens={ 34 self.x: test_set_x[ 35 index * batch_size: (index + 1) * batch_size 36 ], 37 self.y: test_set_y[ 38 index * batch_size: (index + 1) * batch_size 39 ] 40 }, 41 name=‘test‘ 42 ) 43 44 valid_score_i = theano.function( 45 [index], 46 self.errors, 47 givens={ 48 self.x: valid_set_x[ 49 index * batch_size: (index + 1) * batch_size 50 ], 51 self.y: valid_set_y[ 52 index * batch_size: (index + 1) * batch_size 53 ] 54 }, 55 name=‘valid‘ 56 ) 57 58 def valid_score(): 59 return [valid_score_i(i) for i in range(n_valid_batches)] 60 61 def test_score(): 62 return [test_score_i(i) for i in range(n_test_batches)] 63 64 return train_fn, valid_score, test_score
注意到 valid_socre 和 test_score 不是一个Theano函数,但是会在验证集和整个测试集循环,构造一个这个数据集上的损失列表。
下面构造一个栈式自编码器
1 numpy_rng = numpy.random.RandomState(89677) 2 print(‘... building the model‘) 3 # construct the stacked denoising autoencoder class 4 sda = SdA( 5 numpy_rng=numpy_rng, 6 n_ins=28 * 28, 7 hidden_layers_sizes=[1000, 1000, 1000], 8 n_outs=10 9 )
训练这个网络有两步: 逐层预训练,然后fine-tuning。
在预训练阶段,我们会循环所有的层。对于每一层,我们会使用Theano编译的函数来实现SGD的前向反馈实现权值更新,减少重构损失。
1 ######################### 2 # PRETRAINING THE MODEL # 3 ######################### 4 print(‘... getting the pretraining functions‘) 5 pretraining_fns = sda.pretraining_functions(train_set_x=train_set_x, 6 batch_size=batch_size) 7 8 print(‘... pre-training the model‘) 9 start_time = timeit.default_timer() 10 ## Pre-train layer-wise 11 corruption_levels = [.1, .2, .3] 12 for i in range(sda.n_layers): 13 # go through pretraining epochs 14 for epoch in range(pretraining_epochs): 15 # go through the training set 16 c = [] 17 for batch_index in range(n_train_batches): 18 c.append(pretraining_fns[i](index=batch_index, 19 corruption=corruption_levels[i], 20 lr=pretrain_lr)) 21 print(‘Pre-training layer %i, epoch %d, cost %f‘ % (i, epoch, numpy.mean(c, dtype=‘float64‘))) 22 23 end_time = timeit.default_timer() 24 25 print((‘The pretraining code for file ‘ + 26 os.path.split(__file__)[1] + 27 ‘ ran for %.2fm‘ % ((end_time - start_time) / 60.)), file=sys.stderr)
fine-tuning和Multilayer Perceptron类似。唯一的不同就是使用了 build_finetune_functions。
代码下载。here.
一个优化运行时间的方法就是(假设你有足够的内存),你在优化第 k 个 dA 的权值的时候,可以同时计算出第 k+1 层的输出,即第 k 层输入可以马上算出来然后和之前的 dA 分开运行。
1. Stacked Denoising Autoencoders (SdA)- http://deeplearning.net/tutorial/SdA.html
(翻译)deeplearning.net/tutorial —— 栈式去噪自编码器(SdA)
标签:[] init os.path nump reg const out ptr 网络
原文地址:http://www.cnblogs.com/mangoyuan/p/6420851.html