【theano-windows】学习笔记八——预备知识

前言

按照上一个博客所说的,直接按照深度学习0.1文档进行学习,当然在此之前我们需要了解这一系列教程所需要的数据集,以及一些概念性的东西

国际惯例,参考博客网址:

深度学习0.1文档

深度学习0.1文档-中文翻译

基于梯度的学习

数据集网址

网盘下载链接: https://pan.baidu.com/s/1bpvqwDT 密码: 7c2w

在进行操作前先导入基本的模块

#-*- coding:utf-8 -*-
import cPickle,gzip
import numpy as np
import theano
import theano.tensor as T

数据集简介

就是把Lecun大佬的手写数字数据集MNIST做了个序列化,并且分成了机器学习所需要的三种基本数据集:

  • 训练集: 学习模型参数
  • 验证集: 执行模型选择和超参数的选择
  • 测试集: 测试训练好的模型的分辨能力即泛化能力

下载完数据集以后, 就可以进行读取操作

#导入数据集
f=gzip.open('mnist.pkl.gz','rb')
train_set,valid_set,test_set=cPickle.load(f)
f.close()
#train_set中存储了数据和标签
a,b=train_set
print a.shape#输出数据大小(50000L, 784L)
print b.shape#输出标签大小(50000L,)

为了训练性能着想, 教程建议将数据集存储在共享变量中, 并且通过小批索引的方式获取数据集. 存储到共享变量中的原因与使用GPU有关. 将数据拷贝到GPU内存中需要很大功耗.如果按需拷贝(每次使用到的小批数据), 由于上述所说的功耗问题, GPU的代码运行效率并不会比CPU快, 很可能更慢. 一旦存储在共享变量中, theano就可以在构建共享变量的时候一次性拷贝GPU上所有的数据集. 随后GPU可以通过从共享变量中利用切片来获取小批数据, 无需从CPU内存中拷贝任何信息,因而避免了功耗.

注意由于数据点和它们的标签往往具有不同的本质(标签常是整型的,但是数据尝尝是实值), 因而我们建议对数据和标签采用不同的变量存储, 现将所有的数据存储为float, 然后再将标签用theano.tensor.cast转换为int类型

#最好将数据集放入到共享变量中
def shared_dataset(data_xy):data_x,data_y=data_xyshared_x=theano.shared(np.asarray(data_x,dtype=theano.config.floatX))shared_y=theano.shared(np.asarray(data_y,dtype=theano.config.floatX))return shared_x,T.cast(shared_y,'int32')
train_set_x,train_set_y=shared_dataset(train_set)
test_set_x,test_set_y=shared_dataset(test_set)
valid_set_x,valid_set_y=shared_dataset(valid_set)
batch_size=500
#假装获取第三批数据(批索引是0,1,2,3.....)
data=train_set_x[2*batch_size:3*batch_size]
label=train_set_y[2*batch_size:3*batch_size]

深度学习的监督优化基础

分类器

  • 0-1损失
    目的是最小化没有见过的样本的最小错误量. 如果用f:RD0,,L代表预测函数, 那么损失可以被写为

    l0,1=i=1|D|If(x(i))y(i)

    其中I称为示性函数
    Ix={1if x is True0otherwise

    在本实例中, 预测函数的定义为
    f(x)=argmaxkP(Y=k|x,θ)

    上式的含义就是样本x在模型参数θ中, 属于每个标签中概率最大的是第k个标签. 在theano中, 损失函数的实现可以写成:

    
    #0-1损失zero_one_loss=T.sum(T.neq(T.argmax(p_y_given_x),y))
  • 负对数似然
    可以发现0-1损失是不可微的(它仅仅是不是)的加和. 所以我们看预测函数, 只要使得模型预测出真实标签的概率P(Y=|x(i);θ)最大即可,然后我们通常使用极大对数似然来解决这个最大化问题:

    L(θ,D)=i=0|D|logP(Y=y(i)|x(i);θ)

    可以发现这个损失函数的值并非0-1损失那样带包正确预测的数量, 但是从随机初始化的分类器来看, 它们是非常相似的. 为了跟我们经常说的最小化损失函数保持一致, 可以定义最小化负对数似然(NLL)函数:
    $$ NLL(\theta,D)=-\sum_{i=0}^{|D|}\log P(Y=y^{(i)}|x^{(i)};\theta) $$
    theano`中实现它:

    
    #最小化负对数似然NLL=- T.sum(T.log(p_y_given_x)[T.arange(y.shape[0]),y])

    代码标注: 看大括号里面的[T.arange(y.shape[0]),y], 第一项T.arange(y.shape[0])代表的就是样本索引从0-n, 第二项就是每个样本的标签值.这句话说白了就是从概率矩阵p_y_given_x中取出第i个样本对应的标签为y(i)的概率

随机梯度下降

  • 普通的梯度下降法: 是沿着一些参数所定义的损失函数的误差表面下降一小步, 如此反复不断下降. 训练集是大批量进入损失函数的, 伪代码如下:

    while True:loss = f(params)d_loss_wrt_params = ... # compute gradientparams -= learning_rate * d_loss_wrt_paramsif <stopping condition is met>:return params
  • 随机梯度下降(SGD): 与普通的梯度下降原则上相同, 但是处理速度更快, 因为仅仅从部分样本中估算梯度, 极端情况下就是从一个时间仅仅从一个单一样本中估算梯度

    
    # STOCHASTIC GRADIENT DESCENTfor (x_i,y_i) in training_set:# imagine an infinite generator# that may repeat examples (if there is only a finite training set)loss = f(params, x_i, y_i)d_loss_wrt_params = ... # compute gradientparams -= learning_rate * d_loss_wrt_paramsif <stopping condition is met>:return params

    而在深度学习中, 我们比较建议采用小批量随机梯度下降(Minibatch SGD)方法, 一次采用多于一个的训练样本去计算梯度

    for (x_batch,y_batch) in train_batches:# imagine an infinite generator# that may repeat examplesloss = f(params, x_batch, y_batch)d_loss_wrt_params = ... # compute gradient using theanoparams -= learning_rate * d_loss_wrt_paramsif <stopping condition is met>:return params

    特别注意: 如果你训练固定次数, 批大小的设置对于参数的更新控制是非常重要的. 对批大小为1的数据训练十次与对批大小为20的数据训练十次, 达到的效果完全不同, 记住当改变批大小的时候, 要据此调整其他的参数.

    批量随机梯度下降在theano中实现如下:

    d_loss_wrt_params=T.grad(loss,params)
    updates=[(params,params-learning_rate*d_loss_wrt_params)]
    MSGD=theano.function([x_batch,y_batch],loss,updates=updates)
    for (x_batch,y_batch) in train_batches:print ('Current loss is ',MSGD(x_batch,y_batch))if stopping_condition_is_met:return param

正则项

概念就不说了, 机器学习里面常用的减少过拟合方法, 一般采用L1或者L2正则项. 这里还说到了提前停止(early-stopping)也是正则化的一种方法. 详细请看周志华老师《机器学习》P105页缓解过拟合方法

  • L1和L2正则项
    就是在损失函数后面添加一个额外项, 用于乘法某些参数
    正常情况下, 我们的损失函数是这样

    NLL(θ,D)=i=0|D|logP(Y=y(i)|x(i);θ)

    加了正则项以后可能是这样
    E(θ,D)=NLL(θ,D)+λR(θ)orE(θ,D)=NLL(θ,D)+λ||θ||pp

    其中||θ||p=(|θ|j=0|θj|p)1p, 这就是传说中的p范数, 当p=2的时候就代表二范数, 而且也就是传说中的权重衰减

    原则上来说, 在损失上增加正则项能够增强神经网络的平滑映射(通过乘法参数中较大的值, 减少了网络的非线性程度). 最小化损失函数与正则项的和能够在训练集的拟合与一般解之间找到权衡. 为了遵循奥卡姆剃须刀准则(‘如无必要, 勿增实体’), 它们两个的最小化能够帮助我们找到最简单的解.

    L1  = T.sum(abs(param))#L1范数
    L2 = T.sum(param ** 2)#L2范数
    loss = NLL + lambda_1 * L1 + lambda_2 * L2#损失+L1正则+L2正则
  • 提前停止: 通过观察模型在验证集上的性能来减少过拟合. 如果模型在验证集上停止了提升或者出现退化, 就需要我们停止优化了. 关于何时停止, 这是一个判断, 并且很多启发式算法存在, 这里提供了一个几何增加耐心量的算法:

    
    # 提前停止方法patience = 5000  # 迭代结束条件就看这个值与迭代多少次batch的iter大小
    patience_increase = 2     # 结束时间延长
    improvement_threshold = 0.995  # 小于这个值就认为性能没有被再提升
    validation_frequency = min(n_train_batches, patience/2)#验证频率best_params = None
    best_validation_loss = numpy.inf
    test_score = 0.
    start_time = time.clock()done_looping = False#是否结束循环
    epoch = 0
    while (epoch < n_epochs) and (not done_looping):epoch = epoch + 1#当前迭代次数for minibatch_index in range(n_train_batches):#当前迭代的批索引d_loss_wrt_params = ... # 计算梯度params -= learning_rate * d_loss_wrt_params # 参数更新# 从第0次开始迭代,计算得到当前迭代的累计批索引iter = (epoch - 1) * n_train_batches + minibatch_indexif (iter + 1) % validation_frequency == 0:#使用0-1损失验证性能提升this_validation_loss = ... if this_validation_loss < best_validation_loss:#如果性能还在提升if this_validation_loss < best_validation_loss * improvement_threshold:#如果性能提升超过阈值,那么继续迭代patience = max(patience, iter * patience_increase)best_params = copy.deepcopy(params)best_validation_loss = this_validation_loss#看看是否已经到达迭代终止时间if patience <= iter:done_looping = Truebreak

    这个代码的意思就是迭代结束的条件一是达到了最大的迭代次数n_epoch,另一个就是利用patience控制是否提前结束迭代. 如果迭代过程中性能提升超过阈值, 就考虑将patience提升一下max(patience,iter*patience_increase), 反之性能并未提升或者达到稳定情况(阈值范围之内), 那么就对比当前patience与总共使用批样本训练的次数(每次使用一批样本就将iter+1), 一旦iter超过了patience就停止训练了

    注意: 这个验证频率validation_frequency要比patience小, 至少要在一次patience迭代期间验证过两次.所以使用了 validation_frequency = min( value, patience/2.)

测试

当循环完毕, 得到的参数是验证集上效果最好的参数. 这样我们使用同一个训练集、测试集、验证集去训练多个模型, 我们比较每个模型最好的验证集损失, 就认为我们选择了最好的模型.

简单总结

三个数据集: 训练集、验证集、测试集

优化方法: 训练集被用于目标函数的可微近似的批量随机梯度下降中

选择模型: 看模型在验证集上的性能能表现

存储和读取模型参数

  • 存储模型参数

    save_file = open('path', 'wb')
    cPickle.dump(w.get_value(borrow=True), save_file, -1)
    cPickle.dump(v.get_value(borrow=True), save_file, -1)
    cPickle.dump(u.get_value(borrow=True), save_file, -1)
    save_file.close()
  • 读取模型参数

    save_file = open('path')
    w.set_value(cPickle.load(save_file), borrow=True)
    v.set_value(cPickle.load(save_file), borrow=True)
    u.set_value(cPickle.load(save_file), borrow=True)

    关于borrow看这里, 大概就是如果borrow=True, 那么对原始变量的更改会对当前的共享变量产生影响, 还是把例子贴出来吧

    import numpy, theano
    np_array = numpy.ones(2, dtype='float32')s_default = theano.shared(np_array)
    s_false   = theano.shared(np_array, borrow=False)
    s_true    = theano.shared(np_array, borrow=True)
    np_array += 1 # now it is an array of 2.0 sprint(s_default.get_value())
    print(s_false.get_value())
    print(s_true.get_value())
    '''
    [ 1.  1.]
    [ 1.  1.]
    [ 2.  2.]
    '''

    【注】我可能用了假theano, 这个例子在我的环境中执行竟然结果都是[1,1]

后续

数据集和一些基本的训练方法都搞定了, 下一步就得实战一波了

  • logistic回归分类手写数字
  • 多层感知器
  • 卷积
  • 去噪自编码dAE
  • 堆叠去噪自编码SdAE
  • 受限玻尔兹曼机RBM
  • 深度信念网
  • 混合蒙特卡洛采样
  • LSTM
  • RNN-RBM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【theano-windows】学习笔记九——softmax手写数字分类

前言 上一篇博客折腾了数据集的预备知识, 接下来按照官方的Deep learning 0.1 documentation一步步走, 先折腾softmax, 关于softmax和logistic回归分类的联系, 我在之前写过一个小博客 国际惯例, 参考博客走一波: Classifying MNIST digits using Logistic Regression soft…

【theano-windows】学习笔记十——多层感知机手写数字分类

前言 上一篇学习了softmax, 然后更进一步就是学习一下基本的多层感知机(MLP)了. 其实多层感知机同时就是w*xb用某个激活函数激活一下, 得到的结果作为下一层神经元的输入x, 类似于 output⋯f3(f2(f1(x∗w1b2)∗w2b2)∗w3b3)⋯output=\cdots f^3(f^2(f^1(x*w^1+b^2)*w^2+b^2)*…

【theano-windows】学习笔记十一——theano中与神经网络相关函数

前言 经过softmax和MLP的学习, 我们发现thenao.tensor中除了之前的博客【theano-windows】学习笔记五——theano中张量部分函数提到的张量的定义和基本运算外, 还有一个方法称为nnet, 如果自己实现过前面两篇博客中的代码就会发现用到了theano.tensor.nnet.sigmoid和thenao.te…

【caffe-windows】全卷积网络特征图分析

前言 突然就想分析一下全卷积网络的转置卷积部分了, 就是这么猝不及防的想法, 而且这个网络对图片的输入大小无要求&#xff0c;这么神奇的网络是时候分析一波了&#xff0c;我个人的学习方法调试代码&#xff0c;然后对照论文看理论 本次分析主要针对每层的权重大小和特征图…

【theano-windows】学习笔记十二——卷积神经网络

前言 按照进度, 学习theano中的卷积操作 国际惯例, 来一波参考网址 Convolutional Neural Networks (LeNet) 卷积神经网络如何应用在彩色图像上&#xff1f; 卷积小知识 三大特性&#xff1a;局部感知(稀疏连接), 权值共享, 池化 上图很重要, 描述的是前一个隐层m-1具有四…

【theano-windows】学习笔记十三——去噪自编码器

前言 上一章节学习了卷积的写法,主要注意的是其实现在theano.tensor.nnet和theano.sandbox.cuda.dnn中都有对应函数实现, 这一节就进入到无监督或者称为半监督的网络构建中. 首先是自编码器(Autoencoders)和降噪自编码器(denoising Autoencoders) 国际惯例, 参考网址: Denoi…

梯度优化算法Adam

前言 最近读一个代码发现用了一个梯度更新方法, 刚开始还以为是什么奇奇怪怪的梯度下降法, 最后分析一下是用一阶梯度及其二次幂做的梯度更新。网上搜了一下, 果然就是称为Adam的梯度更新算法, 全称是:自适应矩估计(adaptive moment estimation) 国际惯例, 参考博文: 一文看…

读写bin

前言 工程中经常将参数文件存储为bin格式, 但是实际中为了分析其参数, 也不好用C去读取调试它, 所以可以用matlab或者python去读取它, 但是还是蛮坑的 Matlab中的读取和写入 写入文件 比较坑的是, 一定要注意自己的文件存储的类型, 比如数值是float还是double之类的, 不然很…

【theano-windows】学习笔记十四——堆叠去噪自编码器

前言 前面已经学习了softmax,多层感知器,CNN&#xff0c;AE&#xff0c;dAE&#xff0c;接下来可以仿照多层感知器的方法去堆叠自编码器 国际惯例&#xff0c;参考文献&#xff1a; Stacked Denoising Autoencoders (SdA) Greedy Layer-Wise Training of Deep Networks 理…

【theano-windows】学习笔记十五——受限玻尔兹曼机

前言 终于到了最喜欢的模型: 受限玻尔兹曼机(RBM)了, 发现关于RBM是如何从能量模型发展过来的介绍非常不错, 而关于详细理论证明, 可以去看我前面的受限玻尔兹曼机的一系列博客. 国际惯例, 参考博客,超级强推第二个博客, 证明过程很给力: Restricted Boltzmann Machines (R…

【Ogre-windows】环境配置

前言 由于工程原因, 学习一下Ogre面向对象图形渲染开源引擎, 慢慢爬坑吧。首先还是环境的配置问题哎. 其实最重要的是要预先编译三方库, 虽然官方说可以自动编译, 但是在自己电脑上还是出现了无法解析外部符号之类的问题, 正常情况下我就认为是三方库的lib出现了问题, 最后额外…

【theano-windows】学习笔记十六——深度信念网络DBN

前言 前面学习了受限玻尔兹曼机(RBM)的理论和搭建方法, 如果稍微了解过的人, 肯定知道利用RBM可以堆叠构成深度信念网络(deep belief network, DBN)和深度玻尔兹曼机(deep Boltzmann machine), 这里就先学习一下DBN. 国际惯例, 参考博文: Deep Belief Networks A fast lear…

【theano-windows】学习笔记十七——梯度中的consider_constant

前言 主要是在写玻尔兹曼机相关的theano时, 在计算梯度grad的时候发现一个参数名字叫做consider_constant,来看看这个到底做了什么事情 参考博客: using consider_constant selectively 【theano-windows】学习笔记三——theano中的导数 理论 其实就是数学中求导中用到的…

【Ogre-windows】实例配置

前言 折腾了好久才搞定教程实例, 主要是因为上一篇博客安装的具体版本是Ogre1.10.9, 而官方的Ogre Wiki Tutorial Framework没有指定具体版本, 如果单纯下载Ogre Wiki Tutorial Framework 1.10 - (Windows line endings, updated 2015-10-15) 运行, 基本会血崩. 所以, 在经过仔…

【Ogre-windows】旋转矩阵及位置解析

前言 这篇博客主要针对三种问题 如何创建动画帧如何获取全局位置如何计算全局旋转矩阵 仿真环境为VS2013Ogre1.10.9与matlab验证 创建动画帧 这里只做一个简单的实验: 将自带的人物模型Jaiqua的run运动给新创建的运动myrun中并播放&#xff0c;直接贴代码了 void JaiQua:…

矩阵求导与BP的证明的建议

前言 在有些博客推导神经网络的BP时&#xff0c;涉及到多次矩阵求导运算&#xff0c;尤其是反向传播时候&#xff0c;求的梯度结果被转置了&#xff0c;比如假设最后一层的输出为 yσ(w⋅xb)y=\sigma\left(w\cdot x+b \right)\\那么 ∂y∂w∂y∂xσ′(w⋅xb)⋅xTσ′(w⋅xb)⋅…

BP推导——续

前言 之前有证明过一次人工神经网络——【BP】反向传播算法证明 &#xff0c;但是回头看的时候&#xff0c;有很多地方非常不严谨&#xff0c;特此拿出来再单独证明一次BP&#xff0c;并严格保证其严谨性。如果想看看粗略的证明&#xff0c;可以去看我之前的博客&#xff0c;毕…

CNN反向传播卷积核翻转

前言 前面煞费苦心地严格按照上下标证明BP&#xff0c;主要就是为了锻炼自己的证明时候的严谨性&#xff0c;那么这里也严格按照上下标的计算方法推导为何卷积的反向传播需要将卷积核旋转180 粗略证明 回顾一下BP的第l层第i个偏置的更新 ∂E∂bli∑j(δl1jWl1ji)σ′(zli)\…

matlab学习——强连通分量

前言 最近motion graph相关实验&#xff0c;发现实现运动过渡需要构建运动图&#xff0c;而为了避免运动过渡陷入死胡同&#xff0c;需要对图结构进行裁剪&#xff0c;方法就是计算图模型的极大强联通分量&#xff0c;但是自己懒得去实现&#xff0c;所以就去搜了一下matlab中…

【theano-windows】学习笔记十八——混合蒙特卡洛采样

#前言 继续之前的Theano学习&#xff0c;本次主要学习混合蒙特卡洛(Hybrid Monte-Carlo Sampling)采样算法。 国际惯例&#xff0c;参考网址 Hybrid Monte-Carlo Sampling Hybrid Monte Carlo #理论 能量模型所使用的极大似然学习需要鲁棒的算法进行反向阶段的采样。比如…