In [1]: import tensorflow as tf
In [2]:
In [2]: a = tf.random.shuffle(tf.range(6))
2019-10-25 10:09:55.688044: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
In [3]: a
Out[3]: <tf.Tensor: id=4, shape=(6,), dtype=int32, numpy=array([5, 2, 0, 3, 1, 4])>
In [4]: tf.sort(a) # 默认是顺序排列
Out[4]: <tf.Tensor: id=17, shape=(6,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5])>
In [5]: tf.sort(a, direction='ASCENDING') # 默认顺序排列
Out[5]: <tf.Tensor: id=30, shape=(6,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5])>
In [6]: tf.sort(a, direction='DESCENDING') # 指定逆序排列
Out[6]: <tf.Tensor: id=40, shape=(6,), dtype=int32, numpy=array([5, 4, 3, 2, 1, 0])>
也对多维Tensor排序,当对多维Tensor进行排序时,可以通过axis参数指定需要排序的维度,默认axis默认值为-1,也就是对最后一维进行排序。
In [7]: b = tf.random.uniform([3, 3], minval=1, maxval=10,dtype=tf.int32)
In [8]: b
Out[8]:
<tf.Tensor: id=46, shape=(3, 3), dtype=int32, numpy=
array([[6, 6, 8],
[1, 2, 8],
[3, 1, 9]])>
In [9]: tf.sort(b)
Out[9]:
<tf.Tensor: id=59, shape=(3, 3), dtype=int32, numpy=
array([[6, 6, 8],
[1, 2, 8],
[1, 3, 9]])>
In [10]: tf.sort(b,axis=0) # 通过axis参数指定第一维度,也就是列进行排序
Out[10]:
<tf.Tensor: id=75, shape=(3, 3), dtype=int32, numpy=
array([[1, 1, 8],
[3, 2, 8],
[6, 6, 9]])>
In [11]: a
Out[11]: <tf.Tensor: id=4, shape=(6,), dtype=int32, numpy=array([5, 2, 0, 3, 1, 4])>
In [12]: tf.argsort(a, direction='ASCENDING') # 返回排序之后的索引组成的Tensor, 默认是顺序排列
Out[12]: <tf.Tensor: id=88, shape=(6,), dtype=int32, numpy=array([2, 4, 1, 3, 5, 0])>
In [13]: tf.argsort(a, direction='DESCENDING') # n逆序排列
Out[13]: <tf.Tensor: id=99, shape=(6,), dtype=int32, numpy=array([0, 5, 3, 1, 4, 2])>
可以通过axis参数指定需要排序的维度,默认获取-1维度排序后索引:
In [14]: b
Out[14]:
<tf.Tensor: id=46, shape=(3, 3), dtype=int32, numpy=
array([[6, 6, 8],
[1, 2, 8],
[3, 1, 9]])>
In [15]: tf.argsort(b) # 默认对最后一维度排序,也就是以行为单位排序
Out[15]:
<tf.Tensor: id=112, shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
[0, 1, 2],
[1, 0, 2]])>
In [16]: tf.argsort(b,axis=0) # 指定第一维度进行排序,也就是以列为单位进行排序
Out[16]:
<tf.Tensor: id=127, shape=(3, 3), dtype=int32, numpy=
array([[1, 2, 0],
[2, 1, 1],
[0, 0, 2]])>
返回的张量中,每一个元素表示b中原来元素在该行中的索引。
sort()方法和argsort()方法都是对给定Tensor的所有元素进行排序,在某些情况下如果我们只是要获取排序的前几个元素,这时候使用sort()或argsort()方法就有些浪费时间了,这时候可以使用top_k()方法。top_k()方法可以指定获取前k个元素。
注意:top_k()方法在tf.math模块中。
In [17]: a
Out[17]: <tf.Tensor: id=4, shape=(6,), dtype=int32, numpy=array([5, 2, 0, 3, 1, 4])>
In [18]: top_2 = tf.math.top_k(a, 2) # 获取排序后前两位
In [19]: top_2
Out[19]: TopKV2(values=<tf.Tensor: id=131, shape=(2,), dtype=int32, numpy=array([5, 4])>, indices=<tf.Tensor: id=132, shape=(2,), dtype=int32, numpy=array([0, 5])>)
从上述输出可以看到,top_k()方法返回的是一个TopKV2类型对象,内部包含两部分数据:第一部分是排序后的真实数据[5, 4],可以通过TopKV2对象的values属性获取;第二部分是排序后数据所在原Tensor中的索引[2, 5],可以通过TopKV2对象的indices获取。
In [20]: top_2.values
Out[20]: <tf.Tensor: id=131, shape=(2,), dtype=int32, numpy=array([5, 4])>
In [21]: top_2.indices
Out[21]: <tf.Tensor: id=132, shape=(2,), dtype=int32, numpy=array([0, 5])>
对于高维Tensor也是一样的:
In [22]: b
Out[22]:
<tf.Tensor: id=46, shape=(3, 3), dtype=int32, numpy=
array([[6, 6, 8],
[1, 2, 8],
[3, 1, 9]])>
In [23]: tf.math.top_k(b, 2)
Out[23]:
TopKV2(values=<tf.Tensor: id=139, shape=(3, 2), dtype=int32, numpy=
array([[8, 6],
[8, 2],
[9, 3]])>, indices=<tf.Tensor: id=140, shape=(3, 2), dtype=int32, numpy=
array([[2, 0],
[2, 1],
[2, 0]])>)
In [24]: a = tf.random.uniform([3, 3], minval=1, maxval=10, dtype=tf.int32)
In [25]: a
Out[25]:
<tf.Tensor: id=146, shape=(3, 3), dtype=int32, numpy=
array([[3, 7, 4],
[3, 7, 4],
[7, 2, 5]])>
不指定维度时,获取整个Tensor的最小值:
In [26]: tf.reduce_min(a) # 最小值
Out[26]: <tf.Tensor: id=149, shape=(), dtype=int32, numpy=2>
通过axis参数可以对指定维度求最小值:
In [27]: tf.reduce_min(a, axis=0) # 求指定维度的最小值
Out[27]: <tf.Tensor: id=152, shape=(3,), dtype=int32, numpy=array([3, 2, 4])>
###(2)reduce_max():求最大值
In [29]: tf.reduce_max(a) # 最大值
Out[29]: <tf.Tensor: id=155, shape=(), dtype=int32, numpy=7>
In [30]: tf.reduce_max(a, axis=-1) # 求最后一维度的最大值
Out[30]: <tf.Tensor: id=158, shape=(3,), dtype=int32, numpy=array([7, 7, 7])>
不指定维度时,求整个Tensor所有元素的平均值:
In [31]: tf.reduce_mean(a) # 整个Tensor所有元素的平均值
Out[31]: <tf.Tensor: id=161, shape=(), dtype=int32, numpy=4>
In [32]: tf.reduce_mean(a, axis=0) # 求第一维度(行)均值
Out[32]: <tf.Tensor: id=164, shape=(3,), dtype=int32, numpy=array([4, 5, 4])>
在上面求均值的例子中,因为Tensor的dtype为int32,所以求出来的均值也是int32,而不是浮点型。如果需要求浮点型的均值,就需要将a的类型先转换为float32:
In [33]: tf.reduce_mean(tf.cast(a, tf.float32), axis=0)
Out[33]: <tf.Tensor: id=168, shape=(3,), dtype=float32, numpy=array([4.3333335, 5.3333335, 4.3333335], dtype=float32)>
argmin()、argmax()返回最大值最小值的索引组成的Tensor。
In [34]: a = tf.random.uniform([3,3],minval=1, maxval=10, dtype=tf.int32)
In [35]: a
Out[35]:
<tf.Tensor: id=173, shape=(3, 3), dtype=int32, numpy=
array([[1, 6, 6],
[6, 5, 2],
[1, 6, 6]])>
In [36]: b = tf.random.uniform([3,3,3],minval=1, maxval=10, dtype=tf.int32)
In [37]: b
Out[37]:
<tf.Tensor: id=178, shape=(3, 3, 3), dtype=int32, numpy=
array([[[4, 3, 6],
[6, 4, 4],
[6, 5, 5]],
[[6, 2, 5],
[7, 6, 4],
[2, 4, 7]],
[[1, 5, 2],
[1, 5, 1],
[5, 5, 4]]])>
In [38]: tf.argmin(a) # 默认是第0维度
Out[38]: <tf.Tensor: id=181, shape=(3,), dtype=int64, numpy=array([0, 1, 1], dtype=int64)>
In [39]: tf.argmin(b)
Out[39]:
<tf.Tensor: id=184, shape=(3, 3), dtype=int64, numpy=
array([[2, 1, 2],
[2, 0, 2],
[1, 1, 2]], dtype=int64)>
对于shape为(3, 3)的Tensor,argmin(a)返回的是shape为(3,)的Tensor,因为没有指定比较的维度,默认比较的是第0维度的元素,也就是每一列数据;对于shape为(3,3,3)的Tensor,argmin(a)返回的是shape为(3,3)的Tensor,默认比较的是第0维度的元素,也就是每一块对应位置的元素,例如第一块的5、第二块的9、第三块的9比较,第一块的5最小,索引为0,所以返回的Tensor中第一个元素是0。
注意:argmin()方法在没有指定维度时,默认返回的是第0维度最小值的索引,这与reducemin()方法不同,reducemin()方法在没有指定维度是是返回整个Tensor中所有元素中的最小值。
In [40]: a = tf.random.uniform([3,3,3],minval=1, maxval=10, dtype=tf.int32)
In [41]: a
Out[41]:
<tf.Tensor: id=189, shape=(3, 3, 3), dtype=int32, numpy=
array([[[9, 5, 5],
[7, 6, 2],
[4, 8, 5]],
[[4, 1, 1],
[5, 3, 8],
[9, 1, 4]],
[[8, 4, 2],
[1, 4, 2],
[1, 2, 1]]])>
In [42]: tf.argmax(a, axis=0) # 第一维度,也就是每一块
Out[42]:
<tf.Tensor: id=192, shape=(3, 3), dtype=int64, numpy=
array([[0, 0, 0],
[0, 0, 1],
[1, 0, 0]], dtype=int64)>
In [43]: tf.argmax(a, axis=2) # 第三维度,也就是每一行
Out[43]:
<tf.Tensor: id=195, shape=(3, 3), dtype=int64, numpy=
array([[0, 0, 1],
[0, 2, 0],
[0, 1, 1]], dtype=int64)>