Theano介绍及简单应用

一、课程介绍

1.课程说明

本次课程主要是为引导大家入门几个常用的深度学习框架。在课程中有关各种算法的详细推导及思想我们不会做过多的陈诉,旨在通过让同学们动手操作搭建自己的神经网络模型,了解如何使用这些框架解决实际问题。

课程中我们会基于每个框架的官方文档,先带大家熟悉框架中基本的定义语法及常用函数(可看成深度模型的小零件),每个实验最后都会综合这些零件搭建一个简易的神经深度网络模型。学习过程中有问题可随时指出。

2.深度学习概念

深度学习 (deep learning):深度学习是机器学习中的一个分支,试图通过具有多个处理层的计算模型对数据进行多层抽象。这个抽象的结果即是数据一种表达,而深度学习也可看成表达学习(表征学习)的一种方法,深度学习的好处是用无监督式 Unsupervised或半监督式 Semi-supervised的特征学习和分层特征提取高效算法来替代手工获取数据特征。

简单来说,深度学习可以理解为具有很多层(>2)的人工神经网络模型算法,神经网络的构建其实也可以看成一个点-线-面的构造过程。:即神经网络里许多计算节点(在神经网络里,称为神经元 Cell),线:由一些节点再构成一层处理层(这一层就可以理解为对数据的某个抽象表达),:由多个处理层构建起来就形成了一个神经网络。

再由点(神经元,Cell)不同,或是这些点的连接方式不同就可以形成各种各样的不同的表达模型。如下图所示,我们可以看到许多种神经网络结构,例如:Deep Feed Forward深度前向传播网络Recurrent Neural Network(RNN)递归神经网络Long/Short Term Memory(LSTM)长短期记忆神经网络

图片来自:THE ASIMOV INSTITUTE

3.本节内容

本次实验所包含的实验流程如下:

  1. Theano介绍及安装
  2. Theano基本使用
  3. Theano实现stacked Autoencoder(栈式自编码器)

4.实验相关知识点

在后续的课程中,需要预先有了解的知识点:

  • Tensor: 张量,经典的方法把张量视为多维数组,它们是标量,1维向量和2维矩阵的n维推广。张量的"分量"是数组中的值。 这个思想可以进一步推广到张量场,那里张量的元素是函数,甚至微分。 —— 引自维基百科
  • GPU:graphics processing unit,图形处理器

  • Numpy:python中有关数值计算的库

    • Matrix conventions (矩阵约定) for machine learning :矩阵中的每行都是一个例子。如 一个10行5列的矩阵inputs[10,5], 代表着10个5维的实例。

    • Broadcasting: Numpy进行数值运算时广播不同维度的矩阵。如,当一个较小的矩阵a(1*21∗2维)与一个较大的矩阵b( 2*32∗3 维)进行加法运算时,numpy会将矩阵a广播为与矩阵b兼容的矩阵维度,再进行运算。也可通过下图帮助理解。

二、Theano介绍及安装

Theano是一个较为老牌和稳定的机器学习python库之一。Theano基于Python擅长处理多维数组(紧密集成了Numpy),属于比较底层的框架,theano起初也是为了深度学习中大规模人工神经网络算法的运算所设计,我们可利用符号化式语言定义想要的结果,接着theano会对我们的程序进行编译,使其高效运行于GPU或CPU。

从Theano官方文档的欢迎页面上,我们可以看到其对Theano的特征介绍:

  • tight integration with Numpy (紧密集成Numpy) —— 在Theano编译函数中使用numpy.ndarray
  • transparent use of a GPU (GPU的透明使用) —— 使得其对浮点数的运输非常高速
  • efficient symbolic differentiation (高效的符号分解) —— 也是Theano的发明初衷之一,可帮我们推导我们所定义的一个或多个输入的函数
  • speed and stability optimizations (快速且稳定的优化) —— 在函数表达式$log(1+x)$中即使$x$非常小,也可以给出精确的答案
  • dynamic C code generation (动态生成C代码) —— 使得表达式求值(evaluate expression)更加快速
  • extensive unit-testing and self-verification (大量的单元测试及自我验证) —— 可检测及诊断许多类型的错误

在Installing Theano中可查看在各种系统上安装Theano的教程。这里我们将展示在实验楼的ubantu14.04环境的安装过程:

# 1. 先使用apt-get update命令进行更新,避免安装Python库时出现问题
$ sudo apt-get update# 2. 接着安装在安装theano前需安装的Python库
$ sudo apt-get install python-numpy python-scipy python-matplotlib  python-dev python-pip python-nose python-tk g++ libopenblas-dev git# 3. 接着第三步便是使用pip命令安装theano
$ sudo pip install theano

三、Theano基本使用

3.1 Theano的基本运算及符号表达

通过python进入Python终端中,先导入theano的相关模块以便后续操作:

>>> import theano
>>> import theano.tensor as T
>>> from theano.tensor import *
>>> from theano import shared
>>> import numpy as np

基本的张量功能:

Theano 支持Python中任何类型的对象,但它的核心是其支持符号矩阵表达式,如下例中:

>>> x = T.fmatrix()

x是一个TensorVariable张量变量的实例,T.fmatrix对象本身也是TensorType张量类型的一个实例。

Creation创造张量实例

Theano提供了一列预先定义好的张量类型可供使用者很方便地创造张量变量,所有的张量构造函数都接收一个 可选 的输入参数name。如以下便构造了三个以myvar为名字的 0维整型标量(scalar)变量

>>> x = T.scalar('myvar', dtype='int32')
>>> x = iscalar('myvar')
>>> x = TensorType(dtype='int32', broadcastable=())('myvar')

还可以通过vectorrowcolmatrixtensor3tensor4分别构造向量、行向量、列向量、矩阵、三维张量及四维张量。

我们还可以通过以下方式创造张量类型实例

# 创造一个双精度浮点类型的无名矩阵
>>> x = dmatrix()
# 创造了一个双精度浮点类型的名为'x'的矩阵
>>> x = dmatrix('x')
# 创造了一个双精度浮点类型的名为'xyz'矩阵
>>> xyz = dmatrix('xyz')

Plural Constructor 多输出构造函数

Plural Constructor可以同时构造多个变量,以下便是Theano提供的多输出构造函数,其实就是intlong, floatdouble数据类型与标量scalars, 向量vectors行向量rows, 列向量cols矩阵matrices的组合:

  • 返回一个或多个标量:iscalars, lscalars, fscalars, dscalars
  • 返回一个或多个向量:ivectors, lvectors, fvectors, dvectors
  • 返回一个或多个行变量:irows, lrows , frows, drows
  • 返回一个或多个列变量:icols, lcols, fcols, dcols
  • 返回一个或多个矩阵: imatrices, lmatrices, fmatrices, dmatrices

举一个'栗子':

# 构造三个无名双精度浮点类型矩阵
>>> x, y, z = dmatrices(3)
# 构造三个分别名为'x','y','z'的double类型矩阵
>>> x, y, z = dmatrices('x', 'y', 'z')

依次类推,Theano中还有其他的张量类型,除前边的章节介绍外的还有字节型byte,字型word和复数型complex的数据形成的张量。

自定义张量类型

如果上述所提供的构造函数不能构造出你想要的张量时,你可以自定义自己的张量类型TensorType。比如,构造一个5维张量:

>>> dtensor5 = TensorType('float64', (False,)*5)
>>> x = dtensor5()
>>> z = dtensor5('z')

也可以重定义已经提供的张量构造函数。如重构一个 双精度浮点类型矩阵:

>>> my_dmatrix = TensorType('float64', (False,)*2)
>>> x = my_dmatrix() #构造一个无名2维矩阵实例
## 判断自定义的张量类型是否与theano库所提供的构造函数一致
>>> my_dmatrix == dmatrix

3.2 Theano中的线性运算

在进行线性运算前,先从theano中导入一个新的函数function:

>>> from theano import function

使用Theano进行线性运算过程就跟把大象放进冰箱的步骤差不多:

  1. 打开冰箱——定义好需要进行运算的张量变量
  2. 把大象放进冰箱——利用已定义的张量书写你的表达式
  3. 关上冰箱——将表达式转化为可执行的python函数

基于以上三个步骤我们实现两个张量的加运算:

# 1. 定义变量,可以是3.1节介绍的张量类型中的任一种,这里我定义的是double scalar双精度标量
>>> x = T.dscalar('x')
>>> y = T.dscalar('y')
# 或者你可以直接同时定义这两个变量
>>> x, y = T.dscalars('x', 'y')
# 2. 表达式
>>> z = x + y
# 3. 将表达式转化为可执行的python函数
>>> f = function([x, y], z)

第3个步骤中的function函数,其接受的第一个参数类型为 a list of Variables 一组输入变量 ,将作为转化后的python函数f的输入,第二个参数类型为 a single Variable or a list of variables一个或一组变量,将作为函数f的输出。

接下来我们就可以使用函数f进行表达式运算

>>> f(2.33, 6.66)

如果你想在函数f中只个一个输入,而执行加运算。那么可以设置其中一个变量有缺省值 Default Value

>>> from theano import In
>>> f = function([x, In(y, value=1)], z)
# In理解为Instance实例
>>> f(1.33)

还有些时候,我们会在许多函数间用到同一个变量值,那么此时我们可以定义一个共享变量(shared Variable), 共享变量由使用其计算的函数所共享,可通过shared_constructor()构造,可通过get_valueset_value函数分别获得和改变共享变量的值。

>>> np_array = np.zeros(2, dtype='float32')
# 创建共享变量
>>> shared_default = shared(np_array)
>>> shared_false = shared(np_array, borrow=False)
>>> shared_true = shared(np_array, borrow=True)

shared函数中的参数borrow的含义是,变量np_array在函数中被使用时所创建共享变量shared_xxx,在np_array的值发生改变时共享变量是否要跟着发生变化,同学们可通过运行下边的代码获得答案:

>>> np_array += 1 #在数组np_array[0, 0]的值上加1>>> shared_default.get_value()
>>> shared_false.get_value()
>>> shared_true.get_value()

3.3 练习

经过上边的介绍,我们来实现以下表达式:

  1. 向量x的表达式x+x^{10}x+x​10​​
  2. 矩阵x的表达式 s(x)=\frac{1}{1+e^{-x}}s(x)=​1+e​−x​​​​1​​
  3. 基于表达式2实现s(x)s(x)的导数形式
# 表达式1
>>> x = T.vector()
>>> y = x + x ** 10
>>> f = function([x], y)
>>> f([0, 1, 2])

# 表达式2
>>> x = T.dmatrix('x')
>>> s = 1 / (1 + T.exp(-x))
>>> logistic = function([x], s)
>>> logistic([[0 , 1], [-1, -2]])

#表达式3
>>> s = T.sum(1 / (1 + T.exp(-x)))
>>> gradS = T.grad(s, x)
>>> dLogistic = function([x], gradS)
>>> dLogistic([[0, 1], [-1, -2]])

结束之后,利用Ctrl + D退出python终端

四、Theano实现自编码器

本节我们将利用theano实现第一节的关于人工神经网络附图中的自编码器(AutoEncoder, AE):

上图中的自编码器为最简单的三层‘深度’神经网络,在实验楼的课程基于无监督学习的自编码器实现中,我们已经对自编码器解释得比较详细,这里不做过多解释,直接动手做实验:

4.1定义自编码器类

创建AE_code.py文件,在其中定义自编码器类方便我们在之后时使用这个三层前向传播神经网络,对我们给定的数据进行自编码器的训练。

  1. 导入相关的python模块:
# -*- coding: utf-8 -*-
import numpy as np
import theano as th
from theano import tensor as T
from numpy import random as rng
  1. 创建AutoEncoder类:
class AutoEncoder(object):# 在初始化函数中定义自编码器的参数def __init__(self, data, hidden_size, actFun, outFun):self.data = dataself.data = th.shared(name='data', value=np.asarray(self.data, dtype=th.config.floatX),                             borrow=True)self.nIns = data.shape[0]self.nFeatures = data.shape[1]self.hidden_size = hidden_size# W初始值的取值范围,在一个固定范围中取均匀分布的随机值raw_W = np.asarray(random.uniform(low = -4 * np.sqrt(6. / (self.hidden_size + self.nFeatures)),high = 4 * np.sqrt(6. / (self.hidden_size + self.nFeatures)),size=(self.nFeatures, self.hidden_size)), dtype=th.config.floatX)self.W = th.shared(value=raw_W, name='W', borrow=True)# 隐含层的偏置向量self.b1 = th.shared(name='b1', value=np.zeros(shape=(self.hidden_size,),dtype=th.config.floatX), borrow=True)# 输出层的偏置向量self.b2 = th.shared(name='b2', value= np.zeros(shape=(self.nFeatures,),dtype=th.config.floatX), borrow=True)self.actFun = actFunself.outFun = outFun

通过上边的代码可知,在自编码器的权值初始化时是在区间[low, high]上取得,其中low和high的值分别为:

low = - 4 * \sqrt{\frac{6}{n_{hidden}+n_{visible}}}low=−4∗√​​n​hidden​​+n​visible​​​​6​​​​​

high = 4 * \sqrt{\frac{6}{n_{hidden}+n_{visible}}}high=4∗√​​n​hidden​​+n​visible​​​​6​​​​​

而自编码器的隐含层和输出层的偏置都设置为零向量

  1. 自编码器的训练
# 定义自编码器的训练函数
# 训练时的参数在这里有默认设置值,在实际调用时可根据输入数据进行修改def train(self, n_epochs=100, mini_batch_size=10, learning_rate=0.1):index = T.lscalar()x = T.matrix('x')params = [self.W, self.b1, self.b2]hidden = self.actFun(T.dot(x, self.W) + self.b1)output = T.dot(hidden, T.transpose(self.W)) + self.b2output = self.outFun(output)# cross-entropy lossL = -T.sum(x * T.log(output) + (1 - x) * T.log(1 - output), axis=1)cost = L.mean()updates = []# gradient with respect to W, b1, b2gparams = T.grad(cost, params)for param, gparam in zip(params, gparams):updates.append((param, param - learning_rate * gparam))# training given a mini-batch of the datatrain = th.function(inputs=[index], outputs=[cost], updates=updates,givens={x: self.data[index:index + mini_batch_size, :]})import timestart_time = time.clock()for epoch in xrange(n_epochs):print "Epoch:", epochfor row in xrange(0, self.nIns, mini_batch_size):train(row)end_time = time.clock()print "Average time per epoch=", (end_time - start_time) /n_epochs
  1. 定义自编码器输出结果的获取
                def get_output(self, data):W = self.W.get_value()b1 = self.b1.get_value()b2 = self.b2.get_value()x = T.dmatrix('x')hidden = self.actFun(T.dot(x, W) + b1)output = T.dot(hidden, W.T) + b2output = self.outFun(output)ae_output = th.function(inputs=[x], outputs=[output])return ae_output(data)

4.2 调用自编码器类训练minist手写体的自编码网络

本次实验所用的数据集,与我们在课程基于无监督学习的自编码器实现所用的数据集一样,为方便大家在实验楼的在线环境中进行实验,在minist数据集中选用一部分并且已经读入到trainData.mat文件中,节省文件读取的时间。

trainData.mat可通过wget命令从以下地址获得:

wget http://labfile.oss.aliyuncs.com/courses/696/trainData.mat

实验代码部分:

import matplotlib.pyplot as plt
def main():trainData = scio.loadmat('trainData.mat')inputData = trainData['trainData'].TinputData = inputData[:,:] / 255.activation_function = T.nnet.sigmoidoutput_function = activation_functionA = AutoEncoder(inputData, 200, activation_function, output_function)# 训练自编码器,只训练一个epoch,在训练过程中每次只通过一张图片进行权值改进A.train(1, 1)# 训练集中每个数字有对应50张训练图片eachDigitNum = 50showIndex = range(0, inputData.shape[0], eachDigitNum)# Autoencoder类中的get_output函数返回的是一个list# 因此需通过下标0,将list中的结果矩阵读出output = A.get_output(inputData[showIndex, :])[0]# 展示原始图片及自编码器输出结果for iImg in xrange(10):ax = plt.subplot(2, 10, iImg + 1 )plt.imshow(inputData[showIndex[iImg],:].reshape(28, 28).T, cmap= plt.cm.gray)ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(2, 10, iImg + 11 )plt.imshow(output[iImg, :].reshape(28, 28).T, cmap=plt.cm.gray)ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)plt.show()if __name__ == '__main__':main()

最终通过命令行运行AE_code.py文件,查看自编码训练结果

python AE_code.py

程序运行结果截图:

五、总结

通过本次课程,我们学习了Theano中的基本使用方法,了解了Theano的一些基本特性及不同的数据类型。通过实验了解常用的数据符号定义方法,及如何通过theano实现数据表达式。本节实验最后我们Theano实现了一个三层FeedForward network 前馈网络Theano还可实现许多人工神经网络,同学们可自己动手实现。

本次课程的所有源码,可通过以下命令获得:

wget http://labfile.oss.aliyuncs.com/courses/744/AE_code.py

六、参考阅读

  • 利用Theano理解深度学习——多层感知机
  • 利用Theano理解深度学习——自编码器实现
  • 深度学习算法实践——用Theano实现多层前馈网络

七、本节习题

在本次实验中,我们实现了Autoencoder类中的get_output函数,来查看自编码器的输出结果。同学们可通过动手自定义get_hidden函数,获得编码hidden层的编码结果,并在main函数中调用查看网络训练结束后的对每个图片的编码情况。

Theano介绍及简单应用相关推荐

  1. Matplotlib的介绍及简单操作

    Matplotlib的介绍及简单操作 1 什么是Matplotlib 是专门用于开发2D图表(包括3D图表) 以渐进.交互式方式实现数据可视化 2 为什么要学习Matplotlib 可视化是在整个数据 ...

  2. (三)AJAX基本介绍和简单实例03

    (三)AJAX基本介绍和简单实例03-----Ajax与数据库的动态应用 前台显示界面: 选择所有客户之后: 选择其中一个客户---杜森: Demo03.html代码 <html> < ...

  3. rabbitMQ消息队列 – 面板介绍及简单demo

    首先rabbit安装好之后,运维会给一个控制面板. 默认账号密码为guest 登入以后可以看到具体界面. 在此鸣谢百度翻译给予的大力支持.. ###写一个简单的demo 编写之前..虽然说可以直接用底 ...

  4. Protobuf介绍及简单使用(上)

    目录 Protobuf 介绍 优势 protobuf语法 Specifying Field Rules Data type Data name Number Protobuf注释 保留字段与标识符 s ...

  5. SQL Server中追踪器Trace的介绍和简单使用

    原文:SQL Server中追踪器Trace的介绍和简单使用 一.What is Trace? 对于SQL Profiler这个工具相信大家都不是很陌生,没用过的朋友可以在SQL Server Man ...

  6. S3C2440移植linux3.4.2内核之内核框架介绍及简单修改

    文章目录 uboot启动内核分析 简单配置内核 编译内核 设置机器ID 修改晶振 移植Linux3.4.2内核其他文章链接: S3C2440移植linux3.4.2内核之内核框架介绍及简单修改 S3C ...

  7. 新颖的自我介绍_简单新颖的自我介绍范文

    简单新颖的自我介绍范文 简单新颖的自我介绍范文1 各位考官好,今天能够站在这里参加面试,有机会向各位考官请教和学习,我感到非常的荣幸.希望通过这次面试能够把自己展示给大家,希望大家记住我.我叫.... ...

  8. Quartz框架实现定时任务介绍及简单使用

    https://blog.csdn.net/bicheng4769/article/details/81097305 Quartz框架介绍及简单使用 https://www.cnblogs.com/d ...

  9. Hive第一天——Hive介绍以及简单使用

    Hive第二天--Hive介绍以及简单使用 自己的话:黑发不知勤学早,白首方悔读书迟 每天都要保持前进! 一.什么是Hive 数据库: mysql.oracle.sqlserver.DB2.sqlit ...

  10. Helm模板常用语法介绍与简单应用场景

    Helm模板常用语法介绍与简单应用场景 文章目录 Helm模板常用语法介绍与简单应用场景 什么是Helm _help.tpl子模版 应用场景 预定义对象 关于变量 关键字及应用 函数 流程与控制 什么 ...

最新文章

  1. 在CentOS上把MySQL从5.5升级到5.6
  2. 设计模式03------单例模式
  3. Python 技术篇-pip安装提示:‘pip‘ 不是内部或外部命令,也不是可运行的程序或批处理文件,问题解决方法
  4. contiki源码阅读之list
  5. Win7下硬盘安装Ubuntu10.10双系统
  6. FastCgi与PHP-fpm之间的关系
  7. Django框架下报的版本问题
  8. 洛谷树剖模板题 P3384 | 树链剖分
  9. python的itertools库_Python标准库itertools模块使用方法
  10. PyQt教程 - pythonQt的安装和配置及版本间差异
  11. android核心基础(5)_Android)java虚拟机和Dalvik虚拟机的区别
  12. dapper--查询超时时间
  13. mysql数据狛聘_.net 生成拼音码与五笔码实例代码
  14. 基于阿里天池的淘宝用户行为分析
  15. MaNGOS工程概介
  16. SAP AFS ARUN分货操作只争对销售订单行项目上的库存地进行
  17. 【Java】所有做过的面试题
  18. 0x00007FFE81272FE1 (ucrtbased.dll) (Project1.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x0000000000000000 时发
  19. linux安全配置技术论文,基于linux平台的web安全技术研究apache安全大学论文.doc
  20. 【杂篇 · 电脑】买Macbook之后的一些记录

热门文章

  1. rational rose 启动选择_Rational Rose 附使用教程
  2. HP5100常见错误代码
  3. git制作patch补丁
  4. css实现div半透明而文字不透明
  5. python 风玫瑰图_【求助】风玫瑰图
  6. 十六进制转二进制原理
  7. 最近发现一款超牛的记单词软件,分享一下
  8. Eclipse连接SQLServer2008
  9. 【个人总结版】实验报告书写指导
  10. GoldenDict音标乱码