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

Derivatives in Theano

一、计算梯度

现在,让我们使用theano来做稍微更复杂的任务:创建一个函数,用来计算表达式y 关于它的参数x的导数。我们将会用到宏 T.grad 。例如,我们可以计算  关于 的梯度。注意: .

下面就是用来计算这个梯度的代码:

>>> from theano import pp
>>> x = T.dscalar('x')
>>> y = x ** 2
>>> gy = T.grad(y, x)
>>> pp(gy)  # print out the gradient prior to optimization
'((fill((x ** 2), 1.0) * 2) * (x ** (2 - 1)))'
>>> f = function([x], gy)
>>> f(4)
array(8.0)
>>> f(94.2)
array(188.40000000000001)

在这个例子中,我们可以从pp(gy) 中看到我们在计算的符号梯度是正确的。 fill((x ** 2), 1.0) 意思是说创建一个和 x ** 2一样shape的矩阵,然后用1.0来填充。

note:该优化器简化了符号梯度的表达式,你可以深挖编译后的函数的内部属性来了解细节。

pp(f.maker.fgraph.outputs[0])
'(2.0 * x)'

在优化之后,在graph中只有一个 Apply节点,其输入是乘以2的。

我们同样可以计算复杂表达式的梯度,例如由上面定义的逻辑函数。结果显示逻辑函数的梯度为: .

该图是逻辑函数的梯度,x轴表示x的变化,y轴表示梯度  。

>>> x = T.dmatrix('x')
>>> s = T.sum(1 / (1 + T.exp(-x)))
>>> gs = T.grad(s, x)
>>> dlogistic = function([x], gs)
>>> dlogistic([[0, 1], [-1, -2]])
array([[ 0.25      ,  0.19661193],[ 0.19661193,  0.10499359]])

通常来说,对于任何标量表达式, T.grad(s, w) 提供theano表达式来计算 。这种方式下,甚至对于有着许多输入的函数来说,theano可以用来高效的计算符号微分 (正如 T.grad 返回的表达式可以在编译期间进行优化) ( automatic differentiation 有详细的描述关于符号微分的)。

note: T.grad 的第二个参数可以是一个列表,这种情况下,输出也同样是一个列表。在这两个列表中的顺序都是很重要的:输出列表的第 i 个元素是T.grad 的第一个参数关于第二个参数的列表的第 i 个元素的梯度。 T.grad 第一个参数必须是一个标量(其tensor size 为1)。更多有关T.grad的参数的语义的信息和实现的细节,可以参考库的 this 部分。

在内部微分的工作的信息可以在更高级的教程 Extending Theano中找到。

二、计算Jacobian

在theano中,术语 Jacobian 指定为张量包含函数的输出关于输入的第一个偏导数。 (在数学中这就是所谓的Jacobian矩阵) Theano 实现宏theano.gradient.jacobian() 所需要的就是计算Jacobian。下面部分就是解释如何手动去完成它:

为了手动计算一些函数 y 关于一些参数 x 的Jacobian,我们需要使用 scan。即在y 中使用循环来遍历所有元素,然后计算 y[i] 关于x 的梯度。

note:scan 是theano中一个通用的操作,可以以符号方式写出各种递归等式。然而生成一个符号循环是很难的(而且还需要为了性能而去优化它们) ,所以需要努力提升scan.的效果。在后面会接着说 scan 的。

>>> x = T.dvector('x')
>>> y = x ** 2
>>> J, updates = theano.scan(lambda i, y,x : T.grad(y[i], x), sequences=T.arange(y.shape[0]), non_sequences=[y,x])
>>> f = function([x], J, updates=updates)
>>> f([4, 4])
array([[ 8.,  0.],[ 0.,  8.]])

在该代码中所做的就是生成一个int类型的序列,通过使用T.arange来使得其中从0到 y.shape[0] 。然后我们对这个序列进行循环,然后在每一步,灭我们计算元素 y[i]关于x 的梯度。scan 可以自动的连接所有的这些列,生成一个对应于jacobian的矩阵。

note:在使用T.grad的时候记得也有一些陷阱的。 其中一个就是你没法和这样theano.scan(lambda y_i,x: T.grad(y_i,x), sequences=y, non_sequences=x)重写jacobin的上述表达式,,尽管从文档上看scan是可以的。原因在于 y_i 不再试x的函数了,而 y[i]仍然是。

三、计算Hessian

在theano中,术语Hessian 与数学上的概念没差:是一个矩阵,其中包含着标量输出和向量输入的函数的二阶偏导数。Theano 实现宏theano.gradient.hessian() 所要做的就是计算Hessian。下面的部分就是介绍如何手动完成。

你可以可jacobian一样相似的计算Hessian。唯一的差别在于,我们通过计算T.grad(cost,x)的jacobian来代替计算一些表达式y 的jacobian,所以计算的cost是标量的。

>>> x = T.dvector('x')
>>> y = x ** 2
>>> cost = y.sum()
>>> gy = T.grad(cost, x)
>>> H, updates = theano.scan(lambda i, gy,x : T.grad(gy[i], x), sequences=T.arange(gy.shape[0]), non_sequences=[gy, x])
>>> f = function([x], H, updates=updates)
>>> f([4, 4])
array([[ 2.,  0.],[ 0.,  2.]])

四、Jacobian乘以一个向量

有时候我们需要将算法表示成jacobinas乘以向量,或者向量乘以jacobinans。相比较于评估jacobian,然后做乘法,可以直接计算合适的结果从而避免对jacobian的实际计算。这可以带来明显的性能的提升。一个这样的算法可以在下面的文献中找到:

  • Barak A. Pearlmutter, “Fast Exact Multiplication by the Hessian”, Neural Computation, 1994

然而在实际中,我们想要theano能够自动的识别这些模式,不过以通常的方式来实现这样的优化是非常难的。所以,我们提供了特别的函数来应对这些问题:

R-operator

R 操作符是用来评估介于一个jacobian和一个向量之间的乘积的,即 . 该式子可以扩展成当x是一个矩阵,或者一个张量的形式,这种情况下,jacobian就变成了一个张量,然后乘积就变成了某种张量的积。因为在实际中,我们最后是需要计算权重矩阵这样的表达式的,theano支持这种操作的更通用形式。为了评估表达式y的R 操作,(关于x的),使用v乘以jacobian,你需要做类似下面的事情:

>>> W = T.dmatrix('W')
>>> V = T.dmatrix('V')
>>> x = T.dvector('x')
>>> y = T.dot(x, W)
>>> JV = T.Rop(y, W, V)
>>> f = theano.function([W, V, x], JV)
>>> f([[1, 1], [1, 1]], [[2, 2], [2, 2]], [0,1])
array([ 2.,  2.])

实现Rop的操作列表List 。

L-operator

相似于R-操作L-操作 会计算一个行向量乘积,其数学上的形式为 。该L-操纵 同样支持通用的张量 (不只是向量)。相思的,它可以按照下面形式实现:

>>> W = T.dmatrix('W')
>>> v = T.dvector('v')
>>> x = T.dvector('x')
>>> y = T.dot(x, W)
>>> VJ = T.Lop(y, W, v)
>>> f = theano.function([v,x], VJ)
>>> f([2, 2], [0, 1])
array([[ 0.,  0.],[ 2.,  2.]])

note:v, 在L操作和R操作中是不同的。对于L操作来说,该 v 需要有着和输出一样的shape,然而,R操作需要和输入参数一样的shape。更进一步说,这两个操作的结果是不同的。L操作的结果有着和输入参数一样的shape,而R操作有着和输出一样的shape。

五、Hessian乘以一个向量

如果你需要计算Hessian 乘以一个向量,你就需要用到上面定义的操作,它们通常比实际计算准确的Hessian,然后计算乘积更高效。因为Hessian矩阵的对称性,你可以用两种方式得到相同的结果,虽然这些选择也许会有不同的性能。因此,我们建议在使用它们之前先, 先对它们进行分析:

>>> x = T.dvector('x')
>>> v = T.dvector('v')
>>> y = T.sum(x ** 2)
>>> gy = T.grad(y, x)
>>> vH = T.grad(T.sum(gy * v), x)
>>> f = theano.function([x, v], vH)
>>> f([4, 4], [2, 2])
array([ 4.,  4.])

或者使用R操作:

>>> x = T.dvector('x')
>>> v = T.dvector('v')
>>> y = T.sum(x ** 2)
>>> gy = T.grad(y, x)
>>> Hv = T.Rop(gy, x, v)
>>> f = theano.function([x, v], Hv)
>>> f([4, 4], [2, 2])
array([ 4.,  4.])

备注:

  • grad 函数是符号化的工作的:它接受和返回theano变量。
  • grad 可以和宏相比较,因为它可以重复使用
  • 标量损失只能被直接通过grad进行处理。数组可以通过重复应用的形式来解决
  • 内建的函数可以高效的计算向量乘以jacobian和向量乘以Hessian
  • 优化需要高效的计算全jacobian和Hessian矩阵,以及jacobian乘以向量。

参考资料:

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

Theano2.1.6-基础知识之在thenao中的求导相关推荐

  1. 前端基础知识整理汇总(中)

    前端基础知识整理汇总(中) Call, bind, apply实现 // call Function.prototype.myCall = function (context) {context = ...

  2. 2014计算机基础知识,2014年计算机基础知识练习题240_甘肃中公教育

    2014年计算机基础知识练习题240_甘肃中公教育 (3页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 3. 运算精度高电子计算机具有以往计 ...

  3. js基础知识温习:Javascript中如何模拟私有方法

    本文涉及的主题虽然很基础,在很多人眼里属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题.这里会涉及到对象属性的封装.原型.构造函数.闭包以及立即执行表达式等知识. 公有方法 公有方法 ...

  4. 计算机文化基础知识在未来工作中的应用论文,大学计算机文化基础论文范文2篇...

    随着互联网时代的全面到来,计算机应用能力的培养作为普及计算机应用技能的先决条件对互联网经济时代的全面发展起着重要作用.下面是秋天网小编为大家推荐的大学计算机文化基础论文,供大家参考. 大学计算机文化基 ...

  5. 计算机文化基础知识在未来工作中的应用论文,计算机文化基础论文

    计算机文化基础课程作为高职高院校必修的基础课,传统的教学模式不再适合各专业的发展.下面是小编为大家整理的,供大家参考. 篇一 计算机文化基础教学浅谈 摘 要: 本文作者从实际教学角度,提出了个人在教学 ...

  6. 【深度学习基础知识 - 28】三维重建中的点云、体素、mesh

    点云.体素和mesh都是三维重建中常用的三维物体的表示方法. 1. 点云 1.1 点云的概念 点云是不规则的数据结构,就是用一堆点来表示物体,这种方法的限制是点与点之间没有联系,缺乏物体的表面信息. ...

  7. 中职生计算机基础知识总结,浅谈中职学生的计算机基础教育

    摘要:算机的基础教育已经在义务教育中普及,但学生对于计算机的应用能力却有很大差异,这就为中职的计算机基础教育带来不便,对于程度良莠不齐的入校新生来说该如何展开教学,是值得深思的问题,本文就这一问题展开 ...

  8. 公共基础知识:浅析生活中的酒

    为了各位考生更好的备考公共基础知识部分,下面将一个数次出现在各地公共基础知识考试中的考点--酒,讲解给各位考生.帮助大家把这个考点的相关知识积累下去.希望能帮助各位考生更好的备考有关通用知识的考试,下 ...

  9. 湖北省计算机专业基础知识,2012年湖北省中职对口高考计算机应用基础知识点...

    简要介绍资料的主要内容,以获得更多的关注 2012年湖北省中职对口高考计算机应用基础知识点 第一部分 计算机基础知识 1.计算机的发展和应用领域 了解计算机技术的发展过程及趋势,掌握并能列举各阶段发展 ...

最新文章

  1. Webcast 系列课程 NET最全,最权威的学习资源
  2. 使用代码配置 NHibernate
  3. suse linux c 编译环境,SUSE 11中安装GCC开发环境
  4. mysql拼接两个字段_重拾MySQL之创建计算字段和函数
  5. php 组合模式,php设计模式(十三)透明组合模式
  6. 怎样对java网站进行简单修改_用Java写一个简单的毕业设计,功能就增删改查的一些基本功能就可以,需要哪些技术?...
  7. TVS管(瞬态电压抑制二极管)好坏 简单检测方法
  8. @PostConstruct、@PreDestroy注解介绍及Spring中@PostConstruct、constructor、@Autowired的顺序
  9. saspython知乎_sas比spss好用在哪里?
  10. Java- Math类
  11. 用c语言把蜂鸣器封装成函数,C语言蜂鸣器问题
  12. 《计算机网络微课堂》一、计算机网络概述(你确定不点进来看看?)
  13. 内存映射(Memory Map)
  14. 分布式事务中的三种解决方案详解(转载)
  15. apigateway-kong(二)admin-api(结合实例比官网还详细)
  16. 九鼎Study210嵌入式开发板刷机笔记
  17. 2017.10.23 模拟考试 (题目来自:学大伟业)
  18. 【Vue原理】Diff - 源码版 之 Diff 流程
  19. JTAG、SWD、JLINK、ST-LINK、ULINK的区别
  20. 初次做的一个QQ表情搜集整理的软件。记录下来

热门文章

  1. 我在富士康挨踢了七年(八.出国Support)
  2. 个人随笔-《江城子·驻西航》
  3. C#发现之旅第二讲 C#-XSLT开发
  4. 小程序云开发使用where查询遇到的问题
  5. 软考考前冲刺第九,十章多媒体基础知识知识产权基础知识
  6. Swift - 获取、改变按钮的标题文本(UIButton点击切换title)
  7. eclipse+pydev添加已存在django项目及其调试方法
  8. jquery使用技巧总结
  9. git回退的四种操作
  10. python中forward_符合python风格的对象