斯坦福tensorflow教程(二) tensorflow相关运

作者: 致Great | 来源:发表于2018-05-09 10:56 被阅读258次

    1.认识下TensorBoard

    TensorFlow不仅是一个软件库,而是一整套包括TensorFlow、TensorBoard、Tensor Serving在内的软件包。为了更大程度地利用TensorFlow,我们应该了解如何将它们串联起来应用。在和一部分,我们来探索下TensorBoard。
    TensorBoard是一个图(graph)可视化软件,在(安装TensorFlow的时候会默认安装)。下面是谷歌的介绍:
    The computations you'll use TensorFlow for - like training a massive deep neural network - can be complex and confusing. To make it easier to understand, debug, and optimize TensorFlow programs, we've included a suite of visualization tools called TensorBoard.

    在运行一个包含一些运算的TensorFlow程序时,这些运算会导出成一个时间日志文件。TensorBoard 可以将这些日志文件可视化,以便更好观察程序的机构以及运行表现。TensorBoard和TensorFlow一并使用,会使工作更加有趣和更具生产力。

    下面开始我们第一个TensorFlow程序,并使用TensorBoard可视化。

    import tensorflow as tf
    a = tf.constant(2)
    b = tf.constant(3)
    x = tf.add(a, b)
    with tf.Session() as sess:
        print(sess.run(x))
    
    
    执行结果

    为了将上面程序可视化,我们需要下面一行程序将日志写入文件:

    writer = tf.summary.FileWriter([logdir], [graph])
    

    [graph] 是运行程序所在的图,可以通过tf.get_default_graph()返回程序默认图,也可以通过sess.graph返回当前会话中运行的图,后者需要你自己先创建一个session。无论哪种方式,都要你在定义graph之后创建一个writer,否则TensorBoard不能可视化程序。

    [logdir]是存储日志文件的路径

    import tensorflow as tf
    
    a = tf.constant(2)
    b = tf.constant(3)
    x = tf.add(a, b)
    writer = tf.summary.FileWriter('./graphs', tf.get_default_graph())
    with tf.Session() as sess:
        # writer = tf.summary.FileWriter('./graphs', sess.graph) # if you prefer creating your writer using session's graph
        print(sess.run(x))
    writer.close()
    

    然后在cmd运行程序

    $ python3 [my_program.py] 
    $ tensorboard --logdir="./graphs" --port 6006
    

    在浏览器打开



    可视化效果如下



    “Const”和“Const_1”指的是a和b,节点“Add”指的是x,为了更好理解运算,我们可以给ops命名。
    a = tf.constant(2, name="a")
    b = tf.constant(2, name="b")
    x = tf.add(a, b, name="add")
    

    我们可以通过点击节点来查看它的值和类型:


    2.常量op

    op:图中的节点(operation 的缩写).
    下面是创建constant的操作
    tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)

    • 常数
      num = tf.constant(2, name="num")

    • 向量
      # constant of 1d tensor (vector)
      a = tf.constant([2, 2], name="vector")

    • 矩阵
      # constant of 2x2 tensor (matrix)
      b = tf.constant([[0, 1], [2, 3]], name="matrix")
      可以通过填充创建tensor,类似于numpy中的操作

    • tf.zeros(shape, dtype=tf.float32, name=None)

    # create a tensor of shape and all elements are zeros
    tf.zeros([2, 3], tf.int32) ==> [[0, 0, 0], [0, 0, 0]]
    
    • tf.zeros_like(input_tensor, dtype=None, name=None, optimize=True)
    # create a tensor of shape and type (unless type is specified) as the input_tensor but all elements are zeros.
    # input_tensor [[0, 1], [2, 3], [4, 5]]
    tf.zeros_like(input_tensor) ==> [[0, 0], [0, 0], [0, 0]]
    
    • tf.ones(shape, dtype=tf.float32, name=None)
    # create a tensor of shape and all elements are ones
    tf.ones([2, 3], tf.int32) ==> [[1, 1, 1], [1, 1, 1]]
    
    • tf.ones_like(input_tensor, dtype=None, name=None, optimize=True)
    # create a tensor of shape and type (unless type is specified) as the input_tensor but all elements are ones.
    # input_tensor is [[0, 1], [2, 3], [4, 5]]
    tf.ones_like(input_tensor) ==> [[1, 1], [1, 1], [1, 1]]
    
    • tf.fill(dims, value, name=None)
    # create a tensor filled with a scalar value.
    tf.fill([2, 3], 8) ==> [[8, 8, 8], [8, 8, 8]]
    
    • tf.lin_space(start, stop, num, name=None)
    tf.lin_space(start, stop, num, name=None)
    # create a sequence of num evenly-spaced values are generated beginning at start. If num > 1, the values in the sequence increase by (stop - start) / (num - 1), so that the last one is exactly stop.
    # comparable to but slightly different from numpy.linspace
    
    tf.lin_space(10.0, 13.0, 4, name="linspace") ==> [10.0 11.0 12.0 13.0]
    
    • tf.range([start], limit=None, delta=1, dtype=None, name='range')
    # create a sequence of numbers that begins at start and extends by increments of delta up to but not including limit
    # slight different from range in Python
    
    # 'start' is 3, 'limit' is 18, 'delta' is 3
    tf.range(start, limit, delta) ==> [3, 6, 9, 12, 15]
    # 'start' is 3, 'limit' is 1,  'delta' is -0.5
    tf.range(start, limit, delta) ==> [3, 2.5, 2, 1.5]
    # 'limit' is 5
    tf.range(limit) ==> [0, 1, 2, 3, 4]
    

    不像Numpy或者Python其他序列,TensorFlow序列不能迭代

    for _ in np.linspace(0, 10, 4): # OK
    for _ in tf.linspace(0.0, 10.0, 4): # TypeError: 'Tensor' object is not iterable.
    
    for _ in range(4): # OK
    for _ in tf.range(4): # TypeError: 'Tensor' object is not iterable.
    

    也可以生成随机constant,具体请见API

    tf.random_normal
    tf.truncated_normal
    tf.random_uniform
    tf.random_shuffle
    tf.random_crop
    tf.multinomial
    tf.random_gamma
    tf.set_random_seed
    

    3. 数学运算

    • division相关操作
      TensorFlow 运算相当完美与标准,全部内容在这
      tf.div(a/b)是TensorFlow的风格,返回a除以b的商数,比如8/3,返回2;

    tf.divide(a/b)才和Python的风格一样,a除以b

    a = tf.constant([2, 2], name='a')
    b = tf.constant([[0, 1], [2, 3]], name='b')
    with tf.Session() as sess:
        print(sess.run(tf.div(b, a)))             ⇒ [[0 0] [1 1]]
        print(sess.run(tf.divide(b, a)))          ⇒ [[0. 0.5] [1. 1.5]]
        print(sess.run(tf.truediv(b, a)))         ⇒ [[0. 0.5] [1. 1.5]]
        print(sess.run(tf.floordiv(b, a)))        ⇒ [[0 0] [1 1]]
        print(sess.run(tf.realdiv(b, a)))         ⇒ # Error: only works for real values
        print(sess.run(tf.truncatediv(b, a)))     ⇒ [[0 0] [1 1]]
        print(sess.run(tf.floor_div(b, a)))       ⇒ [[0 0] [1 1]]
    
    • tf.add_n
      tf.add_n([a, b, b]) => equivalent to a + b + b
    • 点积 Dot
    a = tf.constant([10, 20], name='a')
    b = tf.constant([2, 3], name='b')
    with tf.Session() as sess:
        print(sess.run(tf.multiply(a, b)))           ⇒ [20 60] # element-wise multiplication
        print(sess.run(tf.tensordot(a, b, 1)))       ⇒ 80 # 按列相乘然后相加
    

    下面是TensorFlow中运算表格,来自《Fundamentals of Deep Learning》


    4 数据类型

    • python基本数据类型
      TensorFlow吸收了Python的一些基本类型,比如布尔值(boolean values),数值(int和float)以及字符串(string)。相应地,单值可以转化为0-d(0维)张量(tensor)(或者标量(scalars)),列表可以转化为1-d tensor (vector),元素为列表的列表可以转化为2-d tensor(matrix),等等。下面是是引自《TensorFlow for Machine Intelligence》的几个例子:
    
    t_0 = 19 # Treated as a 0-d tensor, or "scalar" 
    tf.zeros_like(t_0)                   # ==> 0
    tf.ones_like(t_0)                    # ==> 1
    
    t_1 = [b"apple", b"peach", b"grape"] # treated as a 1-d tensor, or "vector"
    tf.zeros_like(t_1)                   # ==> [b'' b'' b'']
    tf.ones_like(t_1)                    # ==> TypeError
    
    t_2 = [[True, False, False],
           [False, False, True],
           [False, True, False]]         # treated as a 2-d tensor, or "matrix"
    
    tf.zeros_like(t_2)                   # ==> 3x3 tensor, all elements are False
    tf.ones_like(t_2)                    # ==> 3x3 tensor, all elements are True
    
    • TensorFlow基本数据类型
      像NumPy一样,TensorFlow也有自己数据类型,例如:tf.int32,tf.float32.下面是TensorFlow所有数据类型截图:


    • NumPy数据类型
      截止到现在,你会发现TensorFlow与NumPy有很多相似之处,TensorFlow被设计地与这个数据科学领“通用语言”NumPy无缝衔接。
      TensorFlow的数据类型基于NumPy,实际上,np.int32==tf.int32,你可以将NumPy数据类型传递给TensorFlow算子。
      tf.ones([2, 2], np.float32) ==> [[1.0 1.0], [1.0 1.0]]

    5.变量

    constan与variable的区别:

    1. 常量也是常数,经常我们需要在训练模型的时候更新权重与偏置矩阵
    2. 一个常量存储于图中,并且当图加载时需要重新复制;一个变量独立地存储,并且存在与参数服务中。
      以上两点解释了,当权重很大时,constant消耗代价很大,并且减慢了加载图的速度。我们看下图存储的内容:
    import tensorflow as tf
    my_const = tf.constant([1.0, 2.0], name="my_const")
    print(tf.get_default_graph().as_graph_def())
    
    node {
      name: "my_const"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_FLOAT
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_FLOAT
            tensor_shape {
              dim {
                size: 2
              }
            }
            tensor_content: "\000\000\200?\000\000\000@"
          }
        }
      }
    }
    versions {
      producer: 21
    }
    
    [Finished in 3.0s]
    
    • 创建变量
      为了声明一个变量,你需要实例化一个tf.Variable,注意V大写。
    x = tf.Variable(...) 
    x.initializer # init 
    x.value() # read op 
    x.assign(...) # write op 
    x.assign_add(...) 
    # and more
    

    创建变量的旧方式是调用tf.Variable(<initial-value>, name=<optional-name>)

    
    s = tf.Variable(2, name="scalar") 
    m = tf.Variable([[0, 1], [2, 3]], name="matrix") 
    W = tf.Variable(tf.zeros([784,10]))
    

    然而这种方式被TensorFlow摒弃了,推荐我们使用tf.get_variable来创建,因为这样可以更好地实现变量共享。通过tf.get_variable,我们可以internal name,shape,type和initializer提供给初始值。注意当我们通过tf.constant作为initializer时,不需要提供shape

    tf.get_variable(
        name,
        shape=None,
        dtype=None,
        initializer=None,
        regularizer=None,
        trainable=True,
        collections=None,
        caching_device=None,
        partitioner=None,
        validate_shape=True,
        use_resource=None,
        custom_getter=None,
        constraint=None
    )
    
    s = tf.get_variable("scalar", initializer=tf.constant(2)) 
    m = tf.get_variable("matrix", initializer=tf.constant([[0, 1], [2, 3]]))
    W = tf.get_variable("big_matrix", shape=(784, 10), initializer=tf.zeros_initializer())
    
    • 初始化变量
      在使用一个变量之前,需要先初始化,否则将会报错:FailedPreconditionError: Attempting to use uninitialized value.可以通过以下语句来打印出没有初始化的变量:
    print(session.run(tf.report_uninitialized_variables()))
    

    (1)初始化所有的变量:

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
    

    (2)初始化部分变量tf.variables_initializer()

    with tf.Session() as sess:
        sess.run(tf.variables_initializer([a, b]))
    

    (3) 初始化单个变量tf.Variable.initializer

    with tf.Session() as sess:
        sess.run(W.initializer)
    
    • 查看变量的值
      从session取出值
    # V is a 784 x 10 variable of random values
    V = tf.get_variable("normal_matrix", shape=(784, 10), 
                         initializer=tf.truncated_normal_initializer())
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        print(sess.run(V))
    

    通过tf.Variable.eval()取出值

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
            print(V.eval())
    
    • 变量赋值
      通过tf.Variable.assign()
    W = tf.Variable(10)
    W.assign(100)
    with tf.Session() as sess:
        sess.run(W.initializer)
        print(W.eval()) # >> 10
    

    为什么输出的是10而不是100呢?W.assign(100)并没有将100赋值给 W,而是创建了一个assign op.为了使这个op起到效果,我们需要在session运行op

    W = tf.Variable(10)
    
    assign_op = W.assign(100)
    with tf.Session() as sess:
        sess.run(assign_op)
        print(W.eval()) # >> 100
    

    注意此时我们不必去初始化W,因为assign()已经为我们实现。

    # in the [source code](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/variables.py)
    
    self._initializer_op = state_ops.assign(self._variable,  self._initial_value, validate_shape=validate_shape).op**
    

    有趣的例子:

    # create a variable whose original value is 2
    a = tf.get_variable('scalar', initializer=tf.constant(2)) 
    a_times_two = a.assign(a * 2)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer()) 
        sess.run(a_times_two) # >> 4
        sess.run(a_times_two) # >> 8
        sess.run(a_times_two) # >> 16
    

    tf.Variable.assign_add()tf.Variable.assign_sub(),这两个操作需要初始化

    W = tf.Variable(10)
    
    with tf.Session() as sess:
        sess.run(W.initializer)
        print(sess.run(W.assign_add(10))) # >> 20
        print(sess.run(W.assign_sub(2)))  # >> 18
    

    session之间的变量相互独立

    W = tf.Variable(10)
    sess1 = tf.Session()
    sess2 = tf.Session()
    sess1.run(W.initializer)
    sess2.run(W.initializer)
    print(sess1.run(W.assign_add(10)))      # >> 20
    print(sess2.run(W.assign_sub(2)))       # >> 8
    print(sess1.run(W.assign_add(100)))     # >> 120
    print(sess2.run(W.assign_sub(50)))      # >> -42
    sess1.close()
    sess2.close()
    

    如果一个变量依赖于另一个变量,需要初始化

    # W is a random 700 x 10 tensor
    W = tf.Variable(tf.truncated_normal([700, 10]))
    U = tf.Variable(W * 2)
    
    U = tf.Variable(W.initialized_value() * 2)
    

    6 交互的会话

    InteractiveSession是我们在shell或者IPython操作很方便

    sess = tf.InteractiveSession()
    a = tf.constant(5.0)
    b = tf.constant(6.0)
    c = a * b
    print(c.eval()) # we can use 'c.eval()' without explicitly stating a session
    sess.close()
    

    7. 控制依赖

    有时候,graph有多个运算时op,并且我们想指定它们的执行顺序时,可以通过tf.Graph.control_dependencies([control_inputs])实现。

    # your graph g have 5 ops: a, b, c, d, e
    with g.control_dependencies([a, b, c]):
      # `d` and `e` will only run after `a`, `b`, and `c` have executed.
      d = ...
      e = …
    

    8. 导入数据

    8.1 placeholder和feed_dict(旧方法)

    我们在教程1提到过,TensorFlow程序执行通常包括两个阶段

    阶段1:声明一个graph
    阶段2:使用一个session来执行计算,来评估图中的变量
    

    我们声明graphs的时候,不许要知道计算所需变量的值,这如同实名一个关于x和y的函数:f(x,y)=2x+y,其中x和y是实际值的占位符(placeholder)

    graph创建之后,我们需要稍后再提供值的时候来定义一个placeholder:

    tf.placeholder(dtype, shape=None, name=None)
    

    需要注意的是dtypeshape需要自己声明的;当shape=none的时候, 表名可以接受任意shape的张量tensors。
    下面是一个实例:

    a = tf.placeholder(tf.float32, shape=[3]) # a is placeholder for a vector of 3 elements
    b = tf.constant([5, 5, 5], tf.float32)
    c = a + b # use the placeholder as you would any tensor
    with tf.Session() as sess:
        print(sess.run(c)) 
    

    我们知道,此时执行上面程序会报错,因为还没有提供给a值,下面使用feed_dict把值传给a

    with tf.Session() as sess:
        # compute the value of c given the value of a is [1, 2, 3]
        print(sess.run(c, feed_dict={a: [1, 2, 3]}))        # [6. 7. 8.]
    

    8.2 tf.data(新方法)

    此部分结合教程3讲解

    相关文章

      网友评论

      本文标题:斯坦福tensorflow教程(二) tensorflow相关运

      本文链接:https://www.haomeiwen.com/subject/hmtnrftx.html