2017年8月19日星期六整理第五章部分
此處給出本節(jié)的代碼:https://github.com/Leechen2014/TensorFlow-for-Machine-Intelligence
相關(guān)的文件描述在github中給出。
PS:翻譯來(lái)源:
http://shop.oreilly.com/product/9781939902351.do
Convolution
顧名思義,卷積運(yùn)算是卷積神經(jīng)網(wǎng)絡(luò)中重要的組成部分俭识。CNN能夠精確的匹配多種模式的能力可以歸因于卷積計(jì)算拱燃。正如上一節(jié)所示谍倦,這些操作需要復(fù)雜的輸入内颗。在本節(jié)中泳猬,我們將實(shí)驗(yàn)卷積運(yùn)算和調(diào)節(jié)他的可用參數(shù)。現(xiàn)在要將兩個(gè)輸入的張量(輸入和卷積核)卷積為一個(gè)輸出張量晋被,該輸出張量代表每一個(gè)輸入的信息。
Input and Kernel (輸入和卷積核)
在通常情況下Tensorflow中的卷積操作是使用tf.nn.conv2d刚盈。還有其他的用例是使用TensorFlow設(shè)計(jì)的特殊卷積操作羡洛。tf.nn.conv2d是開(kāi)始進(jìn)行實(shí)驗(yàn)的首選卷積運(yùn)算。例如扁掸,我們將兩個(gè)張量卷積在一起并檢查結(jié)果翘县。
input_batch=tf.constant([
[# First Input[[0.0], [1.0]],
[[2.0], [3.0]]
],
[# Second Input[[2.0], [4.0]],
[[6.0], [8.0]]
]
])
kernel=tf.constant([
[
[[1.0,2.0]]
]
])
上述代碼創(chuàng)建了兩個(gè)張量最域。Input_batch張量的形狀和上一節(jié)見(jiàn)過(guò)的image_batch張量的形狀類(lèi)似。第一個(gè)張量將會(huì)是被卷積的锈麸,第二個(gè)張量是作為卷積核的镀脂。卷積核(Kernel)是一個(gè)很重要的術(shù)語(yǔ),其可以與權(quán)重(weights)忘伞、濾波器(filter)薄翅、卷積矩陣(convolution matrix)、掩碼(filter)互換氓奈。由于這個(gè)任務(wù)和計(jì)算機(jī)視覺(jué)相關(guān)翘魄,所以使用術(shù)語(yǔ)內(nèi)核是對(duì)的,因?yàn)檫@種東西在計(jì)算機(jī)視覺(jué)中被稱(chēng)為圖像內(nèi)核舀奶。當(dāng)用tensorflow描述功能的時(shí)候暑竟,術(shù)語(yǔ)之間沒(méi)有實(shí)際的差別。
我們?cè)谏厦娴睦又袆?chuàng)建了兩個(gè)張量(tensor).張量Input_batch的形狀和上一節(jié)中見(jiàn)到的image_batch的形狀很像育勺。這第一個(gè)張量將會(huì)是是被卷積的但荤,第二個(gè)tensor將會(huì)是卷積核。Kernel是一個(gè)很重要的術(shù)語(yǔ)涧至,有的時(shí)候會(huì)被稱(chēng)為權(quán)重(weights),過(guò)濾器(filter)腹躁,卷積矩陣(convolution matrix)或者是膜(mask)。由于這個(gè)任務(wù)(task)與計(jì)算機(jī)視覺(jué)相關(guān)南蓬,常常被看做image kernel纺非,所以使用kernel這個(gè)術(shù)語(yǔ)有一定意義。在Tensorflow中描述這個(gè)函數(shù)的時(shí)候赘方,沒(méi)有本質(zhì)上的區(qū)別烧颖。在Tensorflow中的參數(shù)被稱(chēng)為filter,它是一個(gè)從訓(xùn)練中學(xué)習(xí)到的一組權(quán)重(weights)的集合。(PS:嘿嘿蒜焊,這個(gè)時(shí)候看看filter., weights )倒信。
kernel ( filter parameter)中包含的大量不同的權(quán)重將會(huì)在學(xué)習(xí)過(guò)程中被修改。
在示例代碼中泳梆,有一個(gè)內(nèi)核是kernel變量的第一個(gè)維度鳖悠。kernel被構(gòu)建后返回一個(gè)張量,其將包括第一個(gè)通道與原始輸入和原始輸入第二個(gè)通道加倍(2)优妙。在本文中乘综,通道(channel)用于描述秩(rank)為1的張量(也就是向量)中的元素。通道是計(jì)算機(jī)視覺(jué)中描述輸出向量的術(shù)語(yǔ)套硼,例如RGB圖像具有三個(gè)通道卡辰,表示為rank為1的張量[紅,綠,藍(lán)]【怕瑁現(xiàn)在反砌,想不講stride和padding參數(shù),這兩個(gè)參數(shù)將在以后的section中介紹萌朱,隨后也會(huì)集中關(guān)注卷積(tf.nn.conv2d)輸出宴树。
conv2d = tf.nn.conv2d(input_batch, kernel, strides=[1, 1,1, 1], padding='SAME')
sess.run(conv2d)
示例執(zhí)行后輸出的結(jié)果是:
array([[[[ 0., 0.],
[ 1., 2.]],
[[ 2., 4.],
[ 3., 6.]]],
[[[ 2., 4.],
[ 4., 8.]],
[[ 6., 12.],
[ 8., 16.]]]], dtype=float32)
輸出的也是一個(gè)tensor,它的rank和input_batch一樣,而且維度的數(shù)量也可以在kernel里面發(fā)現(xiàn).想象一下,如果input_batch代表一個(gè)只有一個(gè)通道的圖像,也就是灰度級(jí)圖像. Tensor中的每個(gè)元素代表圖像上的每個(gè)像素點(diǎn).那么,圖像右下角的像素值將為3.0。
將卷積操作tf.nn.conv2d看作為圖像(用input_batch表示)和張量kernel的結(jié)合操作.這兩個(gè)tensor的卷積會(huì)產(chǎn)生一個(gè)特征圖(a feature map).特征圖是一個(gè)廣泛的術(shù)語(yǔ)晶疼,不僅僅只在計(jì)算機(jī)視覺(jué)中出現(xiàn)酒贬,它涉及與圖像內(nèi)核一起使用的操作的輸出。當(dāng)向output添加新圖層的時(shí)候,特征圖代表了這些張量的卷積.
輸入圖像和特征圖輸出之間的關(guān)系可以從代碼中深入探索.我們可以使用相同的索引翠霍,在輸入批次和特征圖中訪(fǎng)問(wèn)元素锭吨。當(dāng)訪(fǎng)問(wèn)同一個(gè)像素下的輸入和特征的時(shí)候,可以顯示出當(dāng)輸入和kernel卷積后的變化.在下面的示例中,可以發(fā)現(xiàn)圖像中右下角的像素被改變,并可以通過(guò)乘法的方式找到改變后的值: 3.0*1.0和3.0*2.0 .相應(yīng)的像素值以及對(duì)應(yīng)的kernel的值可以用以下方式找到:
lower_right_image_pixel = sess.run(input_batch)[0][1][1]
lower_right_kernel_pixel = sess.run(conv2d)[0][1][1]
lower_right_image_pixel, lower_right_kernel_pixel
上述代碼執(zhí)行后,會(huì)輸出:
(array([ 3.], dtype=float32), array([ 3., 6.],dtype=float32))
在這個(gè)簡(jiǎn)單的示例中,圖像中的每個(gè)像素和卷積核中的對(duì)象值相乘,并添加到相應(yīng)的特征圖層(layer)中.在上下文中, Layer(層)指的是輸出的新維度.在這個(gè)例子中很難看到卷積運(yùn)算過(guò)程中的值。
Strides(步長(zhǎng))
卷積在計(jì)算機(jī)視覺(jué)中的價(jià)值在于它能夠降低輸入維度寒匙,在本案中輸入指的是圖像零如。一個(gè)圖像(2D圖像)的維度是它的寬,高和通道數(shù)蒋情。對(duì)于神經(jīng)網(wǎng)絡(luò)來(lái)說(shuō)埠况,掃描一個(gè)龐大的圖像維度并判斷哪些像素重要,這需要消耗大量的時(shí)間棵癣。使用卷積降低圖像的維數(shù)是通過(guò)改變內(nèi)核的strides(步長(zhǎng))來(lái)完成的。
參數(shù)strides可以使得卷積核跳過(guò)圖像中的像素并在輸出的中不包含這些像素夺衍。說(shuō)哪些像素被跳過(guò)是不公平的狈谊,因?yàn)檫@些像素仍然可能會(huì)影響輸出。當(dāng)使用較大的圖像和更復(fù)雜的內(nèi)核時(shí)沟沙,strides參數(shù)會(huì)突出顯示如何與內(nèi)核一起使用卷積操作河劝。由于卷積是將內(nèi)核滑過(guò)輸入,可以使用strides來(lái)設(shè)置如何在input上行走(walk). strides參數(shù)可以配置卷積以跳過(guò)某些元素矛紫,而不是遍歷輸入的每個(gè)元素赎瞎。
PS:作者對(duì)這個(gè)卷積核的操作描述為walk實(shí)在是很形象,
例如颊咬,采取較大圖像和較大內(nèi)核的卷積务甥。在這種情況下,它是6像素高喳篇,6像素寬和1通道深圖像(6x6x1)和(3x3x1)內(nèi)核之間的卷積敞临。
input_batch = tf.constant([
[ # First Input (6x6x1)
[[0.0], [1.0], [2.0], [3.0], [4.0], [5.0]],
[[0.1], [1.1], [2.1], [3.1], [4.1], [5.1]],
[[0.2], [1.2], [2.2], [3.2], [4.2], [5.2]],
[[0.3], [1.3], [2.3], [3.3], [4.3], [5.3]],
[[0.4], [1.4], [2.4], [3.4], [4.4], [5.4]],
[[0.5], [1.5], [2.5], [3.5], [4.5], [5.5]],
],
])
kernel = tf.constant([ # Kernel (3x3x1)
[[[0.0]], [[0.5]], [[0.0]]],
[[[0.0]], [[1.0]], [[0.0]]],
[[[0.0]], [[0.5]], [[0.0]]]
])
# NOTE: the change in the size of the strides parameter.
conv2d = tf.nn.conv2d(input_batch, kernel, strides=[1, 3,3, 1], padding='SAME')
sess.run(conv2d)
代碼執(zhí)行后的輸出如下:
array([[[[ 2.20000005],
[ 8.19999981]],
[[ 2.79999995],
[ 8.80000019]]]], dtype=float32)
通過(guò)在input_batch上按照步長(zhǎng)移動(dòng)kernel使得inpout_batch變量與kernel變量結(jié)合.每次kernel移動(dòng)后,他會(huì)在input_batch中得到確定的元素.然后將重疊值相乘并將結(jié)果加在一起。這是一個(gè)卷積如何使用所謂的逐點(diǎn)乘法去組合(combines)的兩個(gè)輸入麸澜。使用下圖可能更直觀挺尿。
Strides是調(diào)節(jié)輸入爭(zhēng)來(lái)那個(gè)維度的一種方式.降低維度需要更少的處理能力蹂匹,并且不會(huì)產(chǎn)生完全重疊的接受場(chǎng)(overlap)。strides參數(shù)遵循與輸入張量相同的格式
[image_batch_size_stride裆操,image_height_stride怒详,image_width_stride,image_channels_stride]踪区。
通常情況下,很少更改stride參數(shù)的第一個(gè)或最后一個(gè)元素昆烁,因?yàn)檫@倆元素會(huì)使得tf.nn.conv2d操作跳過(guò)數(shù)據(jù),并且不再考慮輸入數(shù)據(jù)了. image_height_stride和image_width_stride在減少輸入維數(shù)方面有用.
// ps作者在最后拋出一個(gè)問(wèn)題,并預(yù)示著下一節(jié)的內(nèi)容
跨越輸入的挑戰(zhàn)經(jīng)常是如何處理不均勻地結(jié)束在輸入邊緣的步幅。這通常是由于圖像大小和內(nèi)核大小不匹配缎岗,不均勻的步幅的時(shí)候會(huì)出現(xiàn)的問(wèn)題静尼。如果圖像大小,內(nèi)核大小和步幅都不能改變传泊,則填充(padding)可以添加到圖像中以處理不均勻區(qū)域鼠渺。
5.2.2 Padding
當(dāng)內(nèi)核重疊在圖像上時(shí),應(yīng)將其設(shè)置為適合圖像的邊界眷细。有時(shí)拦盹,尺寸可能不適合,一個(gè)很好的選擇是填補(bǔ)圖像中的缺失區(qū)域溪椎。填充圖像的缺失區(qū)域稱(chēng)為填充圖像普舆。
TensorFlow會(huì)將用零填充圖像,或者當(dāng)尺寸不允許內(nèi)核跨越圖像而不超過(guò)其邊界時(shí)會(huì)引發(fā)錯(cuò)誤校读。tf.nn.conv2d的零的數(shù)量或錯(cuò)誤狀態(tài)具是由兩個(gè)參數(shù)來(lái)控制padding.('VALID'沼侣,'SAME')。
SAME:意味著卷積的輸出和輸入的大小一樣,當(dāng)計(jì)算如何跨越圖像時(shí)歉秫,這不考慮過(guò)濾器尺寸;當(dāng)將所有缺少的值填充為零時(shí)蛾洛,這可能會(huì)跨越存在的圖像的邊界。
VALID:在計(jì)算如何跨越圖像時(shí)要考慮濾鏡尺寸雁芙。這將盡可能將大量的保持內(nèi)核在圖像的范圍內(nèi)轧膘。在某些情況下可能有填充,但會(huì)避免却特。
//PS 作者這是給出了經(jīng)驗(yàn)貼:
最好考慮輸入的大小扶供,但是如果填充是必要的,那么TensorFlow有內(nèi)置的選項(xiàng)裂明。在大多數(shù)簡(jiǎn)單的情況下椿浓,SAME是一個(gè)很好的選擇太援。當(dāng)輸入和內(nèi)核與步幅良好時(shí),優(yōu)先使用VALID扳碍。有關(guān)更多信息提岔,TensorFlow在卷積文檔中很好地介紹了該話(huà)題().
Data Format
Tf.nn.conv2d的另一個(gè)參數(shù)是Data
Format,在以上的例子中并沒(méi)有使用到, tf.nn.conv2d的官方文檔中解釋其是更改數(shù)據(jù)格式,以便input笋敞,kernel和strides遵循迄今為止使用的格式以外的格式碱蒙。如果輸入input tensor不是遵守[bantch_size,
height, width, channel]標(biāo)準(zhǔn)的話(huà),修改數(shù)據(jù)格式還是很有用的.這種情況出現(xiàn)的話(huà),可以不將輸入更改為所匹配的形式,更改data_format參數(shù)以使用不同的布局就行了.
data_format: An optional string from: “NHWC”, “NCHW”.Defaults to “NHWC”. Specify the data format of the input and output data. Withthe default format “NHWC”, the data is stored in the order of: [batch,in_height, in_width, in_channels]. Alternatively, the format could be “NCHW”,the data storage order of: [batch, in_channels, in_height, in_width]
-------------------------------------------by 8月8號(hào)? --------------------------------
Kernels in Depth(卷積核和深度)
在TensorFlow中夯巷,filter參數(shù)用于指定與輸入進(jìn)行卷積的內(nèi)核赛惩。過(guò)濾器通常是攝影中以調(diào)整圖像的屬性,例如允許到達(dá)相機(jī)鏡頭的陽(yáng)光的量趁餐。在攝影中喷兼,過(guò)濾器允許攝影師徹底改變他們拍攝的照片。攝影師能夠使用過(guò)濾器改變照片的原因是因?yàn)檫^(guò)濾器可以識(shí)別進(jìn)入鏡頭的光的某些屬性后雷。例如季惯,紅色透鏡濾光片將吸收(阻擋)不是紅色的每個(gè)頻率的頻率,只允許紅色通過(guò)濾光片臀突。
在計(jì)算機(jī)視覺(jué)中勉抓,內(nèi)核(過(guò)濾器)用于識(shí)別數(shù)字圖像的重要屬性。他們通過(guò)使用某些模式來(lái)突出顯示圖像中存在的特征候学。將復(fù)制紅色濾鏡示例圖像的內(nèi)核通過(guò)對(duì)除紅色以外的所有顏色使用減小值來(lái)實(shí)現(xiàn)藕筋。在這種情況下,紅色將保持不變梳码,但所有其他匹配的顏色都會(huì)減少念逞。
本章開(kāi)始的例子使用了一個(gè)設(shè)計(jì)用于執(zhí)行邊緣檢測(cè)的內(nèi)核。邊緣檢測(cè)內(nèi)核在計(jì)算機(jī)視覺(jué)應(yīng)用中是常見(jiàn)的边翁,并且可以使用基本的TensorFlow操作和單個(gè)tf.nn.conv2d操作來(lái)實(shí)現(xiàn)。
輸出是將一個(gè)圖像和邊緣檢測(cè)核進(jìn)行卷積產(chǎn)生的,可以看出是檢測(cè)到邊緣的所有區(qū)域硕盹。
代碼中假定一批已經(jīng)從磁盤(pán)中加載的真實(shí)圖像是可用的(這批圖像是image_batch)在本示例中的圖像可以從Stanford
Dogs Dataset中找到符匾。Kernel擁有三個(gè)通道。這些通道會(huì)與[0,255]之間的RGB值同步瘩例,255是最大強(qiáng)度啊胶。調(diào)用tf.minimum和tf.nn.relu是將卷積值保持在有效RGB顏色的范圍內(nèi),即[0,255]垛贤。
在這個(gè)簡(jiǎn)化的例子中可以使用許多其他常用的內(nèi)核焰坪。不同的模式會(huì)產(chǎn)生不同的結(jié)果。以下內(nèi)核將通過(guò)增加顏色變化的強(qiáng)度來(lái)銳化圖像聘惦。
對(duì)比之前的卷積核某饰,我們發(fā)現(xiàn)內(nèi)核中的值被調(diào)整,內(nèi)核的中心強(qiáng)度增加,內(nèi)核周?chē)膮^(qū)域強(qiáng)度降低黔漂。內(nèi)核的變化使得可以匹配強(qiáng)烈像素的圖案诫尽,并增加輸出圖像的強(qiáng)度。這種變化在視覺(jué)上被銳化炬守。注意:請(qǐng)注意牧嫉,內(nèi)核的角都全為0,使得以加號(hào)形式運(yùn)行的輸出不會(huì)受到影響减途。
這些內(nèi)核在圖像基礎(chǔ)上匹配模式酣藻。卷積神經(jīng)網(wǎng)絡(luò)通過(guò)使用在訓(xùn)練期間學(xué)到的復(fù)雜內(nèi)核要比之更多。內(nèi)核的初始值通常是隨機(jī)的鳍置,隨著時(shí)間的推移辽剧,它們(n內(nèi)核里面的值)會(huì)被CNN的學(xué)習(xí)層訓(xùn)練。當(dāng)CNN是完整的的時(shí)候墓捻,開(kāi)始運(yùn)行并且發(fā)送每個(gè)圖像與內(nèi)核的卷積結(jié)果抖仅,然后根據(jù)預(yù)測(cè)值與圖像的label value來(lái)對(duì)卷積核進(jìn)行更改。例如:如果一個(gè)Sheepdog(是不是應(yīng)該翻譯成牧羊犬砖第?)的圖片在訓(xùn)練期間被CNN判斷為公牛撤卢,那么它(CNN)會(huì)修改過(guò)濾器(卷積核)的數(shù)量以便于更好的嘗試匹配SheepDog圖片。
用CNN學(xué)習(xí)負(fù)載的模式的時(shí)候梧兼,往往涉及的不僅僅是一層卷積放吩。即便是我們的代碼示例也要包含一個(gè)tf.nn.relu層,為可視化輸出做準(zhǔn)備羽杰。卷積層可能在CNN中發(fā)生多次渡紫,但它們也可能包括其他層類(lèi)型羡儿。這些層的組合成功的成為CNN架構(gòu)所需的支持網(wǎng)絡(luò)雏逾。
(PS:接下來(lái)5.3來(lái)會(huì)講解這些內(nèi)容)