Press "Enter" to skip to content

给 TensorFlow 初学者或害怕複杂 API 的人的学习建议

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

前言

 

如果你有使用过 (以下简称 TF),特别是很前期的 API,你有很高机率也经历过一段痛苦的学习经验,有这种体验的你并不孤单,一方面是 TF low-level API 的使用逻辑不是很符合直觉(API 文件也写得不是很清楚),另一方面是随着 TF 的演进,同样的目的,做法可能有好几种,所以在网路上 google 程式码的时候,可能会被各种不同的写法搞得头昏眼花(tf.layer、tf.estimator、tf.keras 或直接用 low-level API 实现),这些模模糊糊的观念全部搅在一起,最后得到一团 TF 浆糊。

 

 

不过,TF 仍然是一个很强大的工具,也因为有这个工具,只要找到好的学习方法,使用得当,还是可以节省大家未来很多时间,所以,就让我尝试写一篇文章,来试图减缓一下 TF 的学习曲线吧!

 

这篇文章的目的纯粹是为了降低 TF 的学习难度,如果你想直接用 PyTorch 等其他工具,那也很好。

 

入门建议

 

根据我使用过 Caffe、Tensorflow 跟 PyTorch 的经验,我觉得能够从 high-level API 入门是很重要的,因为刚开始实作各种 neural network(以下简称 NN),从最 high-level 的角度去看才能有掌握整体的感觉,所谓 high-level,就是你只需要看到这个 NN 的 input/output 是什幺、中间层有几层、loss/optimizer 是什幺,然后就开始往你的目标前进。

 

以 tf.keras 的 API 举例,假设你想要分类 MNIST dataset 里面的手写数字,最核心的 model 定义就像下面这样( 完整 source code 见此 ):

 

# 定义 model
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
  tf.keras.layers.Dense(128,='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
# 指定 loss、optimizer
model.compile(
    loss='sparse_categorical_crossentropy',
    optimizer=tf.keras.optimizers.Adam(0.001),
    metrics=['accuracy'],
)
# 开始 train model:使用 ds_train dataset,跑 6 个 epoch
#                  使用 ds_test 做 validation
model.fit(
    ds_train,
    epochs=6,
    validation_data=ds_test,
)

 

是不是很直觉呢?原因是,上面的 code 跟你脑海中,NN 是怎幺建构、进而开始训练的 flow 是很接近的。

 

可是,如果使用比较 low-level 的 API,你会不自觉地被迫离开 “只在乎 NN 基本 flow” 的状态,同样以一个可以分类 MNIST 数字的 model 为例,只是这次是用 low-level API( 完整 source code 在此 ):

 

# 定义 model
def neural_net(x):
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
    layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer
# 建立 model 的输出
logits = neural_net(X)
prediction = tf.nn.softmax(logits)
# 指定 loss、optimizer
loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits=logits, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
# 把 optimizer 跟 loss_op 接起来(嗯,已经开始有点不直觉了,有 predictions、又有 loss_op、现在还要多一个 train_op,怎幺那幺多层)
train_op = optimizer.minimize(loss_op)
# 指定初始化 model 参数的负责人
init = tf.global_variables_initializer()
# 準备开始 training(hmmm....session 是啥?)
with tf.Session() as sess:
    # 初始化 model 参数
    sess.run(init)
    for step in range(1, num_steps+1):
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # 实际 training
        sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})

 

虽然乍看之下,大部分东西都一样啊,可是,写程式是一个很要求精确的心理活动,虽然只有几个小地方阅读起来不顺畅,但这种不清楚知道所有事情的感觉会让心里的模糊资讯增加,最后就会让更大的程式变成一团混乱。

 

你可能会说,上层的 API 把一堆东西都包起来,以透彻理解系统的角度来说,其实还不是很不精确?

 

确实没错。但是,我觉得使用工具的一个重点就在于,你不需要知道这个工具的所有细节,只要理解到一定程度,能利用这个工具达成目的就好,而包得好的 API 就是让你很自然地不需要想到工具的细节。以笔电为例,如果你今天想要写程式,你只需要开机、打开 IDE,就可以开始写程式,是因为开机跟打开 IDE 都已经被包成很 high-level 的行为了。假设现在电脑还很原始,你为了开机,得找出对的电线,把对的电线接起来,还要插上开机磁碟,才能开机,写程式这项 task 的複杂度是不是突然就上升很多?High-level API 的重点就在于降低 task 的複杂度,除非必要,不然你只要会按开机按钮跟开 IDE 就好。

 

所以,我个人很推荐从 tf.keras 开始,因为他的 API 让使用上很符合直觉,你就不需要费太多心思去管 high-level flow 以外的细节。事实上,这也是 TF 目前官方 tutorial 给初学者的建议,但基于我的经验,还是希望把这段分析写出来,如果你也曾经被 TF 吓到过,tf.keras 是一个让你重拾 TF 的好东西。

 

顺带补充一下,如果你有听过 Keras,好奇 Keras 跟 tf.keras 的关係,可以看看这篇 – Keras vs. tf.keras: What’s the difference in TensorFlow 2.0? 。但你如果懒得看,简单 summary 就是,用 tf.keras 就对啦!

 

理解 computational graph

 

上面的 low-level API 範例中,有看到 session 这个东西,其实 session 这个东西,只要你了解 computational graph,就非常直观,而这也是在写 TF code 的时候一定要很清楚的基本观念。

 

避免重複花时间说明别人已经讲得很清楚的东西,直接上个影片,看完就能了解 computation graph 是什幺:

 

 

然后如何跟 session 的观念接起来,请看: The Low/Mid-Level API: Building Computational Graphs and Sessions 。用一句话说就是,先建立好 computation graph,然后 session 会执行你建立的 graph。

 

了解其他 API 的定位

 

TF 的其中一个强大之处,在于他有很多 API,但这也大大增加了这个工具的複杂度,让学习曲线大幅变陡。而为了在学习新的 API、或是上网找各种解答时不混乱,心中有个大地图是非常重要的:

 

 

有这个大地图,你未来在看到各种 API 就不会混乱,你可以先找出那个 API 的定位,想想是不是你需要的,如果不是你要的,那就不需要去弄懂,你也就不会有觉得有很多东西要学的混乱感。上图出自 Ekaba Bisong 的网站

 

最后建议 – 观察你最想从什幺 project 开始玩

 

上面说了这幺多,归根究底也只能稍微帮助大家更容易上手 TF。要能灵活应用,还是要动手多用 TF 去做你有兴趣的 project,然后在过程中,自然会学会越来越多 TF 的细节,这样你就能找到专属于自己的 TF 学习道路!

 

总结

 

以上是我觉得要把 TF 学好的几个重点,也鼓励大家在看这篇文章的时候,meta-learning 一下,想想看自己有没有学习其他东西很卡的经历,如果有,那很卡的原因是什幺呢?能否也像上面拆解学 TF 很卡的原因一样拆解开来?

 

例如你是不是从太困难的路径开始学习,也许能找到其他教学或比较简单的起点?还是你可能缺少了一些基本的重要观念,使得很多东西看起来都不直觉?又或是你心中没有一个大地图能帮你定位看到的各种东西,所以你越学越混乱?

 

当你对 meta-learning 越来越有经验,你就能越来越有效率地移除自己学习路上的障碍,不仅省下大量时间,也减少过程中的痛苦。祝大家都能越来越会 meta-learning,天天学习,天天开心!

Be First to Comment

发表评论

邮箱地址不会被公开。 必填项已用*标注