8.张量排序,填充与复制

8.张量排序,填充与复制

I. 张量排序

1.tf.sort/argsort()

通过设置参数direction为DESCENDING则为降序排列,默认为升序排列
tf.sort(values,axis=-1,direction=‘ASCENDING’):对某一维度排序,
tf.argsort(values,axis=-1,direction=‘ASCENDING’):排序索引,得到排序后的索引

  • 一维排序
In [46]: a=tf.random.shuffle(tf.range(5)) #打乱

In [49]: a
Out[49]: <tf.Tensor: id=116, shape=(5,), dtype=int32, numpy=array([2, 1, 4, 0, 3])>

In [47]: tf.sort(a,direction='DESCENDING') #降序
Out[47]: <tf.Tensor: id=124, shape=(5,), dtype=int32, numpy=array([4, 3, 2, 1, 0])>

In [51]: tf.argsort(a,direction='DESCENDING')
Out[51]: <tf.Tensor: id=144, shape=(5,), dtype=int32, numpy=array([2, 4, 0, 1, 3])>

In [53]: idx =tf.argsort(a,direction='DESCENDING')

In [54]: tf.gather(a,idx) #利用index收集最值,还原出来
Out[54]: <tf.Tensor: id=155, shape=(5,), dtype=int32, numpy=array([4, 3, 2, 1, 0])>
  • 多维排序
In [56]: a=tf.random.uniform([3,3],maxval=10,dtype=tf.int32)

In [57]: a
Out[57]:
<tf.Tensor: id=159, shape=(3, 3), dtype=int32, numpy=
array([[0, 6, 6],
       [2, 3, 0],
       [9, 0, 5]])>

In [58]: tf.sort(a)
Out[58]:
<tf.Tensor: id=170, shape=(3, 3), dtype=int32, numpy=
array([[0, 6, 6],
       [0, 2, 3],
       [0, 5, 9]])>

In [59]: tf.sort(a,direction='DESCENDING')
Out[59]:
<tf.Tensor: id=178, shape=(3, 3), dtype=int32, numpy=
array([[6, 6, 0],
       [3, 2, 0],
       [9, 5, 0]])>

In [60]: idx = tf.argsort(a)

In [61]: idx
Out[61]:
<tf.Tensor: id=189, shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [2, 0, 1],
       [1, 2, 0]])>

In [62]: tf.gather(a,idx) #多维排序,还原会出错
Out[62]:
<tf.Tensor: id=191, shape=(3, 3, 3), dtype=int32, numpy=
array([[[0, 6, 6],
        [2, 3, 0],
        [9, 0, 5]],

       [[9, 0, 5],
        [0, 6, 6],
        [2, 3, 0]],

       [[2, 3, 0],
        [9, 0, 5],
        [0, 6, 6]]])>
2.Top_k之tf.math.top_k()最大的前k个元素

tf.math.top_k(input, k=1, sorted=True)
参数:
input:张量
k:沿维度查找的个数
sort:为True表示k个元素按照值降序排列
返回值:两个对象
values:沿每个维度的k个值
indices:values所对应的索引

In [63]: a=tf.constant([[4,6,8],[9,4,7],[4,5,1]])

In [64]: a
Out[64]:
<tf.Tensor: id=192, shape=(3, 3), dtype=int32, numpy=
array([[4, 6, 8],
       [9, 4, 7],
       [4, 5, 1]])>

In [66]: res=tf.math.top_k(a,2)

In [69]: res
Out[69]:
TopKV2(values=<tf.Tensor: id=194, shape=(3, 2), dtype=int32, numpy=
array([[8, 6],
       [9, 7],
       [5, 4]])>, indices=<tf.Tensor: id=195, shape=(3, 2), dtype=int32, numpy=
array([[2, 1],
       [0, 2],
       [1, 0]])>)


In [67]: res.indices  #索引
Out[67]:
<tf.Tensor: id=195, shape=(3, 2), dtype=int32, numpy=
array([[2, 1],
       [0, 2],
       [1, 0]])>

In [68]: res.values  #值
Out[68]:
<tf.Tensor: id=194, shape=(3, 2), dtype=int32, numpy=
array([[8, 6],
       [9, 7],
       [5, 4]])>

3.top-k accuracy
  • Prob(预测概率):[0.1, 0.2, 0.3, 0.4] 则按照索引来预测的结果最有可能是3
  • Label:[2] (真实值)
  • Only consider top-1 prediction: [3] 当我们按照top-1来预测时结果是3,则预测对的个数是0,预测的次数是1,故它的准确度是0/1 = 0%
  • Only consider top-2 prediction:[3, 2] ;考虑不仅仅是最有可能的预测值,而且还是次最有可能的预测值,则前两个概率最大的是0.4,0.3对应的值是3,2,里面还有正确值2,则它预测对的个数是1,预测的次数是1,故它的准确率是1/1 = 100%;top-2 accuracy:只需要保证前2个有一个预测为正确就好了
  • Only consider top-3 prediction:[3,2,1],类似上例,它预测对的个数是1,预测的次数是1,故它的准确率是1/1 = 100%
    注意:这就是top-k accuracy的定义,可以看出top-1 accuracy是要求最严格的,因为我们要去概率最大的那个是预测对的,但是实际上top-1可能没有这么表现好。例如:我们在imagenet上面,有1000个类别,每个类的物种是非常复杂的,我们做预测时会发现不太容易,有时只有70%的top-1 accuracy,或者80%的top-1 accuracy
    那么为了很好的检测一个算法的性能,我们还会考虑另一个指标,Top-5 accuracy,也就是说1000个类别中,如果前5个预测最高的可能性之中有一个预测对了,那么我们就可以认为它预测对了。虽然没有top-1那么精准,但是top-5也能从另一个方面反映模型是否比较好,是否优于目前的。
    计算top-5 accuracy
In [29]: prob= tf.constant([[0.1,0.2,0.7],[0.2,0.7,0.1]]) #第一个预测值是2,第二个预测值是1

In [30]: target=tf.constant([2,0]) #两个的真实值

In [32]: k_b=tf.math.top_k(prob,3).indices

In [33]: k_b 
Out[33]:
<tf.Tensor: id=40, shape=(2, 3), dtype=int32, numpy=
array([[2, 1, 0],
       [1, 0, 2]])> #预测值

In [34]: k_b = tf.transpose(k_b,[1,0]) #转置

In [35]: k_b
Out[35]:
<tf.Tensor: id=42, shape=(3, 2), dtype=int32, numpy=
array([[2, 1],  #top-1
       [1, 0],  #top-2
       [0, 2]])>  #top-3

In [36]: target=tf.broadcast_to(target,[3,2])

In [37]: target
Out[37]:
<tf.Tensor: id=44, shape=(3, 2), dtype=int32, numpy=
array([[2, 0],
       [2, 0],
       [2, 0]])>

计算举例

II.填充与复制

1.tf.pad() 填充

tf.pad(a, [ [1, 2], [3, 4] ]) 在矩阵中,[1, 2]表示在行上填充,1指在前面填充一行,2指在后面填充2行;[3, 4]表示在列上填充,3指在列前面填充3列,4指在列上填充4列
填充示意图

In [70]: a=tf.reshape(tf.range(9),[3,3])

In [71]: a
Out[71]:
<tf.Tensor: id=201, shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])>

In [73]: tf.pad(a,[[0,0],[0,0]]) #0表示未填充任何数据
Out[73]:
<tf.Tensor: id=203, shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])>

In [74]: tf.pad(a,[[0,0],[1,2]]) #只填充列
Out[74]:
<tf.Tensor: id=205, shape=(3, 6), dtype=int32, numpy=
array([[0, 0, 1, 2, 0, 0],
       [0, 3, 4, 5, 0, 0],
       [0, 6, 7, 8, 0, 0]])>

In [75]: tf.pad(a,[[1,1],[0,0]]) #只填充行
Out[75]:
<tf.Tensor: id=207, shape=(5, 3), dtype=int32, numpy=
array([[0, 0, 0],
       [0, 1, 2],
       [3, 4, 5],
       [6, 7, 8],
       [0, 0, 0]])>

In [78]: tf.pad(a,[[1,1],[2,0]]) #行列都填充
Out[78]:
<tf.Tensor: id=211, shape=(5, 5), dtype=int32, numpy=
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 1, 2],
       [0, 0, 3, 4, 5],
       [0, 0, 6, 7, 8],
       [0, 0, 0, 0, 0]])>     

应用:图片,句子的填充,为了等长需要进行填充成定长
Image padding

In [79]: a=tf.random.normal([4,28,28,3])

In [83]: b=tf.pad(a,[[0,0],[2,2],[2,2],[0,0]]) #在第二,三维度前后各填充2,
In [84]: b.shape
Out[84]: TensorShape([4, 32, 32, 3])

In [80]: c=tf.pad(a,[[1,1],[2,2],[3,3],[4,4]]) #一般padding为行和列,多维度,在对应的维度上增加相应的列数

In [81]: c.shape
Out[81]: TensorShape([6, 32, 34, 11])

imagepadding卷积时,实现相同的卷积

2.tf.tile() 数据复制

tf.tile()在内存上真实的复制, tf.broadcast_to()隐性复制

In [87]: a
Out[87]:
<tf.Tensor: id=228, shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])>

In [88]: tf.tile(a,[1,2]) # 1(当前的维度复制一次保持不变)表示第一个维度
#复制的次数,2表示第二个维度复制的次数
Out[88]:
<tf.Tensor: id=230, shape=(3, 6), dtype=int32, numpy=
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]])>

In [89]: tf.tile(a,[2,1])
Out[89]:
<tf.Tensor: id=232, shape=(6, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8],
       [0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])>

In [90]: tf.tile(a,[2,2])
Out[90]:
<tf.Tensor: id=234, shape=(6, 6), dtype=int32, numpy=
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8],
       [0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]])>
3.tf.tile() VS tf.broadcast_to()

将a.shape为[3, 3]扩展成[2, 3, 3]

  1. 可以通过:tf.expand_dims()和tf.tile()来完成这样的操作
  2. 也可通过:tf.broadcast_to()来完成这个操作
  3. 两者效果都是一样的,只是tf.broadcast_to不需要占用内存,故运行时性能更强
  4. tf.broadcast_to不需要显式调用,在计算中会有广播机构存在
In [91]: aa=tf.expand_dims(a,axis=0) #在0维度前面增加一个维度

In [92]: aa
Out[92]:
<tf.Tensor: id=236, shape=(1, 3, 3), dtype=int32, numpy=
array([[[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]])>

In [93]: tf.tile(aa,[2,1,1])
Out[93]:
<tf.Tensor: id=238, shape=(2, 3, 3), dtype=int32, numpy=
array([[[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]],

       [[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]])>

In [94]: tf.broadcast_to(aa,[2,3,3])
Out[94]:
<tf.Tensor: id=240, shape=(2, 3, 3), dtype=int32, numpy=
array([[[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]],

       [[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]])>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值