zoukankan      html  css  js  c++  java
  • TensorFlow2.0(1):基本数据结构——张量

     

    注:本系列所有博客将持续更新并发布在github上,您可以通过github下载本系列所有文章笔记文件。

     

    1引言

     

    TensorFlow2.0版本已经发布,虽然不是正式版,但预览版都发布了,正式版还会远吗?相比于1.X,2.0版的TensorFlow修改的不是一点半点,这些修改极大的弥补了1.X版本的反人类设计,提升了框架的整体易用性,绝对好评!

    赶紧来学习一波吧,做最先吃螃蟹的那一批人!先从TensorFlow的基本数据结构——张量(tensor)开始。

     

    2 创建

     

    2.1 constant()方法

    In [1]:
    import tensorflow as tf
    
    In [2]:
    tf.constant(1)  # 创建一个整型张量
    
    Out[2]:
    <tf.Tensor: id=0, shape=(), dtype=int32, numpy=1>
    In [3]:
    tf.constant(1.)  # 创建一个浮点型张量
    
    Out[3]:
    <tf.Tensor: id=2, shape=(), dtype=float32, numpy=1.0>
    In [4]:
    tf.constant(2., dtype=tf.double)  # 创建的同时指定数据类型
    
    Out[4]:
    <tf.Tensor: id=4, shape=(), dtype=float64, numpy=2.0>
    In [5]:
    tf.constant([[1.,2.,3.],[4.,5.,6.]])  # 通过传入一个list参数创建
    
    Out[5]:
    <tf.Tensor: id=6, shape=(2, 3), dtype=float32, numpy=
    array([[1., 2., 3.],
           [4., 5., 6.]], dtype=float32)>
     

    如果输入的数据与指定的数据类型不相符,会产生以下异常:
    TypeError: Cannot convert provided value to EagerTensor. Provided value: 2.1 Requested dtype: int32

     

    2.2 convert_to_tensor()方法

    In [9]:
    import numpy as np
    
    In [10]:
    tf.convert_to_tensor(np.ones([2, 3]))
    
    Out[10]:
    <tf.Tensor: id=9, shape=(2, 3), dtype=float64, numpy=
    array([[1., 1., 1.],
           [1., 1., 1.]])>
    In [11]:
    tf.convert_to_tensor(np.ones([2, 3]))
    
    Out[11]:
    <tf.Tensor: id=11, shape=(2, 3), dtype=float64, numpy=
    array([[1., 1., 1.],
           [1., 1., 1.]])>
    In [12]:
    tf.convert_to_tensor([[2.,3.],[3., 4.]])
    
    Out[12]:
    <tf.Tensor: id=13, shape=(2, 2), dtype=float32, numpy=
    array([[2., 3.],
           [3., 4.]], dtype=float32)>
     

    2.3 创建元素为指定值的tensor

     

    如果你熟悉numpy创建数组的方法,你一定见过zeros()、ones()等方法,TensorFlow中也有这些方法。

     

    (1)zeros()与ones()

    In [24]:
    a = tf.zeros([2, 3, 3])  # 创建一个元素全为0,形状为[2, 3, 3]的tensor
    
    In [25]:
    a
    
    Out[25]:
    <tf.Tensor: id=46, shape=(2, 3, 3), dtype=float32, numpy=
    array([[[0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.]],
    
           [[0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.]]], dtype=float32)>
    In [26]:
    b = tf.ones([2, 3])  #  创建一个元素全为1,形状为[2, 3]的tensor
    
    In [27]:
    b
    
    Out[27]:
    <tf.Tensor: id=50, shape=(2, 3), dtype=float32, numpy=
    array([[1., 1., 1.],
           [1., 1., 1.]], dtype=float32)>
     

    (2)zeros_like()与ones_like

    In [28]:
    tf.zeros_like(b)  # 仿照b的shape创建一个全为0的tensor
    
    Out[28]:
    <tf.Tensor: id=52, shape=(2, 3), dtype=float32, numpy=
    array([[0., 0., 0.],
           [0., 0., 0.]], dtype=float32)>
    In [29]:
    tf.ones_like(a)  # 仿照b的shape创建一个全为1的tensor
    
    Out[29]:
    <tf.Tensor: id=56, shape=(2, 3, 3), dtype=float32, numpy=
    array([[[1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.]],
    
           [[1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.]]], dtype=float32)>
     

    (3)fill()

    In [21]:
    tf.fill([2,3],5)  # 创建元素全为5,形状为[2,3]的tensor
    
    Out[21]:
    <tf.Tensor: id=38, shape=(2, 3), dtype=int32, numpy=
    array([[5, 5, 5],
           [5, 5, 5]])>
     

    2.4 随机初始化

     

    在实际应用中,经常需要随机初始化元素服从某种分布的tensor,TensorFlow中也提供了这种功能。

    (1)从指定正态分布中随机取值:tf.random.normal()。例如,随机初始化一个元素服从均值为1,方差为1的正态分布且形状为[2, 3]的tensor:

    In [30]:
    tf.random.normal([2, 3], mean=1, stddev=1) 
    
    Out[30]:
    <tf.Tensor: id=63, shape=(2, 3), dtype=float32, numpy=
    array([[ 1.7034731 ,  0.4979009 ,  1.4266468 ],
           [-0.33414853,  0.2618034 ,  0.3966313 ]], dtype=float32)>
     

    (2)从指定的截断正态分布中随机取值:truncated_normal()。意思是从指定的正太分布中取值,但是取值范围在两个标准差范围内,也就是:[ mean - 2 stddev, mean + 2 stddev ]

    In [31]:
    tf.random.truncated_normal([2, 3], mean=1, stddev=1)
    
    Out[31]:
    <tf.Tensor: id=70, shape=(2, 3), dtype=float32, numpy=
    array([[0.71736836, 1.7930655 , 0.47575486],
           [0.83504593, 0.7969478 , 0.6002228 ]], dtype=float32)>
     

    (3)从指定均匀分布中随机取值:tf.random.uniform()。

    In [32]:
    tf.random.uniform([2, 3], minval=1, maxval=2) # 在1~2之间均匀分布
    
    Out[32]:
    <tf.Tensor: id=78, shape=(2, 3), dtype=float32, numpy=
    array([[1.7117869, 1.2625391, 1.6652637],
           [1.3810604, 1.0297629, 1.1268978]], dtype=float32)>
     

    3 索引

    In [33]:
    a = tf.convert_to_tensor(np.arange(80).reshape(2,2,4,5))
    
    In [34]:
    a
    
    Out[34]:
    <tf.Tensor: id=80, shape=(2, 2, 4, 5), dtype=int32, numpy=
    array([[[[ 0,  1,  2,  3,  4],
             [ 5,  6,  7,  8,  9],
             [10, 11, 12, 13, 14],
             [15, 16, 17, 18, 19]],
    
            [[20, 21, 22, 23, 24],
             [25, 26, 27, 28, 29],
             [30, 31, 32, 33, 34],
             [35, 36, 37, 38, 39]]],
    
    
           [[[40, 41, 42, 43, 44],
             [45, 46, 47, 48, 49],
             [50, 51, 52, 53, 54],
             [55, 56, 57, 58, 59]],
    
            [[60, 61, 62, 63, 64],
             [65, 66, 67, 68, 69],
             [70, 71, 72, 73, 74],
             [75, 76, 77, 78, 79]]]])>
     

    3.1 基础索引

     

    TensorFlow支持Python原生的基础索引方式,即多个方括号逐步索引取值:[idx][idx][idx],每个方括号对应一个维度。

    In [35]:
    a[0]  # 取第一个维度
    
    Out[35]:
    <tf.Tensor: id=85, shape=(2, 4, 5), dtype=int32, numpy=
    array([[[ 0,  1,  2,  3,  4],
            [ 5,  6,  7,  8,  9],
            [10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19]],
    
           [[20, 21, 22, 23, 24],
            [25, 26, 27, 28, 29],
            [30, 31, 32, 33, 34],
            [35, 36, 37, 38, 39]]])>
    In [36]:
    a[0][1]  # 同时筛选两个维度
    
    Out[36]:
    <tf.Tensor: id=94, shape=(4, 5), dtype=int32, numpy=
    array([[20, 21, 22, 23, 24],
           [25, 26, 27, 28, 29],
           [30, 31, 32, 33, 34],
           [35, 36, 37, 38, 39]])>
    In [37]:
    a[0][1][3][3]  # 同时对4个维度进行筛选
    
    Out[37]:
    <tf.Tensor: id=111, shape=(), dtype=int32, numpy=38>
     

    这种索引数据的方法简单,易于理解,但是可读性差,只能按维度依次索引数据,也不能索引列。

     

    3.2 numpy索引

     

    TensorFlow也继承了numpy中的部分索引方式,如果对numpy索引方式不熟悉,可以查看我的前几篇博客
    (1)[idx1, idx2, idx3]
    这种索引方式是在一个方括号内写下所有的索引,每个索引序号之间用逗号隔开。

    In [38]:
    a[1]  # 筛选第一维度,这跟基础索引一样
    
    Out[38]:
    <tf.Tensor: id=116, shape=(2, 4, 5), dtype=int32, numpy=
    array([[[40, 41, 42, 43, 44],
            [45, 46, 47, 48, 49],
            [50, 51, 52, 53, 54],
            [55, 56, 57, 58, 59]],
    
           [[60, 61, 62, 63, 64],
            [65, 66, 67, 68, 69],
            [70, 71, 72, 73, 74],
            [75, 76, 77, 78, 79]]])>
    In [39]:
    a[1,1, 3]  # 同时帅选3个维度
    
    Out[39]:
    <tf.Tensor: id=121, shape=(5,), dtype=int32, numpy=array([75, 76, 77, 78, 79])>
     

    (2)冒号切片与步长:[start:end:step]

     

    这种索引方式在Python原生的list类型中也是常见的,而且使用方法也是一样的。

    In [40]:
    a[1,:,0:2] # 对第1维度选第二块数据,对第二维度选所有数据,对第三维度选前两行
    
    Out[40]:
    <tf.Tensor: id=126, shape=(2, 2, 5), dtype=int32, numpy=
    array([[[40, 41, 42, 43, 44],
            [45, 46, 47, 48, 49]],
    
           [[60, 61, 62, 63, 64],
            [65, 66, 67, 68, 69]]])>
    In [41]:
    a[1,:,0:2,0:4] # 继续上面的例子,对第4维度筛选去前4列
    
    Out[41]:
    <tf.Tensor: id=131, shape=(2, 2, 4), dtype=int32, numpy=
    array([[[40, 41, 42, 43],
            [45, 46, 47, 48]],
    
           [[60, 61, 62, 63],
            [65, 66, 67, 68]]])>
    In [42]:
    a[1,:,0:2,0:4:2] # 对第4维度加上步长,每隔一个数据取一次
    
    Out[42]:
    <tf.Tensor: id=136, shape=(2, 2, 2), dtype=int32, numpy=
    array([[[40, 42],
            [45, 47]],
    
           [[60, 62],
            [65, 67]]])>
     

    也可以使用负值步长表示逆序索引,但要注意,负数步长时,原本的[start : end : step]也要跟着编程[end : start : step]:

    In [43]:
    a[1,:,0:2,4:0:-1]
    
    Out[43]:
    <tf.Tensor: id=141, shape=(2, 2, 4), dtype=int32, numpy=
    array([[[44, 43, 42, 41],
            [49, 48, 47, 46]],
    
           [[64, 63, 62, 61],
            [69, 68, 67, 66]]])>
    In [44]:
    a[1,:,0:2,4:0:-2]
    
    Out[44]:
    <tf.Tensor: id=146, shape=(2, 2, 2), dtype=int32, numpy=
    array([[[44, 42],
            [49, 47]],
    
           [[64, 62],
            [69, 67]]])>
     

    在numpy和TensorFlow中还有“..."(三个英文句号)的使用,“..."用于表示连续多个维度全选:

    In [45]:
    a[1,...,0:4] # 等同于a[1, : , : ,0:4]
    
    Out[45]:
    <tf.Tensor: id=151, shape=(2, 4, 4), dtype=int32, numpy=
    array([[[40, 41, 42, 43],
            [45, 46, 47, 48],
            [50, 51, 52, 53],
            [55, 56, 57, 58]],
    
           [[60, 61, 62, 63],
            [65, 66, 67, 68],
            [70, 71, 72, 73],
            [75, 76, 77, 78]]])>
    In [46]:
    a[0,0,...] # 等同于a[0,0,:,:]
    
    Out[46]:
    <tf.Tensor: id=156, shape=(4, 5), dtype=int32, numpy=
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19]])>
     

    3.3 gather与gather_nd

     

    gather与gather_nd是指TensorFlow通过gather()方法和gather_nd()方法提供的两种索引方式。在numpy中,可以通过嵌套list的方式来指定无规则的索引:

    In [47]:
    b = np.arange(20).reshape(4,5)
    
    In [48]:
    b[1, [0,3,4]] # 选取第2行的第1列、第4列、第5列
    
    Out[48]:
    array([5, 8, 9])
     

    但是在TensorFlow中,这种索引方式并没有从numpy中继承下来,所以如果在Tensor中使用这种方式,会抛出以下异常:
    TypeError: Only integers, slices (:), ellipsis (...), tf.newaxis (None) and scalar tf.int32/tf.int64 tensors are valid indices, got [0, 3, 4]

     

    还好的是,在TensorFlow中通过gather()方法和gather_nd()方法提供了这种索引方法。

     

    (1)gather()方法

    In [54]:
    tf.gather(b, axis=0, indices=[0, 2, 3]) # 选取第1行,第3行,第4行
    
    Out[54]:
    <tf.Tensor: id=163, shape=(3, 5), dtype=int32, numpy=
    array([[ 0,  1,  2,  3,  4],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19]])>
    In [55]:
    tf.gather(b, axis=1, indices=[0, 2, 3]) # 选取第1列,第3列,第4列
    
    Out[55]:
    <tf.Tensor: id=168, shape=(4, 3), dtype=int32, numpy=
    array([[ 0,  2,  3],
           [ 5,  7,  8],
           [10, 12, 13],
           [15, 17, 18]])>
     

    仔细观察上面gather()方法例子,可以发现,第一个参数时数据源,还有两个参数中,axis指的是将要的维度,indices指的是需要选取的序号。

     

    (2)gather_nd()

     

    gather()方法一次只能对一个维度进行索引,gather_nd()方法可以同时对多个维度进行索引。

    In [56]:
    tf.gather_nd(b, [[0, 2],[3, 3]]) # 选取第1行第3列的那个数据,和第4行第4列的数据
    
    Out[56]:
    <tf.Tensor: id=172, shape=(2,), dtype=int32, numpy=array([ 2, 18])>
     

    3.5 条件索引

     

    可以结合一些简单的逻辑运算符进行索引取值:

    In [1]:
    import tensorflow as tf
    
    In [6]:
    a = tf.random.uniform([3,3],minval=-10,maxval=10,dtype=tf.int32)
    a
    
    Out[6]:
    <tf.Tensor: id=17, shape=(3, 3), dtype=int32, numpy=
    array([[-7, -9,  6],
           [-6, -5,  9],
           [ 8,  9,  4]])>
    In [7]:
    mask = a < 0
    mask
    
    Out[7]:
    <tf.Tensor: id=20, shape=(3, 3), dtype=bool, numpy=
    array([[ True,  True, False],
           [ True,  True, False],
           [False, False, False]])>
     

    可以看到,返回的是一个shape与a相同的tensor,在a小于零的位置是True,大于零的位置为False。进一步地,我们可以用boolwan_mask()方法直接取出符合条件的元素:

    In [13]:
    tf.boolean_mask(a,mask)
    
    Out[13]:
    <tf.Tensor: id=82, shape=(4,), dtype=int32, numpy=array([-7, -9, -6, -5])>
     

    可以结合where()方法取出符合条件元素的索引:

    In [14]:
    m_index = tf.where(mask)
    m_index
    
    Out[14]:
    <tf.Tensor: id=84, shape=(4, 2), dtype=int64, numpy=
    array([[0, 0],
           [0, 1],
           [1, 0],
           [1, 1]], dtype=int64)>
     

    再使用之前说过的gather_nd()方法取值:

    In [15]:
    tf.gather_nd(a,m_index)
    
    Out[15]:
    <tf.Tensor: id=86, shape=(4,), dtype=int32, numpy=array([-7, -9, -6, -5])>
     

    where()方法还有第二种用法——从两个tensor中取出符合条件的值,这时候where()方法必须接受3个参数:

    In [26]:
    condition = tf.random.uniform([3,3],minval=0,maxval=2,dtype=tf.int32)
    condition = tf.cast(condition, tf.bool)
    condition
    
    Out[26]:
    <tf.Tensor: id=124, shape=(3, 3), dtype=bool, numpy=
    array([[ True,  True, False],
           [ True, False, False],
           [ True, False, False]])>
    In [34]:
    a = tf.range(1,10)
    a = tf.reshape(a,[3,3])
    a
    
    Out[34]:
    <tf.Tensor: id=162, shape=(3, 3), dtype=int32, numpy=
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])>
    In [35]:
    b = tf.range(-9,0)
    b = tf.reshape(b,[3,3])
    b
    
    Out[35]:
    <tf.Tensor: id=169, shape=(3, 3), dtype=int32, numpy=
    array([[-9, -8, -7],
           [-6, -5, -4],
           [-3, -2, -1]])>
    In [36]:
    tf.where(condition, a, b)
    
    Out[36]:
    <tf.Tensor: id=171, shape=(3, 3), dtype=int32, numpy=
    array([[ 1,  2, -7],
           [ 4, -5, -4],
           [ 7, -2, -1]])>
     

    上面where()方法返回的结果在True的位置取值是a中对应位置元素的值,在False位置是b中对应元素的值。

     

    4 维度变换

     

    4.1 reshape()

     

    numpy中的ndarray数组有个一reshape()方法,用来改变数组的shape,TensorFlow中的reshape()方法,功能也是一样的,不过TensorFlow中的reshape()没有绑定到tensor中:

    In [58]:
    a = tf.ones([2,3,4])
    
    In [59]:
    a.shape
    
    Out[59]:
    TensorShape([2, 3, 4])
    In [60]:
    a
    
    Out[60]:
    <tf.Tensor: id=176, shape=(2, 3, 4), dtype=float32, numpy=
    array([[[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]],
    
           [[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]]], dtype=float32)>
    In [61]:
    b = tf.reshape(a, [2, 2, 6])
    
    In [62]:
    b.shape
    
    Out[62]:
    TensorShape([2, 2, 6])
    In [64]:
    b
    
    Out[64]:
    <tf.Tensor: id=179, shape=(2, 2, 6), dtype=float32, numpy=
    array([[[1., 1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1., 1.]],
    
           [[1., 1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1., 1.]]], dtype=float32)>
    In [65]:
    c = tf.reshape(a, [3, 2, 4])
    
    In [66]:
    c
    
    Out[66]:
    <tf.Tensor: id=183, shape=(3, 2, 4), dtype=float32, numpy=
    array([[[1., 1., 1., 1.],
            [1., 1., 1., 1.]],
    
           [[1., 1., 1., 1.],
            [1., 1., 1., 1.]],
    
           [[1., 1., 1., 1.],
            [1., 1., 1., 1.]]], dtype=float32)>
     

    可以看到,在上面的例子中,通过reshape()方法可以很方便的改变tensor的形状,得到一个新的tensor,需要注意的是在进行维度变换时,数据的重量是不变的,上面的例子无论是[2,3,4], [2, 2, 6]还是[3, 2, 4]都对应总量24,如果对应不上,就会产生异常。

     

    4.2 转置:transpose()

     

    transpose()方法提供了一种类似于装置的操作:

    In [75]:
    a = tf.constant([[1,2,3],[4,5,6]])
    
    In [76]:
    a.shape
    
    Out[76]:
    TensorShape([2, 3])
    In [77]:
    b = tf.transpose(a)
    
    In [78]:
    b.shape
    
    Out[78]:
    TensorShape([3, 2])
    In [79]:
    b
    
    Out[79]:
    <tf.Tensor: id=192, shape=(3, 2), dtype=int32, numpy=
    array([[1, 4],
           [2, 5],
           [3, 6]])>
     

    在默认情况下,transpose()方法会将所有维度按逆序方式完全转置,当然也可以通过perm参数执行需要转置的维度:

    In [80]:
    a=tf.constant([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
    
    In [81]:
    a
    
    Out[81]:
    <tf.Tensor: id=194, shape=(2, 2, 3), dtype=int32, numpy=
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])>
    In [82]:
    b = tf.transpose(a) # 不指定perm参数时,相当于tf.transpose(a, perm=[2, 1, 0])
    
    In [83]:
    b
    
    Out[83]:
    <tf.Tensor: id=197, shape=(3, 2, 2), dtype=int32, numpy=
    array([[[ 1,  7],
            [ 4, 10]],
    
           [[ 2,  8],
            [ 5, 11]],
    
           [[ 3,  9],
            [ 6, 12]]])>
    In [84]:
    c = tf.transpose(a, perm=[2, 1, 0])
    
    In [85]:
    c
    
    Out[85]:
    <tf.Tensor: id=200, shape=(3, 2, 2), dtype=int32, numpy=
    array([[[ 1,  7],
            [ 4, 10]],
    
           [[ 2,  8],
            [ 5, 11]],
    
           [[ 3,  9],
            [ 6, 12]]])>
    In [86]:
    d = tf.transpose(a, perm=[0, 2, 1]) # 第一个维度不做变换,对第二、第三维度进行转置
    
    In [87]:
    d
    
    Out[87]:
    <tf.Tensor: id=203, shape=(2, 3, 2), dtype=int32, numpy=
    array([[[ 1,  4],
            [ 2,  5],
            [ 3,  6]],
    
           [[ 7, 10],
            [ 8, 11],
            [ 9, 12]]])>
     

    4.3 添加维度:expand_dims()

    In [88]:
    a=tf.constant([[1,2,3],[4,5,6]])
    
    In [89]:
    a
    
    Out[89]:
    <tf.Tensor: id=205, shape=(2, 3), dtype=int32, numpy=
    array([[1, 2, 3],
           [4, 5, 6]])>
    In [90]:
    tf.expand_dims(a, axis=0)
    
    Out[90]:
    <tf.Tensor: id=208, shape=(1, 2, 3), dtype=int32, numpy=
    array([[[1, 2, 3],
            [4, 5, 6]]])>
    In [91]:
    tf.expand_dims(a, axis=1)
    
    Out[91]:
    <tf.Tensor: id=211, shape=(2, 1, 3), dtype=int32, numpy=
    array([[[1, 2, 3]],
    
           [[4, 5, 6]]])>
    In [92]:
    tf.expand_dims(a, axis=-1)
    
    Out[92]:
    <tf.Tensor: id=214, shape=(2, 3, 1), dtype=int32, numpy=
    array([[[1],
            [2],
            [3]],
    
           [[4],
            [5],
            [6]]])>
    In [93]:
    tf.expand_dims(a, axis=2)
    
    Out[93]:
    <tf.Tensor: id=217, shape=(2, 3, 1), dtype=int32, numpy=
    array([[[1],
            [2],
            [3]],
    
           [[4],
            [5],
            [6]]])>
     

    expand_dims()方法添加维度时,通过axis参数指定添加维度的位置,正数表示从前往后数,负数表示从后往前数。

     

    4.4 压缩维度:squeeze()

     

    squeeze()方法与expand_dims()方法作用刚好相反,其作用是删除张量中dim为1的维度:

    In [94]:
    a = tf.ones([1,3,1,2])
    
    In [95]:
    a
    
    Out[95]:
    <tf.Tensor: id=221, shape=(1, 3, 1, 2), dtype=float32, numpy=
    array([[[[1., 1.]],
    
            [[1., 1.]],
    
            [[1., 1.]]]], dtype=float32)>
    In [96]:
    tf.squeeze(a)
    
    Out[96]:
    <tf.Tensor: id=223, shape=(3, 2), dtype=float32, numpy=
    array([[1., 1.],
           [1., 1.],
           [1., 1.]], dtype=float32)>

  • 相关阅读:
    gitlab+jenkens+maven私服
    记录一次gitlab+jenkins入坑到排坑的过程
    python进阶之路一,变量、运算符、判断、while循环
    cat EOF追加与覆盖
    tcpdump使用
    iptables学习
    Java生产消费模型—ArrayBlockingQueue详解
    Java泛型详解(透彻)
    Java源码初探_logging日志模块实现
    Java设计模式学习总结
  • 原文地址:https://www.cnblogs.com/chenhuabin/p/11561633.html
Copyright © 2011-2022 走看看