11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

深度学习中的微分

  • 2019-11-10
  • 本文字数:2135 字

    阅读完需:约 7 分钟

深度学习中的微分

导读:我们在研究与应用深度学习时,会碰到一个无法绕过的内容,就是微分求导,再具体点其实就是反向传播。如果我们只是简单地应用深度学习、搭搭模型,那么可以不用深究。但是如果想深入的从工程上了解深度学习及对应框架的实现,那么了解程序是如何进行反向传播,自动微分就十分重要了。本文将一步步的从简单的手动求导一直谈到自动微分。


我们目前可以将微分划分为四大类:Manual Differentiation、Symbolic Differentiation、Numeric Differentiation、Automatic Differentiation。


Manual Differentiation

Manual Differentiation 正如字面意思所写,就是手动对函数求导。


比如下式就是个简单的函数。



对 x 求导可得:



对 y 求导可得:



这个例子很见到,只要了解基本的求导公式,都可以很迅速的解决。但是当我们面临的是一个极其复杂的公式时,整个过程将会非常繁琐,而且容易出错。


Symbolic Differentiation

为了避免人力的介入,首先提出了 Symbolic Differentiation 即符号微分。


下面也是个简单的例子:



符号微分方式如下图:



这个例子很简单,但是对于复杂函数会生成非常大的图,很难简化,有一定的性能问题。


更重要的是,符号微分无法对任意代码定义的函数进行求导,如下:



def my_func(a, b): z = 0 for i in range(1000): z = a * np.cos(z + i) + z * n return z
复制代码


Numeric Differentiation

那怎样才能对任意函数进行求导呢,于是引出了 Numeric Differentiation,顾名思义就是用数值去近似计算,求微分。


我们知道:




def f(x, y): return x**2*y + y + 2 def derivative(f, x, y, x_eps, y_eps): return (f(x + x_eps, y + y_eps) - f(x, y)) / (x_eps + y_eps)
df_dx = derivative(f, 3, 4, 0.00001, 0) # 24.000039999805264df_dy = derivative(f, 3, 4, 0, 0.00001) # 10.000000000331966
复制代码


数值微分里边,如上边的代码,我们至少需要执行三次 f(x,y),当我们的参数有 1000 个时就至少要执行 1001 次,在大规模的神经网络模型中,这样的做法是很低效的。不过数值微分比较简单,可以用来对手动求导的值进行验证。


Automatic Differentiation

Autodiff 算是在之前提到的这些方案基础之上得到的一个兼具性能和数值稳定的方案。


1. Forward-Mode Autodiff


  • Forward-Mode 是数值微分和符号微分的结合

  • 引入二元数ε, ϵ**2 = 0 ( ϵ ≠ 0)

  • 所以 f(x,y) 在(3,4)点对 x 的导数为ϵ前面的系数



forward-mode autodiff 比数值微分更准确,但是也有同样的问题,就是有 n 个参数要走 n 次图


2. Reverse-Mode Autodiff


为了解决 Forward-Mode 中需要根据参数进行图遍历的问题,提出了 Reverse-Mode Autodiff 方案。这也就是我们常说的链式法则、反向传播算法(machine learning 中我们常常将其等价)。


  • 第一遍,先从输入到输出,进行前向计算

  • 第二遍,从输出到输入,进行反向计算求偏导



  • Reverse-Mode Autodiff 在有大量输入,少量输出时是非常有力的方案

  • 一次正向,一次反向可以计算所有输入的偏导

  • 一个简易教学版的 Autograd 的实现:

  • https://github.com/mattjj/autodidact


3. 相关工程实现


Autograd 将 numpy 包了一层,提供与 numpy 相同的基础 ops,但自己内部创建了计算图



import autograd.numpy as npfrom autograd import grad

def logistic(z): # 等价形式 # np.reciprocal(np.add(1, np.exp(np.negative(z)))) return 1. / (1. + np.exp(-z))
print(logistic(1.5)) # 0.8175744761936437print(grad(logistic)(1.5)) # 0.14914645207033284
复制代码



① Vector-Jacobian Products


雅克比矩阵:



vector-Jacobian product (VJP)



对于每一个基本操作都需要定义一个 VJP。


primitive_vjps = defaultdict(dict)def defvjp(fun, *vjps, **kwargs):    argnums = kwargs.get('argnums', count())    for argnum, vjp in zip(argnums, vjps):        primitive_vjps[fun][argnum] = vjp

defvjp(anp.negative, lambda g, ans, x: -g)defvjp(anp.exp, lambda g, ans, x: ans * g)defvjp(anp.log, lambda g, ans, x: g / x)defvjp(anp.tanh, lambda g, ans, x: g / anp.cosh(x) **2)defvjp(anp.sinh, lambda g, ans, x: g * anp.cosh(x))defvjp(anp.cosh, lambda g, ans, x: g * anp.sinh(x))
复制代码


tracing the forward pass to build the computation graph 上边的代码是截取了 autodidact 的部分代码,像 negative 基本操作,求出倒数就是原来基础上取负。整个过程可以划分为三块。


  • vector-Jacobian products for primitive ops

  • backwards pass


再具体的细节就不粘贴了,有兴趣的同学可以访问我之前贴出的链接,几百行代码,麻雀虽小五脏俱全,非常适合学习。


Reference

  1. Géron, Aurélien. “Hands-On Machine Learning with Scikit-Learn and TensorFlow”

  2. https://www.cs.toronto.edu/~rgrosse/courses/csc321_2018/slides/lec10.pdf

  3. Autograd 的实现:

  4. https://github.com/mattjj/autodidact


本文来自 DataFun 社区


原文链接


https://mp.weixin.qq.com/s?__biz=MzU1NTMyOTI4Mw==&mid=2247494948&idx=1&sn=bd68530672340d263b1b62e25772de3b&chksm=fbd75f48cca0d65e9f808a04da399b62f2c2eeda309513fd04ceb16ac14b1123e2894065a530&scene=27#wechat_redirect


2019-11-10 08:001883

评论

发布
暂无评论
发现更多内容

anyRTC Native 4.1.0.1与Web SDK 4.0.11上线

anyRTC开发者

学习 WebRTC 语音 直播 sdk

LeetCode题解:155. 最小栈,单个栈存储入栈元素与最小值之差,JavaScript,详细注释

Lee Chen

大前端 LeetCode

揭开链表的真面目

Java旅途

Java 数据结构 链表

C语言内存泄露很严重,如何应对?

华为云开发者联盟

c 内存泄露 内存 代码 函数

技术分享:即构互动白板音视频同步、多端有序协作技术实践

ZEGO即构

音视频 在线教育 SVG

云原生如何来进行HTTPS升级

soolaugust

架构 云原生 设计模式

话题讨论 | 当你敲代码累了时,一般喜欢吃点什么补充能量?

InfoQ写作社区官方

加班 写作平台 代码 话题讨论

3种双集群系统方案设计模式详解

华为云开发者联盟

数据库 数据仓库 数据 双集群系统 双ETL模式

某程序员毕业进UC,被阿里收购!跳去优酷土豆,又被阿里收购!再跳去饿了么,还被阿里收购!难道阿里想收购的是他?

程序员生活志

职场 阿里

凡泰极客与Rancher达成深度战略合作,加速企业构建私有化小程序生态

FinClip

java安全编码指南之:对象构建

程序那些事

Java 安全 安全编码指南 对象构建

挽救你的视频号:能够把PPT转换成视频,把备注转换成语音的开源项目

陈磊@Criss

MAC系统初始化

焦振清

macos 重装系统

案例分享丨红外自动感应门设计与实现详解

华为云开发者联盟

物联网 传感器 感应探测器 SMT32处理器 感应门

华为云FusionInsight大数据技术普惠创新,释放千行百业数据价值

数据湖洞见

大数据 FusionInsight 华为云

面试必备知识点:悲观锁和乐观锁的那些事儿

鄙人薛某

面试 乐观锁 悲观锁 CAS 并发控制

Cassandra Gossip协议的二三事儿

华为云开发者联盟

源码 三次握手 开发者 Cassandra Gossip协议

人的转型才是关键 数字化时代你具备数字领导力么

CECBC

区块链 数字化时代

关于显性知识和隐性知识

Tanmer

知识管理 知识产权

读懂k8s 容器编排控制器 Deployment

Garfield

k8s pod k8s入门

你问我答:现有的应用有必要做微服务改造吗?

BoCloud博云

容器 DevOps 微服务 云平台 博云

深圳泰利能源有限公司涉嫌传销 共计2.7亿元

CECBC

区块链 基金

融云Geek Online 2020 编程挑战赛重磅来袭

InfoQ_967a83c6d0d7

拖延症竟然是自己给自己的一种奖励?如何干掉它?

非著名程序员

个人成长 拖延症 番茄土豆工作法

SpreadJS 纯前端表格控件应用案例:雨诺订单管理系统(雨诺OMS)

葡萄城技术团队

SpreadJS 纯前端表格控件应用案例:MHT-CP数据填报采集平台

葡萄城技术团队

Spring Bean处理器

语霖

Spring Framework

XSKY对象存储获全球备份领域领导者Commvault官方认证

XSKY融合存储

从 Node.js(JavaScript) 到 Golang,我的开发体验

Garfield

node.js Go 语言

SpreadJS 纯前端表格控件应用案例:表格数据管理平台

葡萄城技术团队

1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知

YourBatman

Hibernate-Validator Bean Validation 数据校验 JSR380

深度学习中的微分_AI_DataFunTalk_InfoQ精选文章