以下练习题来自机器学习实战:基于Scikit和Tensorflow一书。

  1. 相比直接执行计算,创建计算图的最大优点是什么?最大的缺 点呢?
    答:主要优点:1.TensorFlow可以自动计算梯度(通过反向的autodiff)2.TensorFlow负责在不同的线程中并行执行各个操作3.它可以更容易地在多设备上运行同一个模型 4.它简化了查看,比如,在TensorBoard上查看模型
    主要缺点: 1.学习曲线陡峭 2.逐步的调试比较困难

  2. 语句a_val=a.eval(session=sess)和a_val=sess.run(a)等价吗?
    答:是的,语句a_val=a.eval(session=sess)a_val=sess.run(a) 完全相等。

  3. 语句a_val,b_val=a.eval(session=sess),b.eval(ses sion=sess)和a_val,b_val=sess.run([a,b])等价吗?
    答:语句a_val,b_val=a.eval(session=sess),b.eval(ses sion=sess)不等于a_val,b_val=sess.run([a,b])。第一条语句会运 行两次(第一次计算a,第二次计算b),而第二条语句只运行一次。 如果这些操作(或者它们依赖的操作)中的任意一个具有副作用(比 如,修改一个变量,向队列中插入一条记录,或者读取一个文件 等),那么效果就会不同。如果操作没有副作用,那么语句会返回同 样的结果,不过第二条语句会比第一条快。

  4. 你可以在同一个会话中运行两个图吗?
    答:你无法在同一个会话中运行两个计算图。你需要将两个图合并为一个大图

  5. 假设你创建了一个包含变量w的图,然后在两个线程中分别启 动一个会话,两个线程都使用了图g,每个会话会有自己对w变量的 拷贝,还是会共享变量?
    答:在本地TensorFlow中,会话用来管理变量的值,如果你创建了 一个包含变量w的图g,然后启动两个线程,并在每个线程中打开一 个本地的会话,这两个线程使用同一个图g,那么每个会话会拥有自 己的w的拷贝。如果在分布式的TensorFlow中,变量的值则存储在由 集群管理的容器中,如果两个会话连接了同一个集群,并使用同一个 容器,那么它们会共享变量w。

  6. 变量何时被初始化,又在何时被销毁?
    答: 变量在调用其初始化器的时候被初始化,在会话结束的时候被 销毁。在分布式TensorFlow中,变量存活于集群上的容器中,所以关 闭一个会话不会销毁变量。要销毁一个变量,你需要清空它所在的容 器。

  7. 占位符和变量的区别是什么?
    答:变量是包含一个值的操作。你执行一个变量,它会返回对应的 值。在执行之前,你需要初始化变量。你可以修改变量的值(比如, 通过使用赋值操作)。变量有状态:在连续运行图时,变量保持相同 的值。通常它被用作保存模型的参数,不过也可以用作其他用途(比 如,对全局训练的步数进行计数)。
    占位符则只能做很少的事儿:它们只有其所代表的张量的类型 和形状的信息,但没有值。事实上,如果你要对一个依赖于占位符的 操作进行求值,你必须先为其传值(通过feed_dict),否则你会得到 一个异常。占位符通常在被用作在执行期为训练或者测试数据传值。 在将值传递给赋值节点以更改变量的值时(例如,模型的权重),占 位符也很有用。

  8. 如果对一个依赖于占位符的操作求值,但是又没有为其传值, 会发生什么?如果这个操作不依赖于占位符呢?
    答: 如果运行计算图来求值一个依赖于占位符的操作,但不提供 值,则会发生异常。如果操作不依赖于占位符,则不会引发异常

  9. 运行一个图时,可以为任意操作输出值,还是只能输出占位符 的值?
    答:当你运行一个图时,可以提供任何操作的输出值,而不仅仅是 占位符的值。在实践中,这种情况很少见(有时候会是有用的,比如 你要缓存冷冻层的输出时)。

  10. 在执行期,你如何为一个变量设置任意的值?
    答:你可以在构造一个图时指定变量的初始值,它会在后边的执 行期运行变量初始化器的时候被初始化。如果你想在执行期修改变量 的值,那么最简单的方式是使用tf.assign函数创建一个赋值节点(在 图的构造期),将变量和一个占位符传入作为参数。这样,你可以在 执行期运行复制操作来为变量传入新值。

import tensorflow as tf

x = tf.Variable(tf.random_uniform(shape=(), minval=0.0, maxval=1.0))
x_new_val = tf.placeholder(shape=(), dtype=tf.float32)
x_assign = tf.assign(x, x_new_val)

with tf.Session():
    x.initializer.run()
    print(x.eval())  # 0.7697661
    x_assign.eval(feed_dict={x_new_val: 5.0})
    print(x.eval())  # 5.0

  1. 反向模式autodiff需要多少次遍历图形才能计算10个变量的成 本函数的梯度?正向模式autodiff怎么样?符号微分呢?
    答:要计算任意数量变量的成本函数的梯度,反向模式的autodiff 算法(由TensorFlow实现)只需要遍历两次图。作为对比,正向模式 的autodiff算法需要为每个变量运行一次(如果我们需要10个不同变 量的梯度,那么就需要执行10次)。对于符号微分,它会建立一个不 同的图来计算梯度,所以根本不会遍历原来的图(除了在建立新的梯 度图时)。一个高度优化的符号微分系统可能只需要运行一次新的梯 度图来计算和所有变量相关的梯度,但与原始图相比,新的图可能是 非常复杂和低效的。

  2. 用小批量梯度下降法来实现逻辑回归。用月亮数据集来训练 和评估。尝试下面这些任务:
    ·在函数logistic_regression()中定义可以被复用的图。 ·在训练过程中,定期地通过Saver将检查点保存起来,并将最后 的模型保存起来。
    ·如果训练被终止了,恢复之前保存的模型。
    ·用合理的作用域来定义图,使得其在TensorBoard上看起来比较 漂亮。
    ·添加汇总信息以在TensorBoard中可视化学习曲线。 ·调整诸如学习速率和批次大小等超参数,并查看学习曲线的形状。