美文网首页我爱编程
lesson2 : Tensorflow 入门

lesson2 : Tensorflow 入门

作者: 卖西瓜的西瓜皮 | 来源:发表于2018-06-21 16:59 被阅读0次

    2.1 Tensorflow的计算模型——计算图

      根据lesson1中所讲,Tensorflow实际原理是张量的流动,讲述输入的多维数组(张量)通过不同节点进行不同的运算进行转化的一个过程,Tensorflow的每一个计算都是计算图的一个节点,涉及到一次张量的转化。多个节点构成一个神经元。Tensorflow如果不定义计算图,会自动生成一个默认的计算图,并将定义的计算全部加入默认图。

      如果说类比的话,计算图就像是我们在面向对象编程里的类(看下述代码可以理解),在一个计算图里,每个数据都像是类中的变量,每个计算节点都像是一个成员函数,两个图里的变量名字可以相同但是在指定运行不同的图时,得到结果根据各自图运算过程而定。

      计算图有隔离张量和计算的作用,并对张量和计算进行管理,例如限定计算所使用的GPU等,这个后续学到再说,我现在也不太会😂,而且我前面介绍的安装是CPU版本。自定义图的示例代码如下(python 的缩进很重要,不要漏掉):

    import tensorflow as tf
    
    g1 = tf.Graph()
    with g1.as_default():
          # 在计算图g1中定义变量“v”,初始化为0
          v = tf.get_variable("v",initializer=tf.zeros_initializer(shape=[1]))
    
     g2 = tf.Graph()
    with g2.as_default():
          # 在计算图g2中定义变量“v”,初始化为1
          v = tf.get_variable("v",initializer=tf.ones_initializer(shape=[1]))
    
    # 在计算图g1中读取变量“v”的值
    with tf.Session(graph = g1) as sess:
         tf.initialize_all_variables().run()
         with tf.variable_scope("",reuse=True):
               # 在计算图g1中,“v”为0,所以下述语句应该输出0
               print(sets.run(tf.get_variable("v")))
    
    # 在计算图g2中读取变量“v”的值
    with tf.Session(graph = g2) as sess:
         tf.initialize_all_variables().run()
         with tf.variable_scope("",reuse=True):
               # 在计算图g1中,“v”为1,所以下述语句应该输出1
               print(sets.run(tf.get_variable("v")))
    
    

      使用图限定计算用的GPU

    g = tf.Graph()
    # 指定计算运行的设备
    with g.device('/gpu:0'):
            result = a + b
    


    2.2 Tensorflow的数据模型——张量

    2.2.1 概念

      张量是Tensorflow管理数据的形式,可以简单理解为多维数组,不过Tensor的存储和Numpy的多维数组有所不同,Numpy简介参见这里,观察如下代码:

    import tensorflow as tf
    
    #. td.constant 是一个计算,个人感觉和申请const变量差不多,不过结果是一个张量,存储在变量a中
    a = tf.constant([1.0,2.0],name="a")
    b = tf.constant([2.0,3.0],name="b")
    c = tf.constant([2.0,3.0])
    d = tf.constant([2.0,3.0])
    result = tf.add(a,b,name="add")
    
    print(result) # output : Tensor("add:0",shape=(2,),dtype=float32)
    print(a)  # output: Tensor("a:0", shape=(2,), dtype=float32)
    print(c) # output: Tensor("Const:0", shape=(2,), dtype=float32)
    print(d) # output: Tensor("Const_1:0", shape=(2,), dtype=float32)
    
    sess = tf.Session()
    sess.run(result) # output : array([3., 5.], dtype=float32)
    less.run(a) # output : array([1., 2.], dtype=float32)
    

      从上述代码可以发现张量中主要保存了三个属性:名字(name),维度(shape)和类型(type),其中名字遵循“node:src_output”,比如result为add计算节点的第0个输出,所以命名为add:0,因为有的计算节点并不一定输出一个张量,所以src_output为输出序号,node为计算节点名称,tf.constant()和tf.add()均为计算,所以a为a:0,其中节点的名称可以由我们定义,如果我们不自己定义,Tensorflow有自己的默认命名,比如c的"Const:0" 以及d的“Const_1:0”

      所以,我感觉Tensor不能单纯的理解为多维数组,它包含了他是从哪个计算节点计算而来的,以及它的大小,我们可以理解为Tensorflow分为两部分工作,第一部分工作是定义计算图,也就是定义张量是如何流动的,但是每一步运算都并没有实质上的运行,张量就是这样而存在的。第二部分是对计算图进行实质上的通过CPU或者GPU进行计算,这就需要运行Session,Session的使用会在后面小节具体描述,从上述代码可以看到运行sess.run()就会输出运算结果

    2.2.2 张量的使用

      观察下列代码的运行

    import tensorflow as tf
    
    a = tf.constant([1,2],name="a")
    b = tf.constant([2.0,3.0],name="b")
    c =  tf.constant([1,2],name="c",dtype=tf.float32)
    
    result = a + b # Get ERROR bellow
    # ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("b:0", shape=(2,), dtype=float32)'
    
    result = b+c # no error
    

      对于Tensorflow,如果不声明类型dtype,那么没有小数点默认类型为int32,有小数点默认为float32,这个和我们编程不一样,不存在强制类型转换,需要注意。Tensorflow所支持的数据类型:

    • 浮点数(tf.float32、tf.float64)
    • 整数(tf.int8、tf.int16、tf.int32、tf.int64、 tf.unit8)
    • 布尔型(tf.bool)
    • 复数(tf.complex64、tf.complex128)
    import tensorflow as tf
    
    a = tf.constant([1.0,2.0],name="a")
    b = tf.constant([2.0,3.0],name="b")
    
    result = a + b; # 和tf.add()效果相同,根据需要选择,使用tf.add()可以自定义节点的其他属性,比如计算节点的名字
    
    # 和上述代码效果一样,但可读性差
    result_1 = tf.constant([1.0,2.0],name="a") + 
               tf.constant([2.0,3.0],name="b")
    
    

      从上述代码可以看到,中间变量a和b只是为了存储中间张量,可以不写,但是为了可读性应该使用类似的中间变量增加代码可读性,优点如下:

    • 对于python:由于python的灵活的类型转化无需声明数据类型,设置必要中间变量方便调试
    • 对于Tensorflow: 由于有的网络巨大,在设计计算图时需要考虑张量的大小问题,设置中间变量可以方便的获取中间步骤张量的大小,省去人为计算


    2.3 Tensorflow运行模型——会话

      前面两节介绍了Tensorflow如何组织数据和运算,可以认为是计算图的设计部分,而会话(session)是对前面两个部分设计结果的执行。会话可以管理Tensorflow程序运行时的所有资源。计算完成后需要关闭绘画帮助系统回收资源,可以理解为一个指针,这个指针指向计算图的某个节点,该节点就被激活并执行计算,当所有运算执行完,关闭会话,类似于指针的free。

      Tensorflow的会话的使用一般有两种,如下所示,所有计算完成后关闭资源,但是这种方法有一个问题就是当在session.close()执行之前,程序出现异常而退出,那么会造成资源泄漏。不过我喜欢。。😏

    # 创建一个会话
    sess = tf.Session()
    # 使用这个会话得到关心的运算结果,比如上节使用的sess.run(result)
    session.run(...)
    #关闭会话释放资源
    session.close()
    

      还有一种写法如下,不会泄漏资源,但是我感觉写起来很麻烦

    # 创建一个会话,通过Python的上下文管理器来管理这个会话。
    with tf.Session() as session:
         # 使用创建的会话计算关心的结果
         session.run(...)
    # 不需要调用Session.close()函数
    # 当上下文退出后会话关闭并进行资源释放
    
    

      以上两种介绍的是Session的简单的也是常用的写法,其实会话的使用很灵活,主要表现在默认会话的设置和使用上。Session和计算图Graph类似存在默认会话,在默认的会话下,无需调用sess.run(),使用方法如下所示

    sess = tf.Session()
    #设置为默认会话
    with sess.as_default():
         print(result.eval())
    

      同样效果的等价写法还有如下两种:

    sess = tf.Session()
    
    # 如下两行等价,均未设置默认会话
    print(sess.run(result))
    print(result.eval(session=sess))
    

      如果Session设置为每一步计算节点的默认会话,仅需调用运算节点的eval()成员函数即可得到运算结果,Tensorflow提供一个将自动生成的会话直接注册为默认会话的函数,作用于全局,用法如下:

    # 生成一个注册为默认会话的会话sess
    sess = tf.InteractiveSession()
    print(result.eval())
    sess.close()
    



      至此,Tensorflow的基本思想已经简单介绍完毕,下一部分将根据一些网络的设计和使用展开对Tensorflow展开进阶介绍

    相关文章

      网友评论

        本文标题:lesson2 : Tensorflow 入门

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