tf一些函数

作者: 小碧小琳 | 来源:发表于2017-10-19 08:06 被阅读835次

    对于 tf.get_variable() vs tf.Variable(),tf.name_scope() vs tf.variable_scope()

    最近刚接手tf,有些函数,理解不清楚,做一下笔记。
    对于函数,知道平时的用法就行了,不用纠结里面的每一个参数的意思,基本用不到,还浪费时间

    一、name-scope 和 variable-scope

    name-scope 和 variable-scope 都是命名空间,意思就是,定义一个空间,在这个空间里面的,定义的变量,基本都会以这个命名空间作为其变量名的前缀。(但是也有例外)

    比如下图中,尽管是两段代码,但都是在variable-scope定义的名称为“V1”的空间中。而reuse命令,允许共享当前scope(同一个命名空间)下的所有变量,所以a1和a3的变量名都是 V1/a1:0

    import tensorflow as tf    
    import numpy as np    
    
    with tf.variable_scope('V1'):  
        a1 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))  
      
    with tf.variable_scope('V1', reuse=True):  
        a3 = tf.get_variable('a1')  
    
    • name_scope对 get_variable()创建的变量 的名字不会有任何影响,而创建的op会被加上前缀.
    • tf.get_variable_scope() 返回的只是 variable_scope,不管 name_scope.所以以后我们在使用tf.get_variable_scope().reuse_variables() 时可以无视name_scope
    • name_scope 是给op_name加前缀, variable_scope是给get_variable()创建的变量的名字加前缀。

    二 、tf 的 reduce(降维)操作

    1. 基础理解

    1.1 向量的“维”

    这里加入基础理解的意思,是为了防止概念不清晰。
    比如若说X是一个n维向量,表示X中,含有n个元素,可以在n维坐标系中表示出来(原点到X坐标的向量)。另外,在机器学习的降维中,是把X从n维降到k维。 ---但这不是tf中的‘‘降维”

    n维向量!= n维数组!!!

    1.2 tf中的“维”

    在tf中,用constant定义的tensor

    • 0维数组,表示一个数,如:6。(可以理解为“点”)
    • 1维数组,表示一个a = [1,2,3]。(可以理解为“线”,这也和上面的向量联系起来了。一方面,这是一个三维向量,另一方面,在n维坐标系中,向量是一条直线,是“线”)
    • 2维数组,表示一个
      b = [[1,2,3],
      [4,5,6]]。(可以理解为“面”,或者矩阵)
    • 3维数组,表示一个
      c = [[[1,2,3],[4,5,6]],
      [[7,8,9],[1,1,1]],
      [[2,2,2],[3,3,3]]]
      可以理解为“体”。
    1.3 对数组进行索引

    索引,类似于Python中的列表索引,0表示第一个元素,但又不一样。
    比如,对上面的2维数组b进行索引 ,得到
    b[0] = [1,2,3],
    c[0] = [[1.2.3].[4.5.6]] (都是数组里的第一个元素)

    1.4 tf.reduce_xxx操作中的axis

    因为版本的不同,有时参数axis(轴)等同于参数reduction_indices(减去索引)
    这里所说的,应该是侧重于axis轴的意思

    这里作者就按照坐标轴来理解。比如,上面的三维数组c,我把它理解为由x,y,z轴组成的坐标系中的三个自变量组成的“体”,c的0维就相当于x变量,剩下的由y和z两个组成的几个平面,也就是剩下的3个二维数组。这里的“c的0维”不等于“c[0]”。

    那么。去掉c的0维,就相当于只剩下y,z两个变量组成的三个平面。

    reduc_sum(c,0)那就理解为,先把三个平面相加,再去掉x自变量。
    所以,就相当于,先把每个第0维里面的元素(即三个二维数组)按照规则相加,再去掉最外面的“0维”。于是,最后剩一个二维数组。

    最外面的中括号代表了第0维,再往里代表了第1维(比如[[1,2,3],[4,5,6]],第一维里面的元素相加,就是[1,2,3]+[4,5,6]),再往里代表了第2维(比如[1,2,3].)

    1.5 代码

    具体别的情况,就看下面代码。其中,keep_dims表示的意思就是,照常计算,但不消除该维。

    import tensorflow as tf
    import numpy as np    
    
    x = [[[1,2,3],[4,5,6]],
    [[7,8,9],[1,1,1]],
    [[2,2,2],[3,3,3]]]
    
    x = tf.constant(x)
    
    # x 后面没有参数,就默认为把所有的元素相加
    a = tf.reduce_sum(x)
    
    #把所有0维里的元素都按照规则相加,再消去0维度(即消去代表0维度的中括号)
    b = tf.reduce_sum(x,0)
    
    #以下没有消去的维度都是保留的
    #只举一个例子,把目前所有1维里的元素都相加如 ==>得到相加的结果 ==>再消去1维度
    # [1,2,3]+[4,5,6] ==> [5,7,9] ==>5,7,9
    c = tf.reduce_sum(x,1)
    
    #只举一个例子, 把所有第2维的元素都相加 ==> 得到结果 ==> 消去2维度
    # [1+2+3],[4+5+6] ==> [6],[15] ==> 6,15
    d = tf.reduce_sum(x,2)
    
    # 把第1维所有元素相加,得到结果 ==> 再把第2维所有元素相加,得到结果 ==>消去1,2维度
    # [[[5,7,9]],[[8,9,10]],[[5,5,5]]]==>[[[21]],[[27]],[[15]]]==>[21,27,15]
    f = tf.reduce_sum(x,[1,2])
    
    #把0维所有元素相加以后,1维所有元素相加以后,2维所有元素相加以后消去012维
    g = tf.reduce_sum(x,[0,1,2])
    
    #把目前所有1维里的元素都相加如 ==>得到相加的结果 ==>但不消去1维度(即括号不去掉)== 保留该维度
    # [1,2,3]+[4,5,6] ==> [5,7,9] ==>[5,7,9]
    h = tf.reduce_sum(x,1,keep_dims=True)
    
    #只举一个例子, 把所有第2维的元素都相加 ==> 得到结果 ==> 但不消去2维度 == 保留该维度
    # [1+2+3],[4+5+6] ==> [6],[15] ==> [6],[15]
    i = tf.reduce_sum(x,2,keep_dims=True)
    
    with tf.Session() as sess:
       print('a',sess.run(a))
       print('b',sess.run(b))
       print('c',sess.run(c))
       print('d',sess.run(d))
       print('f',sess.run(f))
       print('g',sess.run(g))
       print('h',sess.run(h))
       print('i',sess.run(i))
    

    三、tf.nn.embedding_lookup()函数

    基础知识

    shape,列表和数组,

    • 1 shape方法
      shape方法得到的结果的是一个tuple,从第一个元素到最后一个元素,依次表示的是从数组第0维里含有元素的个数,第1维含有元素的个数,第2维。。。如上面的x数组,x.shape ==>(3,2,3);再如a=[1,2,3]是一个列表,那么a.shape ==>(3,)一定有一个逗号,表示这是一个元组的数据结构

    • 2 列表和数组
      在运用一个函数或者方法之前,一定要弄明白,需要传入的参数是什么数据结构的!!!就比如这个方法,作者一开始定义好x之后,没有用np.array设置成数组,或者用constant设置成一个整体的tensor,结果x一直是列表形式,最终出现毛病。

    def embedding_lookup(params, ids, partition_strategy="mod"),主要讲这三个参数。

    params可以是一个tensor,也可以是多个tensor,不过输入多个tensor的时候,需要用作为params=[a,b,c]的形式进行输入。

    当系统认为,params的长度等于1时候,就和平时的索引一样,按照ids中的id索引就行。

    但是当系统认为params的长度大于1的时候,就会用第三个参数(默认是“mod”)的模式,将params去掉里面每个tensor的中括号以后所有的元素个数,按照求余数相同的方式分成len(params)个切片,每个切片里的第i个id对应该切片里的第i个元素。
    举个栗子:
    a = [[1,2,3],[4,5,6]]
    b = [[7,8,9],[1,1,1]]
    c = [[2,2,2],[3,3,3]]
    a = tf.constant(a)
    b = tf.constant(b)
    c = tf.constant(c)

    那么传入params=[a,b,c],此时,系统认为params里是多个量了(3个tensor),那么去掉每个tensor的最外面中括号共有3*2=6个元素,所以一共可以有6个id,分别是012345,有3个tensor,就有3个切片。按照余数相同分组,不均匀就前面的分的多。分为[0,3],[1,4],[2,5],对应的分别是 a,b,c。索引id时,id等于3,就相当于索引的是a中第二个元素,所以索引的是[4,5,6].

    另外,返回的tensor的shape应该是shape(ids) + shape.params[1:]
    这里的params指的是被索引的那个param
    比如ids = [3],那么返回的结果的shape应该是shape.[3] + shape.a[1:]=(1,)+(2,3)[1:] = (1,)+(3,) = (1,3),所以结果应该是[[4,5,6]],二维数组
    但这里,这个函数是把a作为一个params了,作为一个tensor了。

    另外需要注意的是,tf中传入多个参数,就是用中括号把参数作为一个整体,以列表的方式传给函数。所以,有的函数一旦遇到[a,b,c]这种形式的,就会认为a,b,c是参数。
    所以,若是x一开始定义为列表格式的话,那么这个函数就会把这个‘表示为列表的中括号’认为是类似于上面的[a,b,c]这个传参的中括号,从而把x认为是由三个tensor组成的。然后就会启动上面所说的切片模式。比如用上面说的x,那么就会认为x是三个[2,3]的数组。

    但是如果用np.array(x)或者用x=tf.constant(x)以后,x就被认为是一个整个的tensor了,那么这时候就认为x是1个,就不会启动上面的切片模式,就是正常的索引现象。

    以后在遇到的时候,需要先明确x是列表,还是由constant定义好了的一个tensor(或者nparray定义的数组)。自己用的时候,最好用后者,把x当成是一个整体,若是需要输入多个,那么就用[a,b,c]的方式输入。

    四、 tf.gather(params,indices,..)

    合并 - 索引indices所指示的params中的切片
    比如a = tf.gather(x,[0,2]),就是索引x这个tensor的0维下的元素的位置索引为0,2的两个元素 并合并起来,即结果再放进一个列表中, 即使只有一个元素也要放进列表中

    import tensorflow as tf
    
    x = [[[1,2,3],[4,5,6]],
    [[7,8,9],[1,1,1]],
    [[2,2,2],[3,3,3]]]
    
    a = tf.gather(x,[0,2])
    
    with tf.Session() as sess:
        print('a',sess.run(a))#输出123,456和222,333
    

    五、tf 的onehot函数

    参考[tf.one_hot()函数简介](https://www.jianshu.com/writer#/notebooks/17771847/notes/18446692/preview

    比如,输入indices是一维列表,[1,3,5,7,9],depth等于10
    那么就会输出一个shape为[5,10]的二维数组,其中第一行中的索引为1的位置为1,其余为0.第二行中索引为3的位置为1,其余值为0.

    如果输入的indices是一个shape是[1,5]的二维数组,[[1,3,5,7,9]],那么输出就会使一个[1,5,10]的三维数组。其中的onehot形式是一样的。

    相关文章

      网友评论

        本文标题:tf一些函数

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