Tensorflow的基礎知識(二)

1. 張量的索引與切片操作

通過索引與切片操作可以提取張量的部分數(shù)據(jù),它們的使用頻率非常高集惋。

1.1 索引操作

在Tensorflow中,支持基本的[i][j]···標準索引方式踩娘,也支持通過逗號分隔索引號的索引方式刮刑。例如:

x = tf.random.normal([4,32,32,3])
x[0]#取第一張圖片的數(shù)據(jù)
x[0][1]#取第一張圖片的第二行
x[0][1][2]#取第一張圖片,第二行养渴,第三列的數(shù)據(jù)
x[2][1][0][1]#取第三張圖片雷绢,第二行,第一列理卑,B通道顏色強度值

當張量的維度數(shù)較高時翘紊,使用[i][j]...[k]的方式書寫不方便,可以采用[i,j...k]的方式索引藐唠,它們是等價的帆疟。

x[1,9,2]#取第二張圖片孵滞,第十行,第三列的數(shù)據(jù)

1.2 切片操作

通過start:end:step切片方式可以方便地提取一段數(shù)據(jù)鸯匹,其中start為開始讀取位置的索引坊饶,end 為結(jié)束讀取位置的索引(不包含end 位),step為采樣步長殴蓬。
以下為切片操作的示例:

x[1:3]#讀取第2,3張圖片

start: end: step切片方式有很多簡寫方式匿级,其中start、end染厅、step 3個參數(shù)可以根據(jù)需要選擇性地省略痘绎,全部省略時即為::,表示從最開始讀取到最末尾肖粮,步長為1孤页,即不跳過任何元素。如x[0,::]表示讀取第1張圖片的所有行涩馆,其中::表示在行維度上讀取所有行行施,它等價于x[0]的寫法:

x[0,::]#讀取第一張圖片

為了更加簡潔,::可以簡寫為單個冒號:魂那,例如:

x[:,0:28:2,0:28:2,:]#表示讀取所有圖片蛾号,隔行采樣,隔列采樣涯雅,讀取所有通道數(shù)據(jù)

總結(jié)一下start: end: step切片的簡寫方式鲜结,其中從第一個元素讀取時start可以省略,即start=0 是可以省略的活逆。取到最后一個元素時end 可以省略精刷,步長為1 時step 可以省略。

特別地蔗候,step可以為負數(shù)怒允,考慮最特殊的一種例子,當step = -1時琴庵,start: end: -1表示從start開始误算,逆序讀取至end 結(jié)束(不包含end)仰美,索引號 end <= start迷殿。考慮一個0~9的簡單序列向量咖杂,逆序取到第1 號元素庆寺,不包含第1 號:

x = tf.range(9) #創(chuàng)建0~9向量
x[8:0:-1]# 從8取到0,逆序,不含0
x[::-1]#逆序取全部元素
x[::-2]#逆序間隔取樣
x = tf.random.normal([4,32,32,3])
x[0,::-2,::-2,:]#取第一張圖片的所有通道诉字,行按逆序隔行取樣懦尝,列按逆序隔行取樣

當采樣的維度數(shù)較多時知纷,不需要采樣的維度一般用單冒號: 表示采樣所有元素,此時有可能出現(xiàn)大量的:冒號陵霉,例如:

x = tf.random.normal([4,32,32,3])
x[:,:,:,1]#只需要采樣G通道上的數(shù)據(jù)

為了避免出現(xiàn)像[:,:,:,1]這樣過多冒號的情況琅轧,可以使用···表示多個維度上所有的數(shù)據(jù),其中維度的數(shù)量需根據(jù)規(guī)則自動推斷:當切片方式出現(xiàn)···符號時踊挠,···符號左邊的維度將自動對齊到最左邊乍桂,···符號右邊的維度將自動對齊到最右邊,而系統(tǒng)將自動推斷···符號代表的維度數(shù)量效床。下面是一些示例:

x = tf.random.normal([4,32,32,3])
x[0:2,...,1:]#取第1,2張圖片的G/B通道數(shù)據(jù)
x[2:,...]#讀取最后2張圖片
x[...,:2]#讀取 R/G 通道數(shù)據(jù)

小結(jié):
張量的索引與切片方式多種多樣睹酌,尤其是切片操作,剛開始學習時很容易犯迷糊剩檀。但本質(zhì)上切片操作只有start: end: step這一種基本形式憋沿,通過這種基本形式有目的地省略掉默認參數(shù),從而衍生出多種簡寫方法沪猴,這也是很好理解的辐啄。另外,由于深度學習一般處理的維度在4維以下运嗜,···操作符完全可以用: 符號代替则披,因此理解了這些就會發(fā)現(xiàn)張量切片操作并不復雜。

2. 張量的維度變換操作

在神經(jīng)網(wǎng)絡運算過程中洗出,維度變換是最核心的張量操作士复,通過維度變換可以將數(shù)據(jù)任意地切換形式,滿足不同場合的運算需求翩活。

基本的維度變換操作函數(shù)包括:

  • reshape():改變視圖函數(shù)
  • expand_dims():插入新維度
  • squeeze():刪除維度
  • transpose():交換維度
  • tile():復制數(shù)據(jù)

2.1 reshape操作

在TensorFlow中阱洪,可以通過張量的 ndim 和 shape 成員屬性獲得張量的維度數(shù)和形狀。

x = tf.random.normal([4,32,32,3])
print(x.ndim,x.shape)
4 (4, 32, 32, 3)

通過tf.reshape(x, new_shape)菠镇,可以將張量的視圖任意地合法改變冗荸。例如:

x = tf.range(96)
tf.reshape(x,[2,-1])
<tf.Tensor: shape=(2, 48), 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,
        80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]],
      dtype=int32)>

其中的參數(shù)-1表示當前軸上長度需要根據(jù)張量總元素不變的法則自動推導,從而方便用戶書寫利耍。

tf.reshape(x,[2,4,12])#改變張量數(shù)據(jù)的視圖
tf.reshape(x,[2,-1,3])#再次改變張量數(shù)據(jù)的視圖

2.2 張量增蚌本、刪維度

增加一個長度為1的維度相當于給原有的數(shù)據(jù)添加一個新維度的概念,維度長度為1隘梨,故數(shù)據(jù)并不需要改變程癌,僅僅是改變數(shù)據(jù)的理解方式,因此可以理解為改變視圖的一種特殊方式轴猎。
下面是示例:

x = tf.random.uniform([2,2],maxval=10,dtype=tf.int32)
x = tf.expand_dims(x,axis=2)
print(x)
tf.Tensor(
[[[3]
  [5]]

 [[6]
  [2]]], shape=(2, 2, 1), dtype=int32)

通過 tf.expand_dims(x,axis) 可在指定的 axis 軸前插入一個新的維度嵌莉。

同樣的方法,我們可以在最前面插入一個維度捻脖。

x = tf.expand_dims(x, axis=0)
print(x)
tf.Tensor(
[[[[6]
   [9]]

  [[1]
   [1]]]], shape=(1, 2, 2, 1), dtype=int32)

需要注意的是锐峭,tf.expand_dims 的 axis 為正時中鼠,表示在當前維度之前插入一個新維度;為負時沿癞,表示當前維度之后插入一個新的維度援雇。

通過 tf.squeeze(x, axis)函數(shù)可以刪除張量的維度,axis 參數(shù)為待刪除的維度的索引號椎扬。下面看一下用法:

x = tf.random.normal([1,32,32,1])
print('brfore: ',x.shape)
x = tf.squeeze(x,axis=0)#刪除圖片數(shù)量維度
print('after: ',x.shape)
brfore:  (1, 32, 32, 1)
after:  (32, 32, 1)

#繼續(xù)刪除通道數(shù)維度
x = tf.squeeze(x, axis=2)
print(x.shape)
(32, 32)

提示:如果不指定維度參數(shù) axis熊杨,即 tf.squeeze(x),那么它會默認刪除所有長度為1的維度盗舰。

x = tf.random.normal([1,28,28,1])
print('before:', x.shape)
x = tf.squeeze(x)
print('after:',x.shape)
before: (1, 28, 28, 1)
after: (28, 28)

建議使用tf.squeeze()時逐一指定需要刪除的維度參數(shù)晶府,防止Tensorflow意外刪除某些長度為1的維度。

2.3 交換維度操作

通過交換維度操作钻趋,改變了張量的存儲順序川陆,同時也改變了張量的視圖。
通過使用 tf.transpose(x, perm) 函數(shù)完成維度交換操作蛮位,其中perm參數(shù)表示新維度的順序List较沪。
下面看操作示例:

x = tf.random.normal([4,32,32,3])
x = tf.transpose(x, [0,3,1,2])#把圖片的通道維度移動到圖片數(shù)量維度后
print(x.shape)
(4, 3, 32, 32)

注意:通過 tf.transpose 完成維度交換后,張量的存儲順序已經(jīng)改變失仁,視圖也隨之改變尸曼,后續(xù)的所有操作必須基于新的存儲順序和視圖進行。

2.4 復制數(shù)據(jù)操作

通過 tf.tile(x, multiples) 函數(shù)完成數(shù)據(jù)在指定維度上的復制操作萄焦,multiples參數(shù)分別指定了每個維度上面的復制倍數(shù)控轿,對應位置為1表明不復制,為2表明新長度為原來長度的2倍拂封,即數(shù)據(jù)復制一份茬射,經(jīng)此類推。
下面看操作示例:

b = tf.constant([1,2])
b = tf.expand_dims(b, axis=0)#插入一個新的維度
print(b.shape)
(1, 2)

#在 Batch 維度上復制數(shù)據(jù)1份冒签,實現(xiàn)如下:
b = tf.tile(b, multiples=[2,1])
print(b.shape)
(2, 2)

再看另一個例子:

x = tf.range(4)
x = tf.reshape(x,[2,2])
print(x.shape)
(2, 2)

# 然后在列維度上復制1份數(shù)據(jù)
x = tf.tile(x,multiples=[1,2])#在列維度復制數(shù)據(jù)
print(x.shape)
(2, 4)

# 然后在行維度復制1份數(shù)據(jù)
x = tf.tile(x, multiples=[2,1])#在行維度復制數(shù)據(jù)
print(x.shape)
(4, 4)

注意:tf.tile 會創(chuàng)建一個新的張量來保存復制后的數(shù)據(jù)在抛,由于復制操作涉及大量數(shù)據(jù)的讀寫IO操作,計算代價相對較高萧恕。然而神經(jīng)網(wǎng)絡中不同shape之間的張量運算操作十分頻繁刚梭,那么有沒有輕量級的復制操作呢?這就要看接下來的Broadcasting操作了票唆。

3. Broadcasting操作

Broadcasting稱為廣播機制(或自動擴展機制)朴读,它是一種輕量級的張量復制操作,它在邏輯上擴展張量數(shù)據(jù)的形狀惰说,但是只會在需要時才會執(zhí)行實際存儲復制操作磨德。對于大部分場景缘回,Broadcasting機制都能通過優(yōu)化手段避免實際復制數(shù)據(jù)而完成邏輯運算吆视,從面相對于 tf.tile 函數(shù)典挑,減少了計算代價。
下面看使用示例:

a = tf.random.normal([2,32,32,1])
b = tf.random.normal([32,32])

# 張量相加
c = a+b
print(c.shape)
(2, 32, 32, 32)

# 張量相減
c = a-b
print(c.shape)
(2, 32, 32, 32)

# 張量相乘
c = a*b
print(c.shape)
(2, 32, 32, 32)

# 張量相除
c = a/b
print(c.shape)
(2, 32, 32, 32)

可以看到啦吧,上面這些運算都能Broadcasting成[2,32,32,32]的公共shape您觉,再進行運算。

4. 數(shù)學運算

4.1 加授滓、減琳水、乘、除運算

加般堆、減在孝、乘、除是最基本的數(shù)學運算淮摔,分別通過tf.add私沮、tf.subtract、tf.multiply和橙、tf.divide函數(shù)實現(xiàn)仔燕,Tensorflow已經(jīng)重載了+、-魔招、*晰搀、/運算符,可以直接使用運算符來進行運算办斑。
整除和余除也是常見的運算之一外恕,分別使用//和%運算符實現(xiàn)。
下面看使用示例:

a = tf.range(5)
b = tf.constant(2)

a//b#整除運算
<tf.Tensor: shape=(5,), dtype=int32, numpy=array([0, 0, 1, 1, 2], dtype=int32)>

a%b#余除運算
<tf.Tensor: shape=(5,), dtype=int32, numpy=array([0, 1, 0, 1, 0], dtype=int32)>

4.2 乘方運算

通過 tf.pow(x,a) 可以方便的完成乘方運算乡翅,也可以通過運算符實現(xiàn)xa運算吁讨。示例如下:

x = tf.range(4)
tf.pow(x,3)
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([ 0,  1,  8, 27], dtype=int32)>

x**2
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([0, 1, 4, 9], dtype=int32)>

x = tf.constant([1,4,9,16])
x = tf.cast(x, dtype=tf.float32)#求平方根
x**0.5
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([1., 2., 3., 4.], dtype=float32)>

對于常見的求平方、求平方根運算峦朗,可以使用 tf.square(x) 和 tf.sqrt(x)實現(xiàn)建丧。
示例如下:

x = tf.range(5)
x = tf.cast(x, dtype=tf.float32)
x = tf.square(x)#求平方
print(x)
tf.Tensor([ 0.  1.  4.  9. 16.], shape=(5,), dtype=float32)

x = tf.sqrt(x)# 求平方根
print(x)
tf.Tensor([0. 1. 2. 3. 4.], shape=(5,), dtype=float32)

4.3 指數(shù)和對數(shù)運算

通過tf.pow(a,x)或者**運算符也可以方便的實現(xiàn)指數(shù)運算。
對于自然指數(shù)e??波势,可以通過 tf.exp(x)實現(xiàn)翎朱。
示例如下:

x = tf.constant([1,2,3])
2**x #指數(shù)運算
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 4, 8], dtype=int32)>

tf.exp(1.0)
<tf.Tensor: shape=(), dtype=float32, numpy=2.7182817>

在 TensorFlow 中,自然對數(shù)可以通過 tf.math.log(x)實現(xiàn)尺铣。

x = tf.exp(3.)
tf.math.log(x)
<tf.Tensor: shape=(), dtype=float32, numpy=3.0>

Tensorflow還沒有推出任意底數(shù)的log函數(shù)拴曲,但我們可以換一種方法實現(xiàn)它,示例如下:

x = tf.constant([1.,2.])
x = 10 ** x
print(x)
tf.Tensor([ 10. 100.], shape=(2,), dtype=float32)

tf.math.log(x) / tf.math.log(10.)#計算以10為底數(shù)的對數(shù)
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1., 2.], dtype=float32)>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凛忿,一起剝皮案震驚了整個濱河市澈灼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖叁熔,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件委乌,死亡現(xiàn)場離奇詭異,居然都是意外死亡荣回,警方通過查閱死者的電腦和手機遭贸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來心软,“玉大人壕吹,你說我怎么就攤上這事∩玖澹” “怎么了耳贬?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猎唁。 經(jīng)常有香客問我效拭,道長,這世上最難降的妖魔是什么胖秒? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任缎患,我火速辦了婚禮,結(jié)果婚禮上阎肝,老公的妹妹穿的比我還像新娘挤渔。我一直安慰自己,他們只是感情好风题,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布判导。 她就那樣靜靜地躺著,像睡著了一般沛硅。 火紅的嫁衣襯著肌膚如雪眼刃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天摇肌,我揣著相機與錄音擂红,去河邊找鬼。 笑死围小,一個胖子當著我的面吹牛昵骤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肯适,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼变秦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了框舔?” 一聲冷哼從身側(cè)響起蹦玫,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赎婚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后樱溉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挣输,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年饺窿,在試婚紗的時候發(fā)現(xiàn)自己被綠了歧焦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片移斩。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡肚医,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出向瓷,到底是詐尸還是另有隱情肠套,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布猖任,位于F島的核電站你稚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏朱躺。R本人自食惡果不足惜刁赖,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望长搀。 院中可真熱鬧宇弛,春花似錦、人聲如沸源请。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谁尸。三九已至舅踪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間良蛮,已是汗流浹背抽碌。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留决瞳,地道東北人咬展。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像瞒斩,于是被迫代替她去往敵國和親破婆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355