编程符号什么意思,编程符号的含义及用法

首页 > 经验 > 作者:YD1662022-11-18 01:03:22

导读

在深度学习中,我们经常会学习和使用到各种框架,如Facebook的pytorchGoogle的TensorFlow亚马逊的MXNet等。这些框架编程分格主要可以分为三大类,命令式编程符号式编程混合式编程。这篇文章,我们就来介绍一下它们不同编程分格之间的特点。

编程符号什么意思,编程符号的含义及用法(1)

命令式编程

Python的编程分格就是典型的命令式(imperative program)编程,在深度学习框架中pytorch就是用的命令式编程,下面我们使用命令式编程来写一段代码

def add(a, b): return a b def fancy_func(a, b, c, d): e = add(a, b) f = add(c, d) g = add(e, f) return g fancy_func(1, 2, 3, 4)

在调用fancy_func函数运行e=add(a,b)代码时,Python需要调用add方法做加法运算然后将运算结果保存到变量e中,然后再依次运行f=add(c,d)g=add(e,f)代码。

通过上面的代码可以发现在调用fancy_func方法的时候,add函数被重复调用了3次,同时在调用add函数的时候,还需要开辟空间来存储e、f变量,即使后面没有使用到这些变量。因为我们不知道下面究竟会不会使用到这些变量,所以只有当fancy_func函数执行结束的时候,才会释放变量所占用的空间。

命令式编程的特点

编程符号什么意思,编程符号的含义及用法(2)

符号式编程

符号式编程(symbolic program)框架的代表就是TensorFlow,除此之外还有TheanoCaffe。符号式编程需要在计算过程完全被定义好之后才被执行,通常符号式编程会根据下面这三个步骤进行:

  1. 定义计算流程
  2. 将计算流程编译成可执行的程序
  3. 给定输入,调用编译好的程序执行

下面我们来看一段符号式编程分格的代码

A = Variable('A') B = Variable('B') C = B * A D = C Constant(1) # 编译函数 f = compile(D) d = f(A=np.ones(10), B=np.ones(10)*2)

在执行上面代码中的C=B∗A时,并不会触发真正的数值计算,它会生成一个计算图

编程符号什么意思,编程符号的含义及用法(3)

大部分的符号式编程都会有一个隐性或显性的编译步骤,只有编译之后的函数才能够调用,所以在上面的代码中只有最后一行才会触发数值计算。在编译的过程中,系统会自动对计算和内存做一些优化,而且符号式编程不会保存中间变量的结果,所以相对于命令式编程来说,符号式编程的计算效率和内存利用更高。除此之外,符号式编程可以将程序编译成一个与Python无关的函数,从而可以使程序在非Python环境下运行,避免Python解释器的性能问题

符号式编程的特点:

混合编程

大部分的深度学习框架都是在命令式编程和符号式编程二选一,要么选择便于调试和开发的命令式编程要么选择执行高效的符号式编程混合编程的目的就是命令式编程和符号式编程的长处,让开发者能够享受到命令式编程简洁特性同时能够享受到符号式编程的效率

MXNetgluon正是基于混合式编程的思想,用户可以使用纯命令式编程进行开发和调试当用户需在部署时需要产品级的性能时可以将大部分命令式编程程序转换为符号式编程运行

编程符号什么意思,编程符号的含义及用法(4)

计算性能比较

最后,我们通过MXNet框架来实现一段代码体验一下命令式编程和符号式编程之间的性能差距

from mxnet import nd,sym from mxnet.gluon import nn import time #创建一个容器用来定义网络结构 net = nn.HybridSequential() #定义一个三层全连接的网络结构 net.add(nn.Dense(256,activation="relu"), nn.Dense(128,activation="relu"), nn.Dense(2)) #初始化网络参数 net.initialize() #创建一个网络的输出值 x = nd.random.normal(shape=(1,512)) def eval_fun(net,x): start_time = time.time() for i in range(1000): _ = net(x) #等待所有计算完成 nd.waitall() #统计程序运行时间 return time.time() - start_time print("imperative programe consume time:{:.4f}".format(eval_fun(net,x))) #将程序转变为符号式编程 net.hybridize() print("symbolic programe consume time:{:.4f}".format(eval_fun(net,x))) """ imperative programe consume time:0.2620 symbolic programe consume time:0.1610 """

通过上面程序可以发现,上面程序仅仅只是测试了前向传播符号式编程的运行速度要比命令式编程快0.1s左右,而且上面只是一个三层的网络也仅仅只是迭代了1000次,实际应用的网络结构会比这个复杂的多,当数据比较多时迭代次数也会远远大于1000,实际运行能节省的时间远不止这么一点

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.