首页 > 其他分享 >利用Theano理解深度学习——Auto Encoder

利用Theano理解深度学习——Auto Encoder

时间:2023-06-14 21:03:36浏览次数:62  
标签:input Auto self rng Encoder 隐含 Theano theano hidden


注:本系列是基于参考文献中的内容,并对其进行整理,注释形成的一系列关于深度学习的基本理论与实践的材料,基本内容与参考文献保持一致,并对这个专题起名为“利用Theano理解深度学习”系列,若文中有任何问题欢迎咨询。本文提供PDF版本,欢迎索取。

“利用Theano理解深度学习”系列分为利用Theano理解深度学习——Auto Encoder_theano个部分,这是第二部分,在第一部分中的算法主要是监督学习算法,在这部分中主要是无监督学习算法和半监督学习算法,主要包括:

  • 利用Theano理解深度学习——Auto Encoder
  • 利用Theano理解深度学习——Denoising Autoencoder
  • 利用Theano理解深度学习——Stacked Denoising Auto Encoder
  • 利用Theano理解深度学习——Restricted Boltzmann Machine
  • 利用Theano理解深度学习——Deep Belief Network

一、自编码器(Autoencoders)的原理

自编码器是典型的无监督学习算法,其结构如下所示:

利用Theano理解深度学习——Auto Encoder_theano_02

假设输入为利用Theano理解深度学习——Auto Encoder_theano_03,自编码器首先将其映射到一个隐含层,利用隐含层对其进行表示为利用Theano理解深度学习——Auto Encoder_编码器_04,这个过程称为编码(Encoder),如:

利用Theano理解深度学习——Auto Encoder_深度学习_05

其中,利用Theano理解深度学习——Auto Encoder_深度学习_06为一个非线性映射,如sigmoid函数。利用Theano理解深度学习——Auto Encoder_深度学习_07称为隐含的变量,该隐含的变量又会通过一个映射去重构利用Theano理解深度学习——Auto Encoder_theano_08,这里的利用Theano理解深度学习——Auto Encoder_theano_08利用Theano理解深度学习——Auto Encoder_导入数据_10具有相同的结构,这个过程称为解码(Decoder)。其中映射的过程为:

利用Theano理解深度学习——Auto Encoder_导入数据_11

利用Theano理解深度学习——Auto Encoder_theano_08可以看成是给定利用Theano理解深度学习——Auto Encoder_深度学习_07的条件下对利用Theano理解深度学习——Auto Encoder_导入数据_10的一个预测,重构部分的权重矩阵利用Theano理解深度学习——Auto Encoder_深度学习_15可以被看成是第一个映射的逆过程,即利用Theano理解深度学习——Auto Encoder_深度学习_16。这被称为tied weights。模型的参数(即利用Theano理解深度学习——Auto Encoder_theano_17利用Theano理解深度学习——Auto Encoder_深度学习_18利用Theano理解深度学习——Auto Encoder_深度学习_19,如果不用tied weights,同样是利用Theano理解深度学习——Auto Encoder_深度学习_15)将被优化,以使得平均重构误差最小。

二、Autoencoder的损失函数

定义重构误差的方法有很多种,如传统的均方误差(squared error)利用Theano理解深度学习——Auto Encoder_theano_21,如果输入被转换成位向量或者概率的向量,可以使用交叉熵(cross-entropy)的度量方法:

利用Theano理解深度学习——Auto Encoder_theano_22

定义重构误差的方法取决于对输入的合适的假设。我们希望的是利用Theano理解深度学习——Auto Encoder_深度学习_07是一种分布式的表示,可以捕获在数据中的主要变化因素的坐标。这与映射到主要成分的方式相似,可以捕获数据中变化的主要因素。实际上,如果对于存在一个线性的隐含层,并且使用均方误差作为标准训练网络,则第利用Theano理解深度学习——Auto Encoder_theano_24个隐含层节点学到的是将输入映射到前利用Theano理解深度学习——Auto Encoder_theano_24个主要成分张成的空间。如果隐含层是非线性的,则auto-encoder与PCA不同,具有捕获输入分布中的多模态的能力。这种与PCA不一样的性质对于我们构建层叠式多个编码器(stacking multiply encoders)是非常重要的,如构建一个深度自编码器。

因为利用Theano理解深度学习——Auto Encoder_深度学习_07是被看成是利用Theano理解深度学习——Auto Encoder_导入数据_10的有损压缩,不可能对所有的利用Theano理解深度学习——Auto Encoder_导入数据_10都具有较好的压缩效果。优化的过程使得这样的利用Theano理解深度学习——Auto Encoder_深度学习_07对所有的训练样本来说是较好的,同时,希望对其他的输入同样也具有较好的压缩效果,但是不是对任意的输入都适用。在Auto Encoder算法中有如下的结论:

当测试样本与输入样本具有同样的分布时,auto-encoder具有较小的重构误差,但是对于从输入空间中随机选取的样本,通常具有较大的重构误差。

三、利用Theano实现Autoencoder

在Autoencoder的构建中主要包括以下几个部分:

3.1、导入数据集

在导入数据集中,主要使用的是在logistic_sgd中定义的load_data函数,其具体的导入形式如下所示:

#1、导入数据集#
datasets = load_data(dataset)#导入数据集,函数在logistic_sgd中定义
train_set_x, train_set_y = datasets[0]#得到训练数据

3.2、构建模型

构建模型的代码如下所示:

#2、构建模型
rng = numpy.random.RandomState(123)
theano_rng = RandomStreams(rng.randint(2 ** 30))
    
#初始化模型的参数
da = auto_encoder(
	numpy_rng=rng,
	theano_rng=theano_rng,
	input=x,
	n_visible=28 * 28, 
	n_hidden=500
)   
        
#定义模型的损失函数和更新规则
cost, updates = da.get_cost_updates(
	corruption_level=0.,
	learning_rate=learning_rate
)   
        
#定义训练函数
train_da = theano.function(
	[index],
	cost,
	updates=updates,
	givens={
		x: train_set_x[index * batch_size: (index + 1) * batch_size]
	}   
)   

start_time = timeit.default_timer()#定义训练的初始时间

3.2.1、类的定义

首先是对模型中的参数进行初始化,这部分主要是一个auto_encoder的类,类的定义如下所示:

class auto_encoder(object):
    def __init__(
        self,
        numpy_rng,
        theano_rng=None,
        input=None,
        n_visible=784,#输入层节点的个数
        n_hidden=500,#隐含层节点的个数
        W=None,
        bhid=None,
        bvis=None
    ):
        """
        :type numpy_rng: numpy.random.RandomState
        :param numpy_rng: 用于随机产生权重和偏置

        :type theano_rng: theano.tensor.shared_randomstreams.RandomStreams
        :param theano_rng: Theano的随机数生成

        :type input: theano.tensor.TensorType
        :param input: 描述输入的参数,None表示的是单独的autoencoder

        :type n_visible: int
        :param n_visible: 输入层节点的个数

        :type n_hidden: int
        :param n_hidden: 隐含层节点的个数

        :type W: theano.tensor.TensorType
        :param W: 指示权重的参数,如果是None表示的是单独的Autoencoder

        :type bhid: theano.tensor.TensorType
        :param bhid: 指示隐含层偏置的参数,如果是None表示的是单独的Autoencoder

        :type bvis: theano.tensor.TensorType
        :param bvis: 指示输出层偏置的参数,如果是None表示的是单独的Autoencoder

        """
        self.n_visible = n_visible#设置输入层的节点个数
        self.n_hidden = n_hidden#设置隐含层的节点个数

        if not theano_rng:
            theano_rng = RandomStreams(numpy_rng.randint(2 ** 30))

        if not W:#初始化权重
            initial_W = numpy.asarray(
                numpy_rng.uniform(
                    low=-4 * numpy.sqrt(6. / (n_hidden + n_visible)),#下界
                    high=4 * numpy.sqrt(6. / (n_hidden + n_visible)),#上界
                    size=(n_visible, n_hidden)
                ),
                dtype=theano.config.floatX
            )
            W = theano.shared(value=initial_W, name='W', borrow=True)

        if not bvis:#初始化偏置
            bvis = theano.shared(
                value=numpy.zeros(#初始化为0
                    n_visible,
                    dtype=theano.config.floatX
                ),
                borrow=True
            )

        if not bhid:#初始化偏置
            bhid = theano.shared(#初始化为0
                value=numpy.zeros(
                    n_hidden,
                    dtype=theano.config.floatX
                ),
                name='b',
                borrow=True
            )

        self.W = W#输入层到隐含层的权重
        self.b = bhid#输入层到隐含层的偏置
        self.b_prime = bvis#隐含层到输出层的偏置
        self.W_prime = self.W.T#隐含层到输出层的偏置
        self.theano_rng = theano_rng
        
        #将输入作为参数传入,可以方便后面堆叠成深层的网络
        if input is None:
            self.x = T.dmatrix(name='input')
        else:
            self.x = input

        self.params = [self.W, self.b, self.b_prime]#声明参数


    
    def get_corrupted_input(self, input, corruption_level):
        return self.theano_rng.binomial(size=input.shape, n=1,
                                        p=1 - corruption_level,
                                        dtype=theano.config.floatX) * input
    
    
    def get_hidden_values(self, input):#计算隐含层的输出
        return T.nnet.sigmoid(T.dot(input, self.W) + self.b)

    def get_reconstructed_input(self, hidden):#计算输出层的输出
        return T.nnet.sigmoid(T.dot(hidden, self.W_prime) + self.b_prime)

	def get_cost_updates(self, corruption_level, learning_rate):#计算损失函数和更新
        
        tilde_x = self.get_corrupted_input(self.x, corruption_level)
        y = self.get_hidden_values(tilde_x)
        z = self.get_reconstructed_input(y)
        
        #损失函数
        L = - T.sum(self.x * T.log(z) + (1 - self.x) * T.log(1 - z), axis=1)
        cost = T.mean(L)#求出平均误差

        # 对需要求解的参数求其梯度
        gparams = T.grad(cost, self.params)
        
        #基于梯度下降更新每个参数
        updates = [
            (param, param - learning_rate * gparam)
            for param, gparam in zip(self.params, gparams)
        ]

        return (cost, updates)

在该类的定义中,首先是参数的定义方法,在权重利用Theano理解深度学习——Auto Encoder_theano_17的定义中,是在区间利用Theano理解深度学习——Auto Encoder_深度学习_31上均匀取得,其中,利用Theano理解深度学习——Auto Encoder_深度学习_32利用Theano理解深度学习——Auto Encoder_导入数据_33分别为:

利用Theano理解深度学习——Auto Encoder_theano_34

利用Theano理解深度学习——Auto Encoder_导入数据_35

隐含层的偏置和输出层的偏置都设置为利用Theano理解深度学习——Auto Encoder_theano_36向量。get_hidden_values定义了隐含层的输出,get_reconstructed_input定义了输出层的输出,在函数get_cost_updates中定义了损失函数和对每个参数求偏导及更新的规则。计算的方法与前面算法类似。

3.3、训练模型

在模型的训练阶段,是根据每一批样本,利用梯度下降对参数进行求解,程序代码如下:

#3、训练模型
# go through training epochs
for epoch in xrange(training_epochs):
	# go through trainng set
	c = []
	for batch_index in xrange(n_train_batches):
		c.append(train_da(batch_index))

	print 'Training epoch %d, cost ' % epoch, numpy.mean(c)

end_time = timeit.default_timer()

training_time = (end_time - start_time)

'''
print >> sys.stderr, ('The no corruption code for file ' +
                          os.path.split(__file__)[1] +
                          ' ran for %.2fm' % ((training_time) / 60.))
image = Image.fromarray(
        tile_raster_images(X=da.W.get_value(borrow=True).T,
                           img_shape=(28, 28), tile_shape=(10, 10),
                           tile_spacing=(1, 1)))
image.save('filters_corruption_0.png')

os.chdir('../')
'''

其中,在循环的过程中,对模型进行训练,最终的图像输出功能被注释了。我们的目的是求出模型的权重和偏置,利用输入层到隐含层的权重和偏置,在后面的堆叠自编码其中,可以将这两层通过堆叠的方式构建成深度的网络。

四、关于隐含层节点个数的几点论述

对于隐含层节点的个数,对于非线性的自编码器,如果隐含层的节点个数大于输入层的节点个数,通过随机梯度下降法训练得到的模型通常具有更好的表示能力,这里的表示能力是指模型具有较小的分类误差。

隐含层节点个数大于输入层节点个数,这样的自编码器具有更小的分类误差。

以上的现象可以解释为:随机梯度下降法加上early stopping策略相当于对模型中的参数进行利用Theano理解深度学习——Auto Encoder_深度学习_37正则约束。对于一个隐含层节点个数大于输入层节点个数的自编码器,还有一些其他的策略可以使其在隐含层学习到输入数据的更多有用的信息,包括:

  • 增加稀疏性(Sparsity):使得隐含层节点为利用Theano理解深度学习——Auto Encoder_theano_38或者趋近于利用Theano理解深度学习——Auto Encoder_theano_38
  • 在输入到重构的过程中增加随机性(Randomness)。在Restricted Boltzmann Machines和Denoising Auto-Encoders中会涉及。

若需要PDF版本,请关注我的新浪博客@赵_志_勇,私信你的邮箱地址给我。

参考文献

Deep Learning Tutorialshttp://www.deeplearning.net/tutorial/


标签:input,Auto,self,rng,Encoder,隐含,Theano,theano,hidden
From: https://blog.51cto.com/u_16161414/6481065

相关文章

  • pytest 执行脚本时,报(no name '/Users/**/PycharmProjects/interface_auto/test_case/
    触发场景:pytest执行脚本时,命名全部正确,但是直接报找不到执行函数解决方式:取掉init方法原因:测试框架在运行测试时会自动实例化测试类的对象,并且不会传递任何参数。如果您定义了__init__方法,测试框架将无法实例化您的测试类,从而导致测试无法运行。因此,为了确保测试类能够正......
  • python+uiautomator2判断app是否进入到闪屏广告页面
    前提背景:app内部存在多处广告,需要进行进行自动化:1.查看app是否成功跳转了页面2.页面是否空白3.大致经历的耗时主要思路如下:点击前进行截图操作,点击后进行判断判断图片是否空白defis_blank(image_path,gray_value=250,threshold=0.9):"""函数会计算一幅图像中......
  • PostgreSQL技术大讲堂 - 第18讲:Tuning Autovacuum
     PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUGPG技术大讲堂。Part18:Vacuum空间管理工具内容1:什么是autovacuum?内容2:为什......
  • 学习使用auto定义变量的用法
    学习使用auto定义变量的用法#include<stdio.h>intmain(){inti,num;num=2;for(i=0;i<3;i++){printf("num变量为%d\n",num);num++;{autointnum=1;printf("内置模板num变量:%d\n"......
  • 【论文阅读】Masked Autoencoders Are Scalable Vision Learners
    ......
  • 注入属性Autowire和Qualifier
    @Autowire根据属性类型注入使用:在server包使用注解@server创建对象在dao包使用注解@Repository创建对象在dao包使用注解@Autowire装载server包对象具体实现:在server包创建UserServer类,并加注解@server在dao包创建UserDao接口和UserDaoImpl实现类,在实现类加注解@Repository......
  • 标识列AUTO_INCREMENT
      自增长:AUTO_INCREMENT  ......
  • AUTOSAR笔记:ECU级开发MCAL(六)
    目录MCAL配置工具入门MCAL配置工具安装MCAL配置方法、常用接口函数Mcu模块Gpt模块Port模块Dio模块Adc模块Pwm模块Icu模块Can模块Base与Resource模块MCAL配置验证与代码生成小结MCAL位于AUTOSAR架构最底层,与MCU内部及外设有关。该层作用:接收上层指令,完成对硬件的直接操作;获取硬件......
  • AUTOSAR笔记:工程代码集成与调试(七)
    目录工程代码架构、集成方法代码编译链接代码调试MCU可执行文件下载完成AUTOSAR系统级、ECU级、SWC级相关开发和代码生成后,需要进行代码集成与调试。本文对AUTOSAR工程代码架构、集成、编译链接、调试方法进行简单介绍。工程代码架构、集成方法一套完整的符合AUTOSAR规范的ECU......
  • Autowired注解与Resource注解的区别
    两者的用法其实这两个注解的作用都一样,都是在做bean的注入,在使用过程中,两个注解有时候可以替换使用.两者的共同点@Resource注解和@Autowired注解都可以用作bean的注入.在接口只有一个实现类的时候,两个注解可以互相替换,效果相同.两者的不同点@Resource注解是Java自身......