观点 | TensorFlow sucks,有人吐槽TensorFlow晦涩难用

选自nicodjimenez

机器之心编译

参与:李泽南、刘晓坤

作为当今最流行的深度学习框架,TensorFlow 已经出现了两年之久。尽管其背后有着谷歌这样的科技巨头支持,但它的很多缺点已经开始显现。本文作者,创业公司 Mathpix 的首席执行官 Nicolas D. Jimenez 试图向我们全面分析 TensorFlow 的缺点。

每隔几月,我都会向谷歌的搜索框里键入「TensorFlow sucks」或「f**k TensorFlow」,期待能在互联网上找到和我志同道合的人。不幸的是,尽管 TensorFlow 已经出现了两年之久,我们还是很难找到一篇能够全面「冷静评价」TensoFlow 的文章。

或许这是因为我用了一个错误的搜索引擎?应该不是这样,我认为原因在于谷歌信仰。全球的工程师们或多或少都有一点对于谷歌的盲目崇拜,表现在于认为:

  • 在谷歌工作的人比自己更聪明

  • 如果用好 TensorFlow,或许能在谷歌找到一个深度学习的工作(继续做梦吧少年)

  • 如果你的创业公司使用的深度学习框架是 TensorFlow,而你的博客宣扬了它的优点,谷歌或许会考虑来收购你

  • 如果你 get 不到 TensorFlow 的优点,那你就是不懂事

  • 但我们还是要客观,让我们抛弃以上假设,还原 TensorFlow 的真面目吧。

    当 TensorFlow 刚刚出现时,它的开发者们承诺将会结束深度学习框架缺乏维护的阴暗时代(看看 http://github.com/BVLC/caffe/issues 吧)我们或许会得到一个像 Java 一样的深度学习框架(写出来就可以在任何地方使用),虽然不怎么有趣,但有一个纯粹的陈述范式。然而,事情好像并没有这么顺利。

    究竟哪里出错了?为了构建一个能让所有人都满意的产品,谷歌似乎只做到了在所有方面都一般般的结果。

    对于研究人员来说,TensorFlow 难以学习和使用。研究只关乎灵活性,而缺乏灵活性正是根植于 TensorFlow 的特性之一。

    想要提取神经网络中间层的数值?你需要定义一个图,然后以字典的形式传递数据,同时不要忘了在图的中间层添加输出,否则你将无法获得它的值。虽然这很麻烦,但还是可行的。

    想要有条件地执行几个层?比如让 RNN 在句子末端(EOS)生成表征时停止?到你学会使用 PyTorch 做这件事的时候,你可能已经身处第三家摇摇欲坠的创业公司了。对于像我这样的机器学习从业者而言,TensorFlow 也并不是一个绝佳的选择。框架的声明特性使调试变得更加困难。能够让模型运行在安卓和 iOS 上的能力看起来很美好,但当你看到框架二进制文件的大小(20Mb 以上)后就不那么想了。或许你会尝试寻找那几乎不存在的 C++说明文档,或者尝试加入任何类型的条件网络执行——它们在移动端这种计算资源缺乏的情况下比较好用。

    对比其它的框架

    确实 TensorFlow 的开发者都是深度学习的超级巨星。然而,最为出名且受人尊敬的 TensorFlow 的最初开发者贾扬清,离开了谷歌而加入了 Facebook,在那里他的 Caffe2 项目正在快速推进。和 TensorFlow 不一样,Caffe2 允许用户只用一行代码就能为数据创建一个层,非常激进的革新!

    此外,Pytorch 在顶级的 AI 研究者中推广的很迅速。虽然 Torch 用户需要编写 Lua 代码执行简单的字符串运算以防止 RSI 损伤,不过并没有完全抛弃 TensorFlow,只是转换成了 PyTorch。看来 TensorFlow 对于顶级的 AI 实验室来说只是不够好而已。抱歉了,谷歌。

    我最感兴趣的是为什么谷歌会在 TensorFlow 中选择完全陈述范式而不顾这种方法的明显弊端。他们是不是觉得把所有的计算压缩进单一的计算图会简化在 TPU 上执行模型,从而可以省下英伟达提供的云端驱动深度学习芯片的几百万美元的费用吗?很难说。总之,对公众来说,TensorFlow 并不像是一个完全开源的项目,我很同意。虽然设计精巧,但比起谷歌那些漂亮的的开源项目如 Protobuf,Golang 和 Kubernetes,TensorFlow 实在差的太远。

    虽然陈述范式对于 UI 编程很有用,但是对于深度学习而言,这个选择造成了困难,有这么几个原因。

    以 React Javascript 库为例,这是今天交互网页应用的标准选择。在 React 中,数据在应用中流通的复杂过程对开发者来说是不可见的,这很合理,因为 JavaScript 的执行通常比 DOM 的更新快得多。只要终端用户体验足够好,React 的开发者并不关心状态传播的机制。

    另一方面,在深度学习中,一个层就需要用到几百万 FLOP。而且深度学习研究者都很关心计算过程的机制,并希望能很好的控制过程,因为他们随时都在扩大可能性的边缘(比如动态网络),并希望能很容易获取中间结果。

    一个实例

    我们看看这个简单的例子,通过训练模型使其将输入乘以 3。

    首先看看 TensorFlow 的例子:

  • import tensorflow as tf

  • import numpy as np

  • X = tf.placeholder("float")

  • Y = tf.placeholder("float")

  • W = tf.Variable(np.random.random(), name="weight")

  • pred = tf.multiply(X, W)

  • cost = tf.reduce_sum(tf.pow(pred-Y, 2))

  • optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)

  • init = tf.global_variables_initializer()

  • with tf.Session() as sess:

  •    sess.run(init)

  •    for t in range(10000):

  •        x = np.array(np.random.random()).reshape((1, 1, 1, 1))

  •        y = x * 3

  •        (_, c) = sess.run([optimizer, cost], feed_dict={X: x, Y: y})

  •        print c

  • 接下来看看 Pytorch 的例子:

  • import numpy as np

  • import torch

  • from torch.autograd import Variable

  • model = torch.nn.Linear(1, 1)

  • loss_fn = torch.nn.MSELoss(size_average=False)

  • optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

  • for t in range(10000):

  •    x = Variable(torch.from_numpy(np.random.random((1,1)).astype(np.float32)))

  •    y = x * 3

  •    y_pred = model(x)

  •    loss = loss_fn(y_pred, y)

  •    optimizer.zero_grad()

  •    loss.backward()

  •    optimizer.step()

  •    print loss.data[0]

  • 虽然 PyTorch 的例子比 TensorFlow 少一行代码,但其中的计算过程要更加清晰易懂,训练循环中的句法和真实的学习过程要匹配得多:

    1. 输入的前向传递

    2. 生成损失

    3. 计算梯度

    4. 反向传播

    而在 TensorFlow 中核心的算子是像魔术一般呼叫 sess.run。

    你真的想写更多行,但是又很难理解和维护的代码吗?PyTorch 的接口从客观上讲比 TensorFlow 要好得多。

    结论

    通过 TensorFlow,谷歌成功创造了一个完整的深度学习框架,但它同时也太过难以使用,过于低级,不适用于快速进行原型设计;对于尖端研究和资源驱动的生产环境来说又过于高级。

    老实说,当你意识到已经有六个开源的高级库是建立在已经是高级库的 TensorFlow 的基础上——才能让一切变得可用起来——这里面的问题就不是一星半点了:

  • http://tflearn.org/

  • http://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim

  • http://github.com/fchollet/keras

  • http://github.com/tensorflow/skflow

  • 注意:我得承认 Tensorboard(TensorFlow 的监视工具)非常棒。但如果你你想找到一个完美的机器学习项目监控解决方案,其中包含深度模型对比特征,你可以试试 Losswise(http://losswise.com/)。我开发它就是为了让我这样的人能够轻松解耦并追踪使用所有库的模型的表现,我也实现了 Tensorboard 不能提供的很多有用特性。观点 | TensorFlow sucks,有人吐槽TensorFlow晦涩难用

    原文链接:http://nicodjimenez.github.io/2017/10/08/tensorflow.html

    本文为机器之心编译,转载请联系本公众号获得授权

    ?------------------------------------------------

    加入机器之心(全职记者/实习生):hr@jiqizhixin.com

    投稿或寻求报道:content@jiqizhixin.com

    广告&商务合作:bd@jiqizhixin.com