Theano2.1.3-基础知识之更多的例子

来自:http://deeplearning.net/software/theano/tutorial/examples.html

More Examples

现在,是时候开始系统的熟悉theano的基础对象和操作了,可以通过浏览库的部分来详细的了解 Basic Tensor Functionality. 随着这个教程的深入,你可以逐渐的让自己熟悉库的其他相关的部分和文档入口页面的其他相关的主题了。

一、Logistic 函数

这是一个简单的例子,虽然会比两个数值相加要难一些。假设你想要计算一个逻辑曲线,首先得到一个如下的式子:

上图是一个逻辑函数,x轴表示x值,y轴表示s(x)值。

你需要在doubles矩阵上逐元素( elementwise )的计算这个函数,也就是说你是想要在矩阵的每个独立的元素上都使用该函数。代码如下:

[python] view plaincopy

  1. >>> x = T.dmatrix(‘x‘)
  2. >>> s = 1 / (1 + T.exp(-x))
  3. >>> logistic = function([x], s)
  4. >>> logistic([[0, 1], [-1, -2]])
  5. array([[ 0.5       ,  0.73105858],
  6. [ 0.26894142,  0.11920292]])

需要逐元素计算是因为它的操作:除法、加法、指数和减法,都是逐元素的操作。在该情况下也是:

我们可以验证从这个可代替的式子上得到的结果是一样的:

[python] view plaincopy

  1. >>> s2 = (1 + T.tanh(x / 2)) / 2
  2. >>> logistic2 = function([x], s2)
  3. >>> logistic2([[0, 1], [-1, -2]])
  4. array([[ 0.5       ,  0.73105858],
  5. [ 0.26894142,  0.11920292]])

二、在同一时间对多个操作进行计算

Theano支持函数有着多于一个的输出。例如,我们可以在同一时刻计算两个矩阵a和b 之间的逐元素(elementwise )的差,绝对值的差,平方值的差:

[python] view plaincopy

  1. >>> a, b = T.dmatrices(‘a‘, ‘b‘)
  2. >>> diff = a - b
  3. >>> abs_diff = abs(diff)
  4. >>> diff_squared = diff**2
  5. >>> f = function([a, b], [diff, abs_diff, diff_squared])

note:dmatrices 生成提供的名字一样数量的输出。这是一个用来分配符号变量的快捷方式,在本教程中会经常用到。

当我们使用函数f 时,它返回三个变量(输出的时候会为了更好的可读性而被重新格式):

[python] view plaincopy

  1. >>> f([[1, 1], [1, 1]], [[0, 1], [2, 3]])
  2. [array([[ 1.,  0.],
  3. [-1., -2.]]),
  4. array([[ 1.,  0.],
  5. [ 1.,  2.]]),
  6. array([[ 1.,  0.],
  7. [ 1.,  4.]])]

三、对参数设置默认值

假设你想要定义一个相加两个数的函数,如果你定义完之后,在调用的时候,只提供了一个参数,那么另一个输入可以假设默认为1,可以如下所示:

[python] view plaincopy

  1. >>> from theano import Param
  2. >>> x, y = T.dscalars(‘x‘, ‘y‘)
  3. >>> z = x + y
  4. >>> f = function([x, Param(y, default=1)], z)
  5. >>> f(33)
  6. array(34.0)
  7. >>> f(33, 2)
  8. array(35.0)

使用的 Param 参数允许你指定你函数的参数有着更详细的值。这里我们通过创建一个Param实例来将y设置其默认值为1。

有着默认值的输入必须在没有默认值的输入的后面(和python的函数一样的顺序)可以对多个输入进行设置莫仍只。这些蚕食可以通过位置或者名称来进行设定,就像标准的python中一样:

[python] view plaincopy

  1. >>> x, y, w = T.dscalars(‘x‘, ‘y‘, ‘w‘)
  2. >>> z = (x + y) * w
  3. >>> f = function([x, Param(y, default=1), Param(w, default=2, name=‘w_by_name‘)], z)
  4. >>> f(33)
  5. array(68.0)
  6. >>> f(33, 2)
  7. array(70.0)
  8. >>> f(33, 0, 1)
  9. array(33.0)
  10. >>> f(33, w_by_name=1)
  11. array(34.0)
  12. >>> f(33, w_by_name=1, y=0)
  13. array(33.0)

note:Param 不知道作为参数传入的局部变量y 和w 的名称。这些符号变量对象都有name属性(和上面例子一样通过dscalars来设置),这些是我们构建的函数中的关键参数的名称。这就是 Param(y, default=1)中的工作机制。在Param(w, default=2, name=‘w_by_name‘)的情况下 ,我们用在这个函数中使用过的名字来覆盖符号变量的名字属性。
    你可以看看库中的 Function 来更详细的了解。

四、使用共享变量

同样的也可以让函数有一个内部状态。例如,我们想要在开始就设置一个累加器,先初始化为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的参数 updates 必须被以(shared-variable, new expression)这种对形式的列表所赋值。它同样可以是一个字典,其中的键是共享变量而值是新表达式。。不管怎么说,它表示“不论什么时候运行,它会将.value的每个共享变量替换成对应的表达式的结果” 。也就是说,我们的累加器会用状态state的和以及递增数来替换状态state的值。

[python] view plaincopy

  1. >>> state.get_value()
  2. array(0)
  3. >>> accumulator(1)
  4. array(0)
  5. >>> state.get_value()
  6. array(1)
  7. >>> accumulator(300)
  8. array(1)
  9. >>> state.get_value()
  10. array(301)

可以使用 .set_value() 方法来重置状态state:

[python] view plaincopy

  1. >>> state.set_value(-1)
  2. >>> accumulator(3)
  3. array(-1)
  4. >>> state.get_value()
  5. array(2)

正如上面说的,你可以定义超过一个函数来使用相同的共享变量。这些函数都能够更新这个值。

[python] view plaincopy

  1. >>> decrementor = function([inc], state, updates=[(state, state-inc)])
  2. >>> decrementor(2)
  3. array(2)
  4. >>> state.get_value()
  5. array(0)

你也许会惊讶为什么这个更新机制会存在。你总可以通过返回一个新的表达式来得到一个相似的结果,然后在NumPy里面使用它们。该更新机制是一个语法上的方便,不过在这里主要是因为效率问题。对共享变量的更新有时候可以使用in-place算法更快的完成(了例如: low-rank矩阵更新).。同样的,theano有着更多有关在哪和如何来分配共享权重的函数,这些都是在需要使用在 GPU上很重要的组成部分.

有时候你想要使用一个共享变量来表示一些公式,却不想要使用它们的值。在这种情况下,你可以使用function函数的givens的参数,这个用来代替这种情况下graph中的特定的节点。

[python] view plaincopy

  1. >>> fn_of_state = state * 2 + inc
  2. >>> # The type of foo must match the shared variable we are replacing
  3. >>> # with the ``givens``
  4. >>> foo = T.scalar(dtype=state.dtype)
  5. >>> skip_shared = function([inc, foo], fn_of_state,
  6. givens=[(state, foo)])
  7. >>> skip_shared(1, 3)  # we‘re using 3 for the state, not state.value
  8. array(7)
  9. >>> state.get_value()  # old state still there, but we didn‘t use it
  10. array(0)

givens 参数可以用来代替任何符号变量,不只是共享变量。你还可以用来代替常量、表达式。不过要注意,不要让由givens替换的表达式之间有着相互依赖关系,替换的顺序是没法保证的,所以替换之后是有可能以任意顺序来执行的。

在实际中,有关使用givens的一个好的方法就是替换公式的任何部分的时候使用的是不同的表达式,只不过该表达式有着相同shape和dtype的张量而已。

note:Theano 共享变量的广播模式默认情况下对于每个维度来说都是False。共享变量的size可以随着时间变化,所以我们没法使用shape来找到可广播的模式。如果你想要一个不同的模式,只要将它像参数一样传递 theano.shared(..., broadcastable=(True, False))。

五、使用随机数

因为在theano中,你首先会将任何事情进行符号化,然后编译这个表达式来得到函数,然后使用伪随机数不是和Numpy中一样简单的,当然也不会太复杂。

将随机放入theano的计算中就是将随机变量放到你的graph中。theano将会对每个这样的变量分配一个 NumPy RandomStream 对象 (一个随机生成器) ,然后必要的时候提取出来。我们称这类随机数序列为a random stream. 随机流的核心也是共享变量,所以对共享变量的观察在这里也是一样的。theano的随机对象的定义和实现在 RandomStreams 更低的版本,也就是其父类RandomStreamsBase.

5.1 一个简单的例子

这里是一个简短的例子,构建代码为:

[python] view plaincopy

  1. from theano.tensor.shared_randomstreams import RandomStreams
  2. from theano import function
  3. srng = RandomStreams(seed=234)
  4. rv_u = srng.uniform((2,2))
  5. rv_n = srng.normal((2,2))
  6. f = function([], rv_u)
  7. g = function([], rv_n, no_default_updates=True)    #Not updating rv_n.rng
  8. nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)

这里 ‘rv_u’ 表示一个从均匀分布中提取的2*2的矩阵的随机流。同样的, ‘rv_n’ 表示一个从正太分布中提取的2*2矩阵的一个随机流。该分布实现和定义都在 RandomStreams 中,其父类为 raw_random. 他们只在CPU上工作。 Other Implementations 上面有GPU版本的。

现在让我们来使用这些对象。如果我们调用 f(),我们就得到了均匀随机数。 随机数生成器的内部状态是自动进行更新的,所以我们在每个时间上得到的是不同的随机数:

[python] view plaincopy

  1. >>> f_val0 = f()
  2. >>> f_val1 = f()  #different numbers from f_val0

当我们增加额外的参数 no_default_updates=True 到 function (as in g),那么随机数生成器状态不会受到返回函数调用的影响。所以,例如,调用g 函数多次,而返回的是同样的数值:

[python] view plaincopy

  1. >>> g_val0 = g()  # different numbers from f_val0 and f_val1
  2. >>> g_val1 = g()  # same numbers as g_val0!

一个重要的备注是随机变量在任何单一函数执行中最多被提取一次。所以,即使 rv_u 随机变量在输出表达式中出现了三次,nearly_zero函数可以保证返回的值可以逼近0 (除了舍入导致的错误):

[python] view plaincopy

  1. >>> nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)

5.2 Seeding Streams

随机变量可以被独立或集体的被传入种子。你可以只对随机变量通过seeding或者使用.rng.set_value()的.rng 属性来指定传入种子:

[python] view plaincopy

  1. >>> rng_val = rv_u.rng.get_value(borrow=True)   # Get the rng for rv_u
  2. >>> rng_val.seed(89234)                         # seeds the generator
  3. >>> rv_u.rng.set_value(rng_val, borrow=True)    # Assign back seeded rng

你同样可以对所有的随机变量通过RandomStreams对象的seed方法来分配种子。该种子将会被用来传递给一个临时随机数生成器,然后对每个随机变量生成种子。

[python] view plaincopy

  1. >>> srng.seed(902340)  # seeds rv_u and rv_n with different seeds each

5.3 在函数之间共享流

和通常的共享变量一样,用于随机变量的随机数生成器都是函数中常见的。所以我们的nearly_zeros 函数将会使用上面介绍的函数 f 来更新生成器的状态。例如:

[python] view plaincopy

  1. >>> state_after_v0 = rv_u.rng.get_value().get_state()
  2. >>> nearly_zeros()       # this affects rv_u‘s generator
  3. >>> v1 = f()
  4. >>> rng = rv_u.rng.get_value(borrow=True)
  5. >>> rng.set_state(state_after_v0)
  6. >>> rv_u.rng.set_value(rng, borrow=True)
  7. >>> v2 = f()             # v2 != v1
  8. >>> v3 = f()             # v3 == v1

5.4 在theano graphs之间复制随机状态

在一些使用的情况中,用户有可能想要将所有随机数生成器的“state”从一个给定的theano graph (例如, g1,和下面编译的函数f1一起的) 到另一个 graph (例如 g2,和函数f2一起的).。如果你想要从之前模型的pickled版本的参数中初始化模型的state,那么这个问题就会出现。 theano.tensor.shared_randomstreams.RandomStreams 和 theano.sandbox.rng_mrg.MRG_RandomStreams 可以通过复制state_updates参数的元素来获得

每次从一个RandomStreams对象中得到一个随机变量,一个元组就会被添入到 state_updates 列表中。第一个元素就是一个共享变量,用来表示与这个具体的变量相关联的随机数生成器的状态,第二个元素用来表示对应于随机数生成过程(即RandomFunction{uniform}.0)的theano graph。

一个关于如何“random states”可以从一个theano function迁移到另一个的例子如下:

[python] view plaincopy

  1. import theano
  2. import numpy
  3. import theano.tensor as T
  4. from theano.sandbox.rng_mrg import MRG_RandomStreams
  5. from theano.tensor.shared_randomstreams import RandomStreams
  6. class Graph():
  7. def __init__(self, seed=123):
  8. self.rng = RandomStreams(seed)
  9. self.y = self.rng.uniform(size=(1,))
  10. g1 = Graph(seed=123)
  11. f1 = theano.function([], g1.y)
  12. g2 = Graph(seed=987)
  13. f2 = theano.function([], g2.y)
  14. print ‘By default, the two functions are out of sync.‘
  15. print ‘f1() returns ‘, f1()
  16. print ‘f2() returns ‘, f2()
  17. def copy_random_state(g1, g2):
  18. if isinstance(g1.rng, MRG_RandomStreams):
  19. g2.rng.rstate = g1.rng.rstate
  20. for (su1, su2) in zip(g1.rng.state_updates, g2.rng.state_updates):
  21. su2[0].set_value(su1[0].get_value())
  22. print ‘We now copy the state of the theano random number generators.‘
  23. copy_random_state(g1, g2)
  24. print ‘f1() returns ‘, f1()
  25. print ‘f2() returns ‘, f2()

会有如下的输出:

[python] view plaincopy

  1. # By default, the two functions are out of sync.
  2. f1() returns  [ 0.72803009]
  3. f2() returns  [ 0.55056769]
  4. # We now copy the state of the theano random number generators.
  5. f1() returns  [ 0.59044123]
  6. f2() returns  [ 0.59044123]

5.5 其他随机分布

见 other distributions implemented.

5.6 其他实现

这里有2个基于 CURAND 和 MRG31k3p.的两个实现。该RandomStream 只工作在CPU上,而 MRG31k3p 既能在CPU 上也能在GPU上。CURAND 只工作在 GPU上。

5.7 一个真实的例子:逻辑回归

前面的内容会在下面这个更实际的例子中见到,而且该例子会被多次使用。

[python] view plaincopy

  1. import numpy
  2. import theano
  3. import theano.tensor as T
  4. rng = numpy.random
  5. N = 400
  6. feats = 784
  7. D = (rng.randn(N, feats), rng.randint(size=N, low=0, high=2))
  8. training_steps = 10000
  9. # Declare Theano symbolic variables声明theano符号变量
  10. x = T.matrix("x")
  11. y = T.vector("y")
  12. w = theano.shared(rng.randn(feats), name="w")
  13. b = theano.shared(0., name="b")
  14. print "Initial model:"
  15. print w.get_value(), b.get_value()
  16. # Construct Theano expression graph构建theano表达式的图
  17. p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))   # Probability that target = 1
  18. prediction = p_1 > 0.5                    # The prediction thresholded
  19. xent = -y * T.log(p_1) - (1-y) * T.log(1-p_1) # Cross-entropy loss function
  20. cost = xent.mean() + 0.01 * (w ** 2).sum()# The cost to minimize
  21. gw, gb = T.grad(cost, [w, b])             # Compute the gradient of the cost
  22. # (we shall return to this in a
  23. # following section of this tutorial)
  24. # Compile编译
  25. train = theano.function(
  26. inputs=[x,y],
  27. outputs=[prediction, xent],
  28. updates=((w, w - 0.1 * gw), (b, b - 0.1 * gb)))
  29. predict = theano.function(inputs=[x], outputs=prediction)
  30. # Train训练
  31. for i in range(training_steps):
  32. pred, err = train(D[0], D[1])
  33. print "Final model:"
  34. print w.get_value(), b.get_value()
  35. print "target values for D:", D[1]
  36. print "prediction on D:", predict(D[0])

参考资料:

[1]官网:http://deeplearning.net/software/theano/tutorial/examples.html

时间: 2024-11-05 01:52:06

Theano2.1.3-基础知识之更多的例子的相关文章

第二节,基础知识之更多的例子

先声明:theano模块的内容大都是参考来源于网上,并亲手实践复现一遍,也有部分内容是自己补充 本文会列出所参考文章,如有版权问题,请联系我,我会及时删除 # -*- coding: utf-8 -*- """ Created on Fri Mar 23 16:53:19 2018 @author: zy """ ''' Theano2.1.3-基础知识之更多的例子 http://www.cnblogs.com/shouhuxianjian/p/

20_Shell语言———VIM编辑器基础知识三之窗口属性定制、配置文件及查找替换功能

Vim编辑器可以让用户按照需求来定制一些使用属性. 一.窗口属性定义 1)显示行号 行号不是内容,只是用来帮助用户确认文本所在的行.在vim编辑器中,如果要显示行号,可以在末行模式下输入: set number 如果想关闭,则可以在功能名称前面加上no,即: set nonumber 命令可以被简写,如set number 可以简写为 set nu:set nonumber 可以简写为 set nonu. 注意,上述设定仅对当前vim的进程有效,一旦当前进程关闭,这些设定就会失效,如果要使设定永

【Python数据挖掘课程】六.Numpy、Pandas和Matplotlib包基础知识

前面几篇文章采用的案例的方法进行介绍的,这篇文章主要介绍Python常用的扩展包,同时结合数据挖掘相关知识介绍该包具体的用法,主要介绍Numpy.Pandas和Matplotlib三个包.目录:        一.Python常用扩展包        二.Numpy科学计算包        三.Pandas数据分析包        四.Matplotlib绘图包 前文推荐:       [Python数据挖掘课程]一.安装Python及爬虫入门介绍       [Python数据挖掘课程]二.K

【深度分解】听趣拍云产品经理剖析视频基础知识(2)

"随着技术的不断进步,视频技术的制作加工门槛逐渐降低,信息资源的不断增长,同时由于视频信息内容更加丰富完整的先天优势,在近年来已经逐渐成为主流.在基础知识(1)里面已经讲了模拟时代和数字化时代的视频技术.接下来将对视频编码与压缩.画面压缩.运动压缩.互联网视频应用的到来做一个详细的介绍." 视频编码与压缩 视频编码与压缩,是数字化视频非常重要的技术,以至于它直接影响到视频在各个领域的应用.如果没有视频编码技术的不断提高,我们今天也不可能在方方面面享受到视频的便利性. 首先,视频编码是一

第二章 TCP/IP 基础知识

? TCP/IP ?transmission control protocol and ip internet protocol 是互联网众多通信协议中最为著名的. ? 2.2 TCP/IP 的标准化 2.2.2 TCP/IP 标准化精髓 TCP/IP 协议始终具有很强的实用性. 相比于TCP/IP ,OSI 之所以未能达到普及,主要原因在于未能尽早的制定可行性较强的协议.未能提出应对技术快速更新的协议以及没有能及时进行后期的改良的方案. 2.2.3 TCP/IP 规范 --RFC 那些需要标准

TCP/IP基础知识

最近工作中需要自己在板卡植入TCP/IP协议栈,因为毕竟单片机性能有限,完整的TCP/IP协议栈很庞大,所以只能移植经过简化的,本来已成功将LWIP协议栈移植到项目板卡中,但老大说这个协议栈写得过于繁琐,特别是在内存管理这块,不容易理解,而且我们板卡对数据的准确性要求没那么高,重点要保证能通就行,偶尔丢失一两个包都没关系,所以按此需求自写协议栈,实现UDP以及Telnet通信,目前UDP已经实现,其余功能还在慢慢增加中,通过这段时间的研究发现实现UDP并不难,最主要是要把网络通信的一些基本概念知

微信公众平台开发基础知识38问

最近接触微信公众号后台的开发,看了一些资料基本可以满足简单的需求开发.笔者将这些问题及解答整理出来,以帮助更多初学者少走弯路. 1.订阅号与服务号的主要区别是什么? 订阅号每天能群发一条消息,没有自定义菜单及高级接口权限(目前 个人.企业订阅号关联腾讯微博认证之后才有自定义菜单):服务号有自定义菜单微信认证之后有高级接口权限,但每月只能群发一条消息. 2.到底该申请订阅号还是服务号? 申请哪种类型的公众账号,主要取决于账号的用途.服务号主要面向企业和组织,旨在为用户提供服务:订阅号主要面向媒体和

3.Swift基础知识

Swift是用来开发iOS和OS X应用的新语言,但是许多地方用起来跟C或者OC是差不多的. Swift提供了C语言和OC的基本数据类型,比如整型用Int,浮点型用Double或者Float,布尔型用Bool,字符串文本用String,Swift还提供了两种集合类型,Array和Dictionary,后面会介绍. Swift也跟C一样用唯一的变量名来存储与使用数据,还能使用一些值不会变的变量,应该说是常量,比C里面的常量要强大.在涉及到一些值不会发生变化的数据时使用常量类型能让代码更安全整洁.

ArcGIS教程:3D Analyst基础知识

创建3D视图 以三维形式查看数据能为您提供一个全新的认识.通过三维视图可以深入了解通过相同数据的平面地图不易察觉的内容.例如,您不必根据配置等值线来推断是否存在山谷,您能够实际看到山谷和感到谷底和谷脊的高度差异. ArcGlobe 和 ArcScene 可用于构建多图层 3D 环境,并控制如何对各图层进行符号化.渲染各图层和在 3D 空间中定位各图层.还可以控制 3D 视图的全局属性,如照明度或垂直夸大.可以通过以下方式选择要素:使用要素的属性或要素相对于其他要素的位置,或者在场景或地球中单击各