一个c++或者java,python程序员,一开始接触到tensorflow,必然会被其运行方式所迷惑。 因为tensorflow是先构图,再执行。c=tf.add(a,b),在执行这行代码时,只是在构图,并没有进行计算。所以进行print(c)时,只是打出来了未计算的结点引用。
然而,tensorflow这种先构图再计算的方式,并不是首创。像spark, flink这两个计算引擎也是先构图再执行。因此构图也是一种解决问题的模式。 而且还能进行图优化,非常适合分布式计算任务。在游戏引擎中大名鼎鼎的UE4引擎,支持蓝图式编程。可以看作是手动构图。非常适合非程序员职业的人构建程序。而tensorflow是用python去构图,还是有一定的门槛。
从tensorflow2.0开始默认会启动Eager, 这种eager模式下,所有计算会立即执行,非常方便调试。
下面以一个计算1+2+3+...+100的例子来演示它们的区别。
普通python计算
sum = 0 #变量sum用于累计
for i in range(1, 101): #1到100
sum += i
print(sum) #输出5050
ue5蓝图 蓝图是手动构建图。不用编程。
文章图片
文章图片
tensorflow while_loop的核心要求,conditiion, loop_body的输入参数就是loop_vars
loop_body返回值也必须是loop_vars, 参数数量必须一样
condition的返回值是bool类型的tensor
while_loop返回的也是loop_body最后返回的
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
tf.disable_eager_execution ()def condition(i, v): #循环结束条件
return i <= 100def loop_body(i, v):
return i + 1, v + i #输入i,v,返回必须也是两个形状类型相同的tensor,会再次输入i, v = 1, 0 #初始循环变量值
ii, vv = tf.while_loop(condition, loop_body, loop_vars=[i, v]) #这里相当于ue5中蓝图里的for_loop结点#以上是构图,下面执行图得到结果
with tf.Session() as sess:
print(sess.run([ii, vv]))#最后输出:[101, 5050]
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
tf.disable_eager_execution ()i = tf.Variable(1)
v = tf.Variable(0)def condition(i, v):
return i <= 100def loop_body(i, v):
i += 1
v += i
return i, vii, vv = tf.while_loop(condition, loop_body, loop_vars=[i, v])init_op = tf.global_variables_initializer()
#导出图
summary_writer = tf.summary.FileWriter('tb_log/',flush_secs=1)
with tf.Session() as sess:
sess.run([init_op])
print(sess.run([ii, vv]))
summary_writer.add_graph(sess.graph)#添加graph图
summary_writer.close()#运行tensorboard
#tensorboard --logdir tb_log
#然后打开浏览器就能查看:http://localhost:6006/#graphs&run=.
文章图片
从图中可以看出,两个变量分别是i,v。while中的两个add和一个less_equal对就了loop_body,和condition
加上变量名再展示会更好:
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
tf.disable_eager_execution ()i = tf.Variable(1, name="i")
v = tf.Variable(0, name="v")def condition(i, v):
return tf.less_equal(i, 100, name="ile100")def loop_body(i, v):
i = tf.add(i, 1, name="addi")
v = tf.add(i, v, name="addiv")
return i, vii, vv = tf.while_loop(condition, loop_body, loop_vars=[i, v])init_op = tf.global_variables_initializer()
summary_writer = tf.summary.FileWriter('tb_log/',flush_secs=1)
with tf.Session() as sess:
sess.run([init_op])
print(sess.run([ii, vv]))
summary_writer.add_graph(sess.graph)#添加graph图
summary_writer.close()
文章图片
Spark DAG 如下代码,只有在执行collect时才真正开始提交运行图。而上边的代码都是在构图,实际并未运行
文章图片
Flink DAG
文章图片
Flink 原理与实现:架构和拓扑概览
flink中级篇-DAG图的剖析_kangzai98的博客-CSDN博客_dag图解析
C++也能构图后延时计算:boost phoniex 看到下图中的for_,是延时执行的。采用lambda延时计算技术,可以达到类似构图再计算的效果。
for_ Statement - 1.64.0
#include
int iii;
std::for_each(c.begin(), c.end(),
(
for_(ref(iii) = 0, ref(iii) < arg1, ++ref(iii))
[
cout << arg1 << ", "
],
cout << val("\n")
)
);
使用计算图的优势 1. 图是抽象的,与实现无关:比如tf.add这么一个OP, 也就是图中的一个结点.只是定义了一个加法和其输入输出参数,多个结点连接形成的计算图也是抽象的描述了整个计算程序。可看做是声明式编程的一种方式。
2. 不同平台不同实现:图构建好后,可以直接跨平台运行。不同平台只要实现自己的add kernel即可。特别的,比如GPU与CPU的实现可能不同。ARM和x86实现不同。服务器与Android客户端可以实现不同。
3. 优化与剪枝:可以对图进行各种优化,提高性能
4. 分布式并行计算:分析图可以得到哪些计算可以并行,就可以调度到不同机器上并行计算机。同样图可以分块拆解,并放到不同机器上执行。
例如PS-Worker架构,就是把图中的variable等存储结点拆解到PS上。而计算结点拆解到Worker上,并在中间插入通信代码。可见计算图做这种事十分方便。相反,如果是一段C++或者python代码,想这么做就很困难。
【tensorflow|tensorflow运行模式】可以计算图是受限制的代码。每个结点看做一个抽象的函数。在计算图中没有面向对象编程,也无法搞复杂设计模式。其简单性能,边界性虽然给实现功能带来了困难,但是,给分布式执行,自动优化等提供了方便。
推荐阅读
- opencv|从OpenCV人工智能竞赛看计算机视觉应用的5个新兴趋势
- tensorflow API _ 2 (tf.app.flags.FLAGS)
- 深度学习|TensorFlow 对数据集标记的xml文件解析记录
- #|MobileViT(A mobile-friendly Transformer-based model for image classification)
- ai|14岁上中科大,18岁攻读麻省博士,28岁成为哈佛最年轻副教授,“华人女天才”的开挂人生...
- 如何使用tensorflow for mobile,开发环境为android studio
- android things sample(sample-tensorflow-imageclassifier)测试
- 人工智能|一程序员被网恋女友诈骗1.8万,警方调查“女友”后发现竟是...
- 深度学习|TensorFlow惊现大bug(网友(这是逼着我们用PyTorch啊!))