深度学习(14)TensorFlow高阶操作三: 张量排序
深度學習(14)TensorFlow高階操作三: 張量排序
- 一. Sort, argsort
- 1. 一維Tensor
- 2. 多維Tensor
- 二. Top_k
- 三. Top-k accuracy(Top-k應用)
- 1. 問題描述
- 2. 問題解決
- 3. 代碼
Outline
- Sort/argsort(排序/在序列中的位置)
- Topk(前k個排序結果)
- Top-5 Acc.(Topk應用)
一. Sort, argsort
1. 一維Tensor
(1) a = tf.random.shuffle(tf.range(5)): 創建一個[0~5]的Tensor,再將其隨機打亂,打亂后a=[2, 0, 3, 4, 1];
(2) tf.sort(a, direction=‘DESCENDING’): 將a按降序排列,即按照由大到小進行排列,排列完為[4, 3, 2, 1, 0];
注: 升序就是ASCENDING
(3) tf.argsort(a, direction=‘DESCENDING’): 將a按照降序排列,然后得到每個元素在原來a中的位置。例如,4在原來a中的位置是3,那么argsort中的第1個元素就是3; 3在原來a中的位置是2,那么argsort中的第2個元素就是2; 2在原來a中的位置是0,那么argsort中的第3個元素就是0; 1在原來a中的位置是4,那么argsort中的第4個元素就是4; 0在原來a中的位置是1,那么argsort中的第5個元素就是1; 所以得到argsort=[3, 2, 0, 4, 1];
(4) tf.gather(a, idx): 將a按照idx中的索引來排序,得到[4, 3, 2, 1, 0];
2. 多維Tensor
(1) tf.sort(a): 將a升序排列。不指定direction就是默認升序排列;
(2) tf.dort(a, direction=‘DESCENDING’): 將a降序排列;
(3) idx = tf.argsort(a): 將a的升序排列進行索引排列;
二. Top_k
- Only return top-k values and indices
這個方法只能返回tok-k的值和索引。
(1) res = tf.math.top_k(a, 2): 將a中每行按照top2排列;
(2) res.indices: 返回res的索引順序;
(3) rea.values: 返回res的值的順序;
三. Top-k accuracy(Top-k應用)
1. 問題描述
- Prob: [0.1, 0.2, 0.3, 0.4]
表示數字識別中一個數字為“0”的概率為0.1,為“1”的概率為0.2,為“2”的概率為0.3,為“3”的概率為0.4; - Label:[2]
表示這個數字的標簽值(label)為2; - Only consider top-1 prediction: [3]
如果我們只考慮1個最有可能的預測值,就是這個數字為“3”,那么顯然與標簽值“2”對不上號,那么就會導致正確率為0%; - Only consider top-2 prediction: [3, 2]
如果我們考慮2個最有可能的預測值,使用top-2排列為[3, 2],這時準確率就為100%(只要top-2中出現預測值與標簽值相同的情況,準確率就記為1); - Only consider top-3 prediction: [3, 2, 1]
如果我們考慮3個最有可能的預測值,使用top-3排列為[3, 2, 1],這時準確率就為100%;
2. 問題解決
(1) target = tf.constant([2, 0]): 表示標簽(label)值,即第1個樣本的真實值為“2”, 第2個樣本的真實值為“0”;
(2) k_b = tf.math.top_k(prob, 3).indices: 表示將prob中的數據按照top-3排列并給出索引,這個結果也相當于這兩個樣本每個樣本是什么數字的可能性,即第1個樣本最有可能是“2”,次有可能是“1”,再次有可能是“0”; 第2個樣本最有可能是“1”,次有可能是“0”,再次有可能是“2”;
(3) k_b = tf.transpose(k_b, [1, 0]): 將k_b做轉置操作,即將維度由[0, 1]變為[1, 0],這樣的話,第1行就對應這兩個樣本最有可能(即top1)的預測值,第2行就對應這兩個樣本次有可能(即top2)的預測值;
(4) target = tf.broadcast_to(target, [3, 2]): 使用Broadcasting方法將target的維度由[2]擴展為[3, 2]([2] →\to→ [1, 2] →\to→ [3, 2]);
接下來我們需要將預測值與標簽值進行比較操作,例如: 使用top1的預測值比較,即使用[2, 1]和[2, 0]進行比較,結果為[True, False],那么其準確率就為50%,因為只有1個數字識別正確; 使用top2的預測值比較,即使用[[2, 1], [1, 0]]和[[2, 0], [2, 0]]進行比較,那么我們只需要保證top2的每個數字的預測值有1個與標簽值相等即可,結果為[True, True],那么其準確率就為100%; 使用top3的預測值比較,即使用[[2, 1], [1, 0], [0, 2]]和[[2, 0], [2, 0], [2, 0]]進行比較,那么我們只需要保證top3的每個數字的預測值有1個與標簽值相等即可,結果為[True, True, True],那么其準確率還是100%;
(5) def accuracy(output, target, topk=(1,)): 定義accuracy方法,其中output.shape=[2, 3],即共有2個樣本,每個樣本有3種分類; target.shape=[2],即target為這2個樣本的標簽值(label); topk=(1,)表示取值top1;
(6) maxk = max(topk): 表示取最大的top值,例如topk=(1,),那么maxk就取1,也就意味著在后邊的操作中我們使用top1計算accuracy; topk=(1, 2),那么maxk就取2,也就意味著在后邊的操作中我們使用top2計算accuracy; topk=(1, 2, 3),那么maxk就取3,也就意味著在后邊的操作中我們使用top3計算accuracy;
(7) batch_size = target.shape[0]: target.shape=[2],所以batch_size=2;
(8) pred = tf.math.topk(output, maxk).indicies: 將每個樣本預測值按照topk的索引進行排列,例如,如果按照top1排列,那么tf.math.topk(output, 1).indicies就為:
| b0b_0b0? | 2 |
| b1b_1b1? | 1 |
也就是:
[21]\begin{bmatrix}2\\1\end{bmatrix}[21?]
如果按照top2排列,那么tf.math.topk(output, 2).indicies就為:
| b0b_0b0? | 2 | 1 |
| b1b_1b1? | 1 | 0 |
也就是:
[2110]\begin{bmatrix}2&1\\1&0\end{bmatrix}[21?10?]
如果按照top1排列,那么tf.math.topk(output, 3).indicies就為:
| b0b_0b0? | 2 | 1 | 0 |
| b1b_1b1? | 1 | 0 | 2 |
也就是:
[210102]\begin{bmatrix}2&1&0\\1&0&2\end{bmatrix}[21?10?02?]
(9) pred = tf.transpose(pred, perm=[1, 0]): 將pred進行轉置操作,也就是將pred的維度順序索引由[0, 1]變為[1, 0],即:
如果按照top1排列,那么pred就為:
[21]\begin{bmatrix}2&1\end{bmatrix}[2?1?]
如果按照top2排列,那么pred就為:
[2110]\begin{bmatrix}2&1\\1&0\end{bmatrix}[21?10?]
如果按照top3排列,那么pred就為:
[211002]\begin{bmatrix}2&1\\1&0\\0&2\end{bmatrix}???210?102????
(10) target_ = tf.broadcast_to(target, pred.shape)
將target進行Broadcasting操作,使target.shape=pred.shape,即:
如果按照top1排列,那么target_就為:
[20]→[20]\begin{bmatrix}2&0\end{bmatrix}\to\begin{bmatrix}2&0\end{bmatrix}[2?0?]→[2?0?]
如果按照top2排列,那么target_就為:
[20]→[2020]\begin{bmatrix}2&0\end{bmatrix}\to\begin{bmatrix}2&0\\2&0\end{bmatrix}[2?0?]→[22?00?]
如果按照top3排列,那么target_就為:
[20]→[202020]\begin{bmatrix}2&0\end{bmatrix}\to\begin{bmatrix}2&0\\2&0\\2&0\end{bmatrix}[2?0?]→???222?000????
(11) correct = tf.equal(pred, target_): 將pred與target_做比較操作,即:
如果按照top1排列,那么correct就為:
[TrueFalse]\begin{bmatrix}True&False\end{bmatrix}[True?False?]
如果按照top2排列,那么pred就為:
[TrueFalseFalseTrue]\begin{bmatrix}True&False\\False&True\end{bmatrix}[TrueFalse?FalseTrue?]
如果按照top3排列,那么pred就為:
[TrueFalseFalseTrueFalseFalse]\begin{bmatrix}True&False\\False&True\\False&False\end{bmatrix}???TrueFalseFalse?FalseTrueFalse????
(12) res[]: 新建res列表,用于存放準確率結果;
(13) correct_k = tf.cast(tf.reshape(correct[:k], [-1]), dtype=tf.float32):
其中correct[:k]表示correct的前k-1行;
tf.reshape(correct[:k], [-1])表示將correct的前k-1行進行reshape操作,即: 如果按照top1排列,那么correct[:k].shape就由[1, 2]變為[1]; 如果按照top2排列,那么correct[:k].shape就由[2, 2]變為[2]; 如果按照top3排列,那么correct[:k].shape就由[3, 2]變為[3];
tf.cast(tf.reshape(correct[:k], [-1]), dtype=tf.float32)表示將reshape后的correct里的數據類型變為tf.float32,即將True變為1,False變為0;
(14) correct_k = tf.reduce_sum(correct_k): 將correct_k中的每行數據求和,即:
如果按照top1排列,那么correct_k=1+0=1correct\_k=1+0=1correct_k=1+0=1;
如果按照top2排列,那么correct_k=1+0+0+1=2correct\_k=1+0+0+1=2correct_k=1+0+0+1=2;
如果按照top3排列,那么correct_k=1+0+0+1+0+0=2correct\_k=1+0+0+1+0+0=2correct_k=1+0+0+1+0+0=2;
(15) acc = float(correct_k / batch_size): 計算top_k的準確率;
(16) res.append(acc): 將準確率acc放入到結果res中;
3. 代碼
import tensorflow as tf import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' tf.random.set_seed(2467)def accuracy(output, target, topk=(1,)):maxk = max(topk)batch_size = target.shape[0]pred = tf.math.top_k(output, maxk).indicespred = tf.transpose(pred, perm=[1, 0])target_ = tf.broadcast_to(target, pred.shape)# [10, b]correct = tf.equal(pred, target_)res = []for k in topk:correct_k = tf.cast(tf.reshape(correct[:k], [-1]), dtype=tf.float32)correct_k = tf.reduce_sum(correct_k)acc = float(correct_k* (100.0 / batch_size) )res.append(acc)return resoutput = tf.random.normal([10, 6]) output = tf.math.softmax(output, axis=1) target = tf.random.uniform([10], maxval=6, dtype=tf.int32) print('prob:', output.numpy()) pred = tf.argmax(output, axis=1) print('pred:', pred.numpy()) print('label:', target.numpy())acc = accuracy(output, target, topk=(1,2,3,4,5,6)) print('top-1-6 acc:', acc)運行結果如下:
可以看到,隨著top-k的增加,準確率不斷提升,在數字識別種類有6種(即0~5)的情況下,如果我們計算top-6的話,準確率是一定會達到100%的。
參考文獻:
[1] 龍良曲:《深度學習與TensorFlow2入門實戰》
總結
以上是生活随笔為你收集整理的深度学习(14)TensorFlow高阶操作三: 张量排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奇瑞小蚂蚁 2023 款配置公布:三种续
- 下一篇: 深度学习(15)TensorFlow高阶