用梯度下降算法训练神经网络的时候,求导过程是其中的关键计算之一。使用Tensorflow的用户会发现,神经网络的反向传播计算是用户不用考虑的,在给足便捷性的同时也抑制了用户对反向传播的探索心态(博主深受其害)。Tensorflow同时也激起了一个思考:一定存在某种求导的通用方法。


这篇文章主要探索编程求导的通法

  • 文章代码实现均为Python3.6.4
  • 使用模块numpy,sympy

方法1: 定义导函数:

对于函数:y=x2y=x2y=x^2
其导数为:y′=2∗xy′=2∗xy' = 2*x
对于函数:y=sin(x)y=sin(x)y=sin(x)
其导数为:y′=cos(x)y′=cos(x)y' = cos(x)
这里的导函数都需要开发者自己用笔算出来,然后用代码表示出来。为什么可以这么做? 因为神经网络里用到的函数种类有限,我们可以把所有的函数导函数都预先定义出来。如下:

# 目标函数:y=x^2
def func(x):return x**2# 目标函数一阶导数:dy/dx=2*x
def dfunc(x):return 2*x

来看这篇文章的,估计不是为了得到这个答案,为的是解决一般情况的求导公式。而且对于千变万化的loss function,每次都自己手动求导就很麻烦了。
      CSDN上有不少讲解求导的文章,有码友说通过把各种常见基本函数的导数定义好,然后对任何复杂函数进行分解,再查表调用基本函数的导函数,例如y=sin(x)+x2y=sin(x)+x2y = sin(x)+x^2 拆分成两个基本函数y1y1y1=sin(x)sin(x)sin(x)和y2=y2=y2=x2x2x^2。事实上,这种做法也很难,分解复杂函数是最大的难点。比如y=sin(x2/x)y=sin(x2/x)y=sin(x^2/x),这要怎么通过一般式分解呢,当然可以分解,不过分复杂。博主认为,这种思路明显把这个问题弄复杂了。
这种方法,归根结底还是属于查表法

是否认真想过,求导计算能不能用非查表法解决?


方法2:使用专门求导模块

python提供了一个十分好用的求导模块sympy,当然并不是唯一能用来求导的模块。
这个求导方法如下:

from sympy import *
x = Symbol("x") # 把"x"设置为自变量
fu = diff(x ** 2, x) # 求导x^2
print(fu)

输出:

2*x

可以试着把原函数写复杂点: y=sin(x2/x)y=sin(x2/x)y=sin(x^2/x)
改为fu = diff(sin(x**2)/x, x)
输出为:

2*cos(x**2) - sin(x**2)/x**2

可以发现:这个方法可以求解复杂函数的导数。
其实这个方法还有若干缺陷:输入的x只能是数,不能是numpy数组。我们知道,当进行反向传播的时候,输入往往都是数组。此外,很多函数并不是用函数表达式来表示的(下面会举例),没有确切的函数表达式是无法使用这个方法来求导的。

# 目标函数:y=x^2
def func(x):return np.square(x)

如上,这个函数没有确切的函数表达式(虽然知道是y=x2y=x2y=x^2,但无法用这种办法求导)
如果向导函数输入数字:

from sympy import *
x = Symbol("x")
fu = diff(sin(x**2) / x, x)
print(fu.subs('x', 3))

输出: 6
如果向导函数输入数组:

from sympy import *
a = np.array([[1,3,5,7],[7,7,0,0]])
x = Symbol("x")
fu = diff(sin(x**2) / x, x)
print(fu.subs('x', a))

输出: 2∗x2∗x2*x
可见,这种方法无法把数组当作输入。只能把数组的每一个元素抽出来作为单独的数输入到导函数中求解,这种操作非常慢(矩阵计算可以用GPU并行执行,而转换成单独的数字就不能利用GPU的并行性了)。


方法3. 通过导数的数学定义求导

方法2可以让高数初学者验证自己求导是否正确。方法3可以在实际过程中解决问题:计算速度和精度都达到不错的程度。这就是所谓的“无敌”方法。导数定义如下:

f′(x)=limΔx→0[f(x+Δx)−f(x)]/Δxf′(x)=limΔx→0[f(x+Δx)−f(x)]/Δx

f'(x) = \lim_{\Delta x\rightarrow 0} [f(x+\Delta x)-f(x)]/\Delta x
直接用一个很小的数来代替 ΔxΔx\Delta x就可以在计算机上实现这个求导公式了。
实现代码如下:

def derive(f):dx = 0.0000000001return lambda x: (f(x + dx) - f(x)) / dx

对,这种方法并不能给你返回一个导函数公式,你输入x2x2x^2并不能返回2∗x2∗x2*x。但在计算机系统中,求导计算并不需要你准确的导函数公式,只要导函数函数值的计算精度高便可以使用。这种方法,尤其在神经网络的方向传播中十分有用!
具体怎么使用呢,我们可以改造一下上面的例子:

# 目标函数:y=x^2
def func(x):return np.square(x)# 目标函数一阶导数:dy/dx=2*x
def dfunc(x):return derive(func)(x)def derive(f):dx = 0.0000000001return lambda x: (f(x + dx) - f(x)) / dx

可以看出这里的derive方法可以通用。但是呢,这种方法有点点缺陷说明一下:满足数学意义上具有可导性的函数才能用这种方法求解,比如Relu(x)函数,它在x=0处不可导,那么我们需要对它人工分段,不然可能会有尖刺。虽然对最后结果影响几乎没有,不过注意一下还是好的。

【AI数学原理】函数求导(精髓篇)相关推荐

  1. java二维矩阵怎么进行转置_矩阵求导的本质与分子布局、分母布局的本质(矩阵求导——本质篇)...

    〇. 前言 在一个多月前,针对有同学关于矩阵求导中分子布局.分母布局两者的区别的疑问,我写了如下的这篇答案. 矩阵求导中布局约定,两者布局的意义是什么?​www.zhihu.com 虽然这篇答案给出了 ...

  2. python编程求导数_面向对象编程 —— java实现函数求导

    首先声明一点,本文主要介绍的是面向对象(OO)的思想,顺便谈下函数式编程,而不是教你如何准确地.科学地用java求出函数在一点的导数. 一.引子 defd(f) :defcalc(x) : dx= 0 ...

  3. java 求导函数_面向对象编程 —— java实现函数求导

    文章目录 首先声明一点,本文主要介绍的是面向对象(OO)的思想,顺便谈下函数式编程,而不是教你如何准确地.科学地用java求出函数在一点的导数. ★引子 defd(f) :defcalc(x) : d ...

  4. AI基础:矩阵求导,你一定要收藏

    不得不说,向量和矩阵真的是一门高深而又通用的学问,应用十分广泛,不信你可以往回看,前面有关线性代数的文章,哪一篇没个矩阵或者向量.所以呢,我们今天就来看一下向量的导数(矩阵求导)相关内容. 1.定义和 ...

  5. sympy 符号函数求导

    原文链接: sympy 符号函数求导 上一篇: python 一阶线性拟合 下一篇: python 非线性方程组 使用sympy 对指定函数表达式求值和求指定位置的导数 from sympy impo ...

  6. 线性代数之 矩阵求导(2)标量函数求导基本法则与公式

    线性代数之 矩阵求导(2)基本法则与公式 前言 基本约定 标量对向量求导 基本法则 公式 标量对矩阵求导 基本法则 公式 后记 前言 上篇矩阵求导(1)解决了求导时的布局问题,也是矩阵求导最基础的求导 ...

  7. java对三次函数求导_如何画三次函数图像

    问题 请绘制 的图形 思路一 借助软件 软件名称 介绍 geogebra image.png GeoGebra是自由且跨平台的动态数学软件,提供各级教育使用,包含了几何.代数.表格.图形.统计和微积分 ...

  8. 第二章:1、函数求导

    机器学习中问题的求解往往转化为优化问题. 1.函数极限 函数的导数是通过极限来定义和表达的.极限理解: 向量的2范数:表示点到原点的欧氏距离,就是向量的长度.点的邻域表示以点a为心,以为半径的一个d维 ...

  9. sigmoid函数求导与自然指数

    sigmoid函数求导与自然指数 在神经网络里经常使用sigmoid做激活函数,它的导数是怎么样求解呢?因为要使用它的导数来计算梯度下降. 这个过程如下: 1. sigmoid 函数:f(z) = 1 ...

  10. python求导函数的值_python怎么实现函数求导

    python实现函数求导的方法是:1.利用sympy库中的symbols方法传入x和y变量:2.利用sympy库中的diff函数传入需要求导的函数即可返回求导之后的结果. python利用sympy库 ...

最新文章

  1. Android Studio报错解决:droid.tools.idea.welcome.install.WizardException: SDK tools directory is missing
  2. 从具体案例了解知识图谱
  3. HDOJ1035 ( Robot Motion ) 【递归】
  4. AI应用开发实战 - 手写识别应用入门
  5. moment.js 快捷查询
  6. Java:可选的可选实现
  7. jslint4java_JSLint检测javascript的错误提示
  8. 第二十二章 6未命名的命名空间
  9. C/C++ _wcsupr_s 函数 – unicode 字符串小写转大写 - C语言零基础入门教程
  10. 【ModelArts-Lab AI实战营】使用Postman测试Modelarts在线服务(图像分类、物体检测)
  11. 华为机试HJ3:明明的随机数
  12. postgres的序列(Sequence)的使用
  13. 盒子模型之边框border
  14. Rtsp之H265解析
  15. OSPF NSSA区域路由的计算过程与FA值实验
  16. paip.网页右键复制菜单限制解除解决方案
  17. mysql select trim_mysql trim函数用法举例
  18. mysql 数据库管理认证_走进mysql数据库认证证书
  19. 2022PMP考试敏捷知识点(3)
  20. 动作捕捉助力无人车多源传感器信息融合导航技术

热门文章

  1. python解压带密码的rar文件_Python实现加密的RAR文件解压的方法(密码已知)
  2. 基于E-Mail的隐蔽控制:机理与防御
  3. win10系统崩溃怎么修复_系统崩溃!win10系统修复和数据恢复方法总结
  4. DevOps 在公司项目中的实践落地
  5. 过河孙小弟scratch
  6. 进击ReactNative-徐如林-React源码解析
  7. HTML图片的空隙解决
  8. 投屏设置 android,上班摸鱼神器 Anlink安卓手机投屏操作体验
  9. 文件被别的程序打开无法删除怎么办?
  10. 苹果电脑mac桌面上出现关不掉的黑框/白框 解决办法