Theano官方文档的测试和总结(1):安装、基础语法、逻辑斯蒂回归

Theano深度学习库入门
本文详细介绍Theano深度学习库的使用,包括安装、基础语法、函数对象操作及实战案例。Theano支持GPU加速,能优化数学表达式计算,特别适合多维数组处理。

http://deeplearning.net/software/theano/NEWS.html

1. Theano的简介和安装

1.1 Theano简介

发布版本:Theano 1.0.0 (15th of November, 2017)
Theano是一个让你去定义,优化,计算数学表达式,特别是多维数组(numpy.ndarray)的Python包。具有速度快的特点,支持GPU。Theano结合了计算机代数系统(computer algebra system ,CAS) 的特征和优化编译器的功能。

牛刀小试:

import theano
from theano import tensor

# declare two symbolic floating-point scalars
a = tensor.dscalar()
b = tensor.dscalar()

# create a simple expression
c = a + b

# convert the expression into a callable object that takes (a,b)
# values as input and computes a value for c
f = theano.function([a,b], c)

# bind 1.5 to 'a', 2.5 to 'b', and evaluate 'c'
assert 4.0 == f(1.5, 2.5)  #检查条件,不符合就终止程序
print 4.0 == f(1.5, 2.5)    #输出Ture

theano.function可以被视为一个从纯符号图构建可调用对象的编译器接口。Theano最重要的特征之一是theano.function能够优化图,甚至能够将图的一部分或者全部编译成简单的机器指令。

1.2 Theano安装

不同平台的安装方式不同,详情参考http://deeplearning.net/software/theano/install.html#install

2 基础语法

让我们开始一个交互式进程(使用python或者ipython), 然后倒入Theano。

from theano import *

Theano包的tensor模块比较常用,可以导入为T

import theano.tensor as T

在整个教程中,记住在每个页面的右上角都有术语表(Glossary),索引和模块链接来帮助你。
Prerequisites: Python和NumPy

2.1 蹒跚学步–代数学

两个标量(Scalars)相加

>>> import numpy
>>> import theano.tensor as T
>>> from theano import function
>>> x = T.dscalar('x')
>>> y = T.dscalar('y')
>>> z = x + y
>>> f = function([x, y], z)

现在,我们已经创建了函数,让我们来用它们。

>>> f(2, 3)
array(5.0)
>>> numpy.allclose(f(16.3, 12.1), 28.4)
True

Step 1: T.dscalary用来指定变量的类型为 “0-dimensional arrays (scalar) of doubles (d)”。 可用type查看变量类型。Theano’s inner structure参考 Graph Structures.
Step 2: z变量代表着x和y的和,可以使用pp函数打印出与z相关的计算。
Step 3: 创建一个把x,y作为输入,z作为输出的函数。也可以使用eval(串演算指令)方法,传入一个字典,返回表达式的数值。

两个矩阵(Matrices)相加

>>> x = T.dmatrix('x')
>>> y = T.dmatrix('y')
>>> z = x + y
>>> f = function([x, y], z)
>>> f([[1, 2], [3, 4]], [[10, 20], [30, 40]])
array([[ 11.,  22.],
       [ 33.,  44.]])

dmatrix是double矩阵类型。该变量是NumPy array类型,我们也可以直接用NumPy arrays作为输入。
矩阵和标量,矩阵和向量,标量和向量的运算参考 broadcasting
变量类型,可参考 tensor creation

2.2 熟悉 Theano的函数对象和操作
2.2.1 Basic Tensor Functionality

Basic Tensor Functionality
①创建浮点型矩阵:x = T.fmatrix()
②变量可接受一个name。
③不同数据类型的构造函数
④各种类型的构造函数
⑤复数形式的构造函数Plural Constructors
⑥自定义tensor类型
⑦转化Python对象, 调用shared()
⑧略略略

2.2.2 Logistic Function

在这里插入图片描述
在这里插入图片描述
可以使用elementwise来计算double型的矩阵,其意思是将每个独立的元素应用于矩阵。

>>> import theano
>>> import theano.tensor as T
>>> x = T.dmatrix('x')
>>> s = 1 / (1 + T.exp(-x))
>>> logistic = theano.function([x], s)
>>> logistic([[0, 1], [-1, -2]])
array([[ 0.5       ,  0.73105858],
       [ 0.26894142,  0.11920292]])

logistics能够使用elementwise是因为它的所有操作都是加减乘除,是elementwise操作符。logistics函数还可以改写为如下形式:
在这里插入图片描述
再次确认这个改变:

>>> s2 = (1 + T.tanh(x / 2)) / 2
>>> logistic2 = theano.function([x], s2)
>>> logistic2([[0, 1], [-1, -2]])
array([[ 0.5       ,  0.73105858],
       [ 0.26894142,  0.11920292]])
2.2.3 一次计算超过一个表达式

Theano支持多个输出的函数。例如,我们可以一次计算elementwise的两个矩阵的difference, absolute difference和squared difference。

>>> a, b = T.dmatrices('a', 'b')
>>> diff = a - b
>>> abs_diff = abs(diff)
>>> diff_squared = diff**2
>>> f = theano.function([a, b], [diff, abs_diff, diff_squared])

注意:dmatrice可以产生很多的输出。它是分配符号变量(allocating symbolic variables)的简写。
当我们使用函数f, 它会返回三个变量(打印被重新格式化为可读的形式)。

>>> f([[1, 1], [1, 1]], [[0, 1], [2, 3]])
[array([[ 1.,  0.],
       [-1., -2.]]), array([[ 1.,  0.],
       [ 1.,  2.]]), array([[ 1.,  0.],
       [ 1.,  4.]])]   #三个array分别代表着三个输出。
2.2.4 设置带默认值的申明argument
f = function([x, In(y, value=1)], z)    #使用In类型来更加详细地指定你的函数的参数的属性。
f = function([x, In(y, value=1), In(w, value=2, name='w_by_name')], z)
2.2.5 使用共享变量

应用场景:使函数具有内部状态。例如,我们想要创建一个累加器(accumulator): 初始状态为0,每调用一次函数,函数申明的状态值都增加。
首先让我们定义一个累加器(accumulator)函数。它增加它的参数到内部状态,然后返回老的状态值。

>>> from theano import shared
>>> state = shared(0)
>>> inc = T.iscalar('inc')
>>> accumulator = function([inc], state, updates=[(state, state+inc)])

上述代码中,shared函数创建了一个shared variables。这些混合的符号和非符号变量的值可以被多个函数共享。共享变量能够被用于如dmatrices(...)返回的对象所示的符号表达式,但是这些符号有内部值,该内布值定义了使用该共享变量的所有函数的符号变量的值。
共享变量的相关操作:.get_value().set_value()分别用于获取和修改共享变量的值。
要点归纳:
①使用functionupdates参数来更新函数的参数。使用形式为 (shared-variable, new expression),或者键值对。
②为什么updates机制存在? 语法方便;在原地算法(in-place algorithms,例如低阶矩阵、快速排序)中更快;GPU的良好表现。
③使用共享变量定义了表达式,但是不想使用它的值怎么办? 使用function的givens参数来替代特定函数图中的特定节点。实际上,givens是一种允许你使用一个不同的表达式(该表达式计算出一个相同性状和数据类型的张量)替换公式的任何部分的机制。

注意:
Theano的共享变量的broadcast pattern在每一维上默认是False。共享变量的大小随时间变化,因此我们不能够使用shape来查找broadcastable pattern。如果你想要一个不一样的模式,可以传递一个参数:
theano.shared(..., broadcastable=(True, False))


小贴士:什么是broadcast pattern?
参考:Common Data Integration Patterns -The Broadcast Pattern
说明:当考虑Dynamics 365(微软发布的企业资源规划(ERP)和客户关系管理(CRM)应用程序生产线)多种多样的 整合需要时,解决这些问题的公共设计模式出现了。设计模式,在软件工程中是解决特定类型需求的最符合逻辑顺序的步骤,是从实际应用案例中建立的。最常见的数据整合方式有5种。
broadcast pattern是事务性的(transactional),意味着如果数据迁移(一个事务“transaction”)成功,数据被提交(即持久化)到目的地。如果事务失败,数据迁移失败或者回滚。这种类型的同步还优化了处理记录的速度,以便随着时间的推移,多个系统之间的数据是最新的。因此,广播集成必须具有高可用性和可靠性,以避免在传输过程中丢失关键数据。这就是企业服务总线(Enterprise Service Bus)至关重要的地方。

2.2.6 复制函数

Theano的函数可以被复制,针对于创建相似但是具有不同的共享变量的函数很有用。
通过function对象的copy() 方法来实现。

2.2.7 使用随机数

将随机数放到Theano中计算就是把随机数放到你的图中。
Theano将会给每个变量分配一个NumPy RandomStream object(一个随机数生成器),需要时可从中提取。我们把这种随机数序列称为随机流。随机流位于它们的核心共享变量中,因此对共享变量的观察也适用于此。Theano的随机对象是在RandomStreams中定义和实现的,在较低的级别上是在RandomStreamsBase中。

Brief Example

from theano.tensor.shared_randomstreams import RandomStreams
from theano import function
srng = RandomStreams(seed=234)
rv_u = srng.uniform((2,2))    #代表一个取自均匀分布的2x2矩阵的随机输入流,由RandomStreams的raw_random实现
rv_n = srng.normal((2,2))     #代表一个取自正态分布的2x2矩阵的随机输入流,由RandomStreams的raw_random实现
f = function([], rv_u)        #调用f函数时,可返回不同的结果;而调用g函数时,返回结果相同。
g = function([], rv_n, no_default_updates=True)    #Not updating rv_n.rng,返回结果不影响随机数产生器的状态
nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)  #随机变量在单个函数中最多调用一次,nearly_zeros恒为0

Seeding Streams
随机变量的种子(seed)可能是单独的,也可以是集体的。
单独的:用.rng.set_value() ,通过设置.rng属性,来给一个随机变量设置种子。
集体的:通过RandomStream的对象的seed方法给所有的随机变量分配种子。

Sharing Streams Between Functions
与通常的共享变量一样,用于随机变量的随机数生成器在函数之间是通用的。

Copying Random State Between Theano Graphs
在某些使用情况下,一个用户可能想要转移跟给定的theano graph(如g1, 编译函数f1)相关的所有随机数产生器的状态到第二个graph(如g2, 编译函数f2)。

3. 实战案例:逻辑斯蒂回归

import numpy
import theano
import theano.tensor as T
rng = numpy.random

N = 400                                   # training sample size
feats = 784                               # number of input variables

# generate a dataset: D = (input_values, target_class)
# numpy.random.randn(d0, d1, ..., dn) 返回一个标准的正态分布,数组的性状为(d0, d1, ..., dn)
# numpy.random.randint(low, high=None, size=None, dtype='l')返回从low(含)到high(不含)的随机整数。
D = (rng.randn(N, feats), rng.randint(size=N, low=0, high=2))
training_steps = 10000

# Declare Theano symbolic variables
x = T.dmatrix("x")  #返回2维的float64浮点数数组
y = T.dvector("y")  #返回1维的float64浮点数向量

# initialize the weight vector w randomly
#
# this and the following bias variable b
# are shared so they keep their values
# between training iterations (updates)
w = theano.shared(rng.randn(feats), name="w") #生成一个1维的含有784个值的数组

# initialize the bias term
b = theano.shared(0., name="b")

print("Initial model:")
print(w.get_value())
print(b.get_value())

# Construct Theano expression graph
# theano.tensor.dot(X, Y) 对于2维数组等同于矩阵操作,返回X和Y的乘积
p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))   # Probability that target = 1
prediction = p_1 > 0.5                    # The prediction thresholded
xent = -y * T.log(p_1) - (1-y) * T.log(1-p_1) # Cross-entropy loss function
cost = xent.mean() + 0.01 * (w ** 2).sum()# The cost to minimize
gw, gb = T.grad(cost, [w, b])             # Compute the gradient of the cost
                                          # w.r.t weight vector w and
                                          # bias term b
                                          # (we shall return to this in a
                                          # following section of this tutorial)

# Compile
train = theano.function(
          inputs=[x,y],
          outputs=[prediction, xent],
          updates=((w, w - 0.1 * gw), (b, b - 0.1 * gb)))
predict = theano.function(inputs=[x], outputs=prediction)

# Train
for i in range(training_steps):
    pred, err = train(D[0], D[1])

print("Final model:")
print(w.get_value())
print(b.get_value())
print("target values for D:")
print(D[1])
print("prediction on D:")
print(predict(D[0]))

运行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值