前言

按照上一个博客所说的,直接按照深度学习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:RD→0,⋯,Lf:R^D\rightarrow {0,\cdots,L}代表预测函数, 那么损失可以被写为

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

    l_{0,1}=\sum_{i=1}^{|D|} I_{f(x^{(i)})\neq y^{(i)}}
    其中II称为示性函数

    Ix={1if x is True0otherwise

    I_x=\begin{cases}1\quad \text{if x is True}\\0 \quad \text{otherwise}\end{cases}
    在本实例中, 预测函数的定义为

    f(x)=argmaxkP(Y=k|x,θ)

    f(x)=\arg \max_k P(Y=k|x,\theta)
    上式的含义就是样本xx在模型参数θ\theta中, 属于每个标签中概率最大的是第kk个标签. 在theano中, 损失函数的实现可以写成:

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

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

    L(\theta,D)=\sum_{i=0}^{|D|}\log P(Y=y^{(i)}|x^{(i)};\theta)
    可以发现这个损失函数的值并非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)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);θ)

    NLL(\theta,D)=-\sum_{i=0}^{|D|}\log P(Y=y^{(i)}|x^{(i)};\theta)
    加了正则项以后可能是这样

    E(θ,D)=NLL(θ,D)+λR(θ)orE(θ,D)=NLL(θ,D)+λ||θ||pp

    E(\theta,D)=NLL(\theta,D)+\lambda R(\theta)\\or \quad E(\theta,D)=NLL(\theta,D)+\lambda||\theta||_p^p
    其中||θ||p=(∑|θ|j=0|θj|p)1p||\theta||_p=\left( \sum_{j=0}^{|\theta|}|\theta_j|^p \right)^\frac{1}{p}, 这就是传说中的pp范数, 当p=2p=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

【theano-windows】学习笔记八——预备知识相关推荐

  1. 知识图谱学习笔记八(知识问答)

    知识问答 知识问答是一个拟人化的智能系统,接收使用自然语言表达的问题,理解用户的意图,获取相关的知识,通过推理计算形成相应的答案并反馈给用户. 知识问答的基本要素 1.问题,也就是问答系统的输入.(问 ...

  2. linux 内核重定位,Linux 内核学习笔记:预备知识之“目标文件”

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 本文主要阐述 Linux 的目标文件(有可重定位目标文件.可执行目标文件和共享目标文件三种形式),并把重点放在其格式和案 ...

  3. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...

  4. C#3.0笔记(一)预备知识之Delegate

    在学习C#3.0之前还是先来回顾下委托.事件,因为这样能更加有助于理解C#3.0里面的一些新的特性,如Lambada表达式等. 背景 在C语言中我们可以用函数指针来创建回调函数,但是在C里面回调函数存 ...

  5. Halcon 学习笔记八:颜色识别

    Halcon 学习笔记八:颜色识别 一.图像处理需要的知识 二.图像处理的预处理和分割过程 二.颜色识别的方法 三.例子一 四.例子二 五.例子三 一.图像处理需要的知识 1.图像处理基础(rgb(h ...

  6. python3第三方库手册_python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑...

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...

  7. 黑马程序员_java自学学习笔记(八)----网络编程

    黑马程序员_java自学学习笔记(八)----网络编程 android培训. java培训.期待与您交流! 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无 ...

  8. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

  9. HTML5学习笔记 —— JavaScript基础知识

    HTML5学习笔记 -- JavaScript基础知识 标签: html5javascriptweb前端 2017-05-11 21:51 883人阅读 评论(0) 收藏 举报 分类: JavaScr ...

最新文章

  1. 编程能力差!90%输在这点上!谷歌AI专家:其实都是瞎努力!
  2. Visual Studio附加到进程调试
  3. 初探swift语言的学习笔记十一(performSelector)
  4. 29 个 PHP 的 Excel 处理类
  5. Linux下修改系统时间的简单方法
  6. 提取数据_Origin如何提取图片数据
  7. 01 springboot 2入门之hello springboot 2(maven构建springboot)
  8. WindowsXP、Windows2003本地密码清除方法
  9. restlet java_restlet(javase版本) 的最基本使用
  10. 《惢客创业日记》2021.02.01(周一)饺子就酒
  11. PS将一张图片裁剪/划分为多块
  12. 正版 Windows 10安装教程
  13. 怀孕期间各个月注意事项
  14. 介绍Zbrush是什么软件
  15. 上海工程技术大学计算机专硕,上海工程技术大学2019年硕士研究生调剂公告
  16. Linux kprobe原理
  17. android M自带铃声壁纸,​Android Q 内置壁纸、铃声,带你提前进入Q时代。
  18. 【最新】正则表达式:识别手机号码,座机号码,400免费电话
  19. 适合入门的一些现成的人工智能项目
  20. 大学生计算机应用与基础,大学生计算机应用基础试题「附答案」

热门文章

  1. gihosoft android 教程,Gihosoft Free Android Data Recovery
  2. javascript html dom,javascript 操作 HTML DOM
  3. mysql文件说明_MySQL进阶之配置文件说明
  4. Codeblocks无法输出中文和中文乱码解决方法(亲测可用)
  5. 面对面交流的好处_我们的交流方式是如何被网络社交媒体一步步改变的
  6. linux java的启动内存溢出,java - Java的R代码可在Linux上运行,但不能在Windows中运行 - 堆栈内存溢出...
  7. AI有道干货 --- 126 篇 AI 原创文章精选(ML、DL、资源、教程)
  8. 基本机器学习面试问题 ---- Company/Industry Specific/Interest
  9. 散列表(哈希表)工作原理 (转)
  10. power bi_如何将Power BI模型的尺寸减少90%!