【TensorFlow2.0】(7) 张量排序、填充、复制、限幅、坐标选择
各位同學好,今天和大家分享一下TensorFlow2.0中的一些操作。內容有:
(1)排序 tf.sort()、tf.argsort()、top_k();(2)填充 tf.pad();(3)復制 tf.tile();(4)限幅 tf.clip_by_value()、tf.maximum()、tf.nn.relu()、tf.clip_by_norm();(5)根據坐標選擇 tf.where()
那我們開始吧。
1. 張量排序
1.1 tf.sort() 和 tf.argsort()
按升序或降序對張量進行排序,返回排序后的結果:
tf.sort(tensor, direction)
direction 指降序還是升序,默認升序排序。降序:direction='DESCENDING' ;升序:direction='ASCENDING'
按升序或降序對張量進行排序,返回索引:排序后的當前位置在原始位置中的索引:
tf.argsort(tensor, direction)
參數設置和tf.sort()相同
# 生成一維tensor,打亂順序
a = tf.random.shuffle(tf.constant([7,8,9,10,11]))
# 排序,返回值為降序排序的結果
tf.sort(a,direction='DESCENDING')
# 返回降序排序后的索引
tf.argsort(a,direction='DESCENDING')
首先我們定義一個tensor為 [8, 7, 10, 9, 11],通過降序排序,返回結果為?[11,10,9,8,7],得到降序排序的索引為 [4,2,3,0,1]。返回結果11在原數據中的索引為4,返回結果10在原數據中索引位置為2,返回結果9在原數據中索引位置為3。
我們也可以通過返回的索引坐標利用tf.gather()函數來獲取排序后的結果,idx中保存的是降序排序后的索引位置,gather函數針對給定的索引位置對tensor中的值進行搜集,返回降序排序好了的結果。
a = tf.random.shuffle(tf.constant([7,8,9,10,11]))
# 有了排序索引之后,我們可以通過索引來獲取原tensor中的值
# idx保存降序后的值在原數據中的索引
idx = tf.argsort(a,direction='DESCENDING')
# 使用tf.gather()按照指定索引獲取數據
tf.gather(a,idx)
我們看一下對于二維的tensor如何排序
# 創建一個3行3列每個元素在0-9之間的tensor
a = tf.random.uniform([3,3],maxval=10,dtype=tf.int32)
# 對a升序排序
tf.sort(a) # 返回排序后結果
tf.argsort(a) # 獲取改變后的元素,在原位置的索引
?對最內層維度進行升序排序,每一行返回列排序結果
1.2 top_k()
tf.math.top_k(tensor, k)
sort()方法和argsort()方法都是對給定Tensor的所有元素排序,在某些情況下如果我們只是要獲取排序的前幾個元素,這時候可以使用top_k()方法,指定獲取前k個元素。top_k()方法只能對最后一維進行排序
top_k()方法的返回值由兩部分構成,一部分是獲取的數據,另一部分是在原數據中的索引位置
# 創建3行3列的tensor,每個元素在0-9之間
a = tf.random.uniform([3,3],maxval=10,dtype=tf.int32)
# 返回前2個最大的值和索引
res = tf.math.top_k(a,2)
# 查看前兩個最大的值
res.values
# 查看前兩個最大值在原數據中的索引位置
res.indices
以第一行為例,返回最大的兩個數是 [9,3],9在原數據中的索引是1,而3在原數據中的索引為0。?
2. 填充
tf.pad( tensor, paddings )
tensor指需要填充的張量,paddings指出要給tensor的哪個維度進行填充,以及填充方式,要注意的是paddings的rank必須和tensor的rank相同
# 生成0-8的tensor,重新塑形變成3行3列
a = tf.reshape(tf.range(9),[3,3])
# 填充該tensor
# 行的上下都不填充,列的上下也不填充,不改變
tf.pad(a,[[0,0],[0,0]])
# 行的上邊填充1行,下邊不填充;列的左邊不填充,右邊填充一列
tf.pad(a,[[1,0],[0,1]])
對于一個二維的tensor,tf.pad( a, [ [1,0], [0,1] ]?) 中的paddings的左邊的括號代表第0個維度,即行維度,右邊的括號代表第1個維度,即列維度。[1,0] 是指對行維度上的上側填充一行,下側不填充。[0,1] 是指對列維度上的左側不填充,右側填充一列。用0填充。
對于一個四維的tensor,shape為[4,28,28,3],即有4張圖像,有28行28列,3個通道,對行列填充,shape變成[4,32,32,3]
# 4張圖像28行28列3通道
a = tf.random.normal([4,28,28,3])
# 擴寬圖像的行列,左右上下邊都填充
b = tf.pad(a,[[0,0],[2,2],[2,2],[0,0]])
b.shape
第0個維度圖像維度[0,0]不填充;第1個維度行維度[2,2],行的上側和下側都填充2行;第2個維度列維度[2,2],列維度的左右側都填充2列;最后一個維度[0,0]不改變
3. 復制
tf.tile(input, multiples)
用于對張量進行擴張,將前面的數據進行復制然后直接接在原數據后面。input代表輸入的tensor變量,multiples代表在同一個維度上復制的次數。
# 創建一個3行3列的tensor
a = tf.reshape(tf.range(9),[3,3])
# 1代表第一個維度復制的次數,2代表第二個維度復制的次數
tf.tile(a,[1,2])
# 第一個維度變成了原來的2倍,把原來的復制了2遍。第二個維度變成2倍
tf.tile(a,[2,2])
復制時先對小維度復制,再對大維度復制。tf.tile(a,[1,2])中,2代表新tensor的第二個維度(列維度) 是原tensor第二個維度的2倍。1代表新tensor的第一個維度(行維度) 是原tensor第一個維度的1倍,即,沒有擴張第一個維度,只是把它一模一樣復制過來。
4. 張量限幅
4.1?tf.clip_by_value()
tf.clip_by_value(tensor, min, max)
對tensor限幅,將一個張量的值限制在指定的最大值和最小值之間。
# 根據數值來限幅
a = tf.range(10)
# 把數據值限制在2-7之間,張量a中的值小于2的都返回2,大于7的都返回7
tf.clip_by_value(a,2,7)
變量a的值為[0,1,2,3,4,5,6,7,8,9],將a中的值限制在2到7之間,所有小于2的值都返回2,所有大于7的值都返回7。
4.2 tf.maximum() 和 tf.minimum()
tf.maximum(x, y)? ?指定下限,返回所有x>y的值,小于y的值變成y
tf.minimum(x, y)? ??指定上限,返回所有x<y的值,大于y的值變成y
通過 tf.minimum(tf.maxmum(x, a), b) 把x的值限制在a到b之間
a = tf.range(10)
# 限制最小值為2
tf.maximum(a,2)
# 限制最大值為7
tf.minimum(a,7)
# 限制在兩個區間內
tf.minimum(tf.maximum(a,2),7)
4.3 tf.nn.relu()
tf.nn.relu(tensor)
用于限制下限幅。輸入小于0的值,幅值為0,輸入大于0的值則不變
# 創建一個-5到4的一維tensor
a = tf.range(-5,5)
# 限制下限幅,小于0都返回是0
tf.nn.relu(a)
?該方法相當于使用 tf.maximum(a,0) 來限制下限。
4.4?tf.clip_by_norm()
根據范數來限幅:?tf.clip_by_norm(tensor, 指定范數大小)
對梯度進行裁剪,通過控制梯度的最大范數,防止梯度爆炸的問題
不改變tensor的方向,只改變tensor模的大小,使限幅后的數值的二范數為指定的范數值。計算方法是,將所有元素都乘上 指定范數/原范數。
# 根據范數來限幅
a = tf.constant([[1,2],[3,4]],dtype=tf.float32)
# 求tensor變量的二范數
tf.norm(a)
# 指定新的范數,使改變后的數值計算后得到這個新范數
a = tf.clip_by_norm(a,4)
# 計算二范數
tf.norm(a)
5. 根據坐標選擇值
tf.where(condition, x, y)
condition 是一個tensor,是布爾類型的數據;如果x、y均為空,那么返回condition中的值為True的位置的Tensor;如果x、y均存在,那么如果condition為True,就選擇x,condition為False,就選擇y。
(1)使用tf.boolean_mask()獲取元素
# 生成一個-4到4的tensor,變成3行3列
a = tf.reshape(tf.range(-4,5),[3,3])
# 與0比較,返回布爾類型的tensor,返回的shape和原來的shape相同
mask = a>0
# 獲取元素對應位置是True的元素
tf.boolean_mask(a,mask)
mask = a>0,是指mask將tensor中元素大于0的元素返回True,否則返回False,返回值的shape和原tensor的shape一致。
使用tf.boolean_mask(),mask是指定位置的布爾索引,變量a和mask相互對應,函數返回mask中索引為True所對應變量a中的值。
(2)使用tf.where()記錄元素坐標
a = tf.reshape(tf.range(-4,5),[3,3])
# 使用where函數結合mask標記,返回所有為True元素的坐標,獲取對應元素
mask = a>0
# 返回所有指定mask的坐標
indices = tf.where(mask)
# 通過indices指定的坐標來獲取所要的值
tf.gather_nd(a,indices)
indices存放的是所有mask為True的坐標,使用tf.gather_nd()方法通過坐標來獲取tensor中的值。
(3)當where()中有兩個tensor時
# 兩個相同shape的tensor
a = tf.fill([3,3],4)
b = tf.fill([3,3],7)
# 獲取布爾索引,已經定義好了,如下圖
mask
# 根據布爾索引篩選a和b中的值
tf.where(mask,a,b)
mask中第一個值時False,返回值變量b中的第一個元素,mask中的值是True,對應位置就返回變量a中的元素
? ??
?
?
總結
以上是生活随笔為你收集整理的【TensorFlow2.0】(7) 张量排序、填充、复制、限幅、坐标选择的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【TensorFlow2.0】(6) 数
- 下一篇: 【神经网络】(1) 简单网络,实例:气温