keras圖像深度學(xué)習(xí)實(shí)戰(zhàn)_第1頁
keras圖像深度學(xué)習(xí)實(shí)戰(zhàn)_第2頁
keras圖像深度學(xué)習(xí)實(shí)戰(zhàn)_第3頁
keras圖像深度學(xué)習(xí)實(shí)戰(zhàn)_第4頁
keras圖像深度學(xué)習(xí)實(shí)戰(zhàn)_第5頁
已閱讀5頁,還剩127頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

圖像深度學(xué)習(xí)實(shí)戰(zhàn)2023目錄TOC\o"1-2"\h\u289861簡介 4135901.1keras是什么 499141.2一些基本概念 6326001.3安裝Python 9320811.4安裝Theano 10313851.5安裝opencv 11125651.6安裝Keras 1217532CNN眼中的世界 13198012.1卷積神經(jīng)網(wǎng)絡(luò) 14184632.2使用Keras探索卷積網(wǎng)絡(luò)的濾波器 17153382.3可視化所有的濾波器 2118952.4愚弄神經(jīng)網(wǎng)絡(luò) 22304022.5展望未來 2481683Keras模型 25145323.1Sequential模型 258843.2常用層 31115293.3卷積層 40304743.4池化層 44229674目標(biāo)函數(shù) 46288834.1MSE 47108824.2MAE 4828464.3MAPE 49246444.4MSLE 50235704.5squared_hinge 5157164.6hinge 52164414.7binary_crossentropy 53213734.8categorical_crossentropy 54220264.9sparse_categorical_crossentrop 5530135優(yōu)化器 5669425.1公共參數(shù) 57249375.2SGD 58245005.3RMSprop 5999125.4Adagrad 60111855.5Adadelta 62285865.6Adam 64184955.7Adamax 66147075.8Nadam 67316636訓(xùn)練模型的注意事項(xiàng) 6880296.1參數(shù)初始化 68126396.2數(shù)據(jù)預(yù)處理(DataPreprocessing) 7040067圖片預(yù)處理 74219177.1利用小數(shù)據(jù)量 74184987.2圖像處理scipy.ndimage 79117517.3熱點(diǎn)圖 80252577.4高斯濾波 82307187.5圖片翻轉(zhuǎn) 85120617.6輪廓檢測 87119307.7角點(diǎn) 90253507.8直方圖 9222497.9形態(tài)學(xué)圖像處理 94315808CNN實(shí)戰(zhàn) 99126068.1Mnist 100315438.2Cifar16 105238348.3人臉識(shí)別 109122818.4視頻識(shí)別 114260998.5用神經(jīng)網(wǎng)絡(luò)去噪 125122098.6視頻抽取圖片 132簡介keras是什么Keras是基于Theano或TensorFlow的一個(gè)深度學(xué)習(xí)框架,它的設(shè)計(jì)參考了Torch,用Python語言編寫,是一個(gè)高度模塊化的神經(jīng)網(wǎng)絡(luò)庫,支持GPU和CPU。pipinstallpythonModuleName-i/simpleKeras可以通過pip安裝,國內(nèi)可以換一個(gè)豆瓣pip源,網(wǎng)速快的驚人!臨時(shí)使用時(shí)可以使用下述命令:pipinstallpythonModuleName-i/simple也可以永久更改:/root/.pip/pip.conf:\[global]\[global]index-url=/simple在pip.conf中,添加以上內(nèi)容,就修改了默認(rèn)的軟件源。到\h/pypi/下載所需的python庫,直到安裝Keras。安裝以下軟件包,排名不分先后:Scipy,Numpy,Theano,Tensowflow,Pyyaml,Six,pycparser,cffi,Keras等。如果是.whl則運(yùn)行pipinstallxxx.whl安裝,如果是setup.py則運(yùn)行pythonsetup.pyinstall安裝(如果是源碼先運(yùn)行pythonsetup.pybuild),如果缺少依賴包會(huì)有提示,到下載對(duì)應(yīng)的依賴包再重新安裝就可以了。安裝過程中需要用到vc++forpython編譯器,到微軟官網(wǎng)上下載,也可從\hhttp://aka.ms/vcpython27進(jìn)去。安裝scipy的時(shí)候報(bào)錯(cuò)nolapack/blasresourcesfound。最后找到一個(gè)方法,到\h/~gohlke/pythonlibs/下載scipy對(duì)應(yīng)的whl安裝即可。最后運(yùn)行keras的例子:pythonimdb_lstm.py,如果正常運(yùn)行說明Keras安裝成功了!如果沒有安裝TensorFlow但安裝了Theano,則importkeras會(huì)提示找不到TensorFlow,因?yàn)镵eras默認(rèn)的backend是TensorFlow,這時(shí)候找到用戶目錄下的.keras/keras.json,將backend從“tensorflow”改成“theano”。例如目錄下:C:\Users\17020405.keras如果還不行則修改Lib\site-packages\keras\backend下的_init_.py文件,將_BACKEND從“tensorflow”改成“theano”。一些基本概念在開始學(xué)習(xí)Keras之前,我們希望傳遞一些關(guān)于Keras,關(guān)于深度學(xué)習(xí)的基本概念和技術(shù),這將減少學(xué)習(xí)過程中的困惑。符號(hào)計(jì)算Keras的底層庫使用Theano或TensorFlow,這兩個(gè)庫也稱為Keras的后端。無論是Theano還是TensorFlow,都是一個(gè)“符號(hào)式”的庫。因此,這也使得Keras的編程與傳統(tǒng)的Python代碼有所差別?;\統(tǒng)的說,符號(hào)主義的計(jì)算首先定義各種變量,然后建立一個(gè)“計(jì)算圖”,計(jì)算圖規(guī)定了各個(gè)變量之間的計(jì)算關(guān)系。建立好的計(jì)算圖需要編譯以確定其內(nèi)部細(xì)節(jié),然而,此時(shí)的計(jì)算圖還是一個(gè)“空殼子”,里面沒有任何實(shí)際的數(shù)據(jù),只有當(dāng)你把需要運(yùn)算的輸入放進(jìn)去后,才能在整個(gè)模型中形成數(shù)據(jù)流,從而形成輸出值。就像用管道搭建供水系統(tǒng),當(dāng)你在拼水管的時(shí)候,里面是沒有水的。只有所有的管子都接完了,才能送水。Keras的模型搭建形式就是這種方法,在你搭建Keras模型完畢后,你的模型就是一個(gè)空殼子,只有實(shí)際生成可調(diào)用的函數(shù)后(K.function),輸入數(shù)據(jù),才會(huì)形成真正的數(shù)據(jù)流。使用計(jì)算圖的語言,如Theano,以難以調(diào)試而聞名,當(dāng)Keras的Debug進(jìn)入Theano這個(gè)層次時(shí),往往也令人頭痛。沒有經(jīng)驗(yàn)的開發(fā)者很難直觀的感受到計(jì)算圖到底在干些什么。盡管很讓人頭痛,但大多數(shù)的深度學(xué)習(xí)框架使用的都是符號(hào)計(jì)算這一套方法,因?yàn)榉?hào)計(jì)算能夠提供關(guān)鍵的計(jì)算優(yōu)化、自動(dòng)求導(dǎo)等功能。通常建議在使用Keras前稍微了解一下Theano或TensorFlow,百度一下即可。張量張量,或tensor,是本文檔會(huì)經(jīng)常出現(xiàn)的一個(gè)詞匯,在此稍作解釋。使用這個(gè)詞匯的目的是為了表述統(tǒng)一,張量可以看作是向量、矩陣的自然推廣,我們用張量來表示廣泛的數(shù)據(jù)類型。規(guī)模最小的張量是0階張量,即標(biāo)量,也就是一個(gè)數(shù)。當(dāng)我們把一些數(shù)有序的排列起來,就形成了1階張量,也就是一個(gè)向量。如果我們繼續(xù)把一組向量有序的排列起來,就形成了2階張量,也就是一個(gè)矩陣。把矩陣摞起來,就是3階張量,我們可以稱為一個(gè)立方體,具有3個(gè)顏色通道的彩色圖片就是一個(gè)這樣的立方體。把立方體摞起來,好吧這次我們真的沒有給它起別名了,就叫4階張量了,不要去試圖想像4階張量是什么樣子,它就是個(gè)數(shù)學(xué)上的概念。張量的階數(shù)有時(shí)候也稱為維度,或者軸,軸這個(gè)詞翻譯自英文axis。譬如一個(gè)矩陣[[1,2],[3,4]],是一個(gè)2階張量,有兩個(gè)維度或軸,沿著第0個(gè)軸(為了與python的計(jì)數(shù)方式一致,本文檔維度和軸從0算起)你看到的是[1,2],[3,4]兩個(gè)向量,沿著第1個(gè)軸你看到的是[1,3],[2,4]兩個(gè)向量。要理解“沿著某個(gè)軸”是什么意思,不妨試著運(yùn)行一下下面的代碼:importnumpyasnpimportnumpyasnpa=np.array([[1,2],[3,4]])sum0=np.sum(a,axis=0)sum1=np.sum(a,axis=1)printsum0printsum1關(guān)于張量,目前知道這么多就足夠了。data_formatTheano和TensorFlow發(fā)生了分歧,'th'模式,也即Theano模式會(huì)把100張RGB三通道的16×32(高為16寬為32)彩色圖表示為下面這種形式(100,3,16,32),Caffe采取的也是這種方式。第0個(gè)維度是樣本維,代表樣本的數(shù)目,第1個(gè)維度是通道維,代表顏色通道數(shù)。后面兩個(gè)就是高和寬了。這種theano風(fēng)格的數(shù)據(jù)組織方法,稱為“channels_first”,即通道維靠前。而TensorFlow的表達(dá)形式是(100,16,32,3),即把通道維放在了最后,這種數(shù)據(jù)組織方式稱為“channels_last”。Keras默認(rèn)的數(shù)據(jù)組織形式在~/.keras/keras.json中規(guī)定,可查看該文件的image_data_format一項(xiàng),也可在代碼中通過K.image_data_format()函數(shù)返回,請(qǐng)?jiān)诰W(wǎng)絡(luò)的訓(xùn)練和測試中保持維度順序一致。模型在Keras0.x中有兩種模型,一種是Sequential模型,又稱為序貫?zāi)P?,也就是單輸入單輸作上也比較簡單。第二種模型稱為Graph,即圖模型,這個(gè)模型支持多輸入多輸出,層與層之間想怎么連怎么連,但是編譯速度慢??梢钥吹剑琒equential其實(shí)是Graph的一個(gè)特殊情況。在Keras1和Keras2中,圖模型被移除,從而增加了“functionalmodelAPI”這個(gè)東西,更加強(qiáng)調(diào)了Sequential模型是特殊的一種。一般的模型就稱為Model。由于functionalmodelAPI在使用時(shí)利用的是“函數(shù)式編程”的風(fēng)格,我們這里將其稱為函數(shù)式模型??偠灾灰@個(gè)東西接收一個(gè)或一些張量作為輸入,然后輸出的也是一個(gè)或一些張量,但不管它是什么,統(tǒng)統(tǒng)都叫做“模型”。batchbatch這個(gè)概念與Keras無關(guān),老實(shí)講不應(yīng)該出現(xiàn)在這里的,但是因?yàn)樗l繁出現(xiàn),而且不了解這個(gè)術(shù)語的話看函數(shù)會(huì)很頭痛,所有這里還是簡單說一下。深度學(xué)習(xí)的優(yōu)化算法,說白了就是梯度下降。每次的參數(shù)更新有兩種方式。種方法每更新一次參數(shù)都要把數(shù)據(jù)集里的所有樣本都看一遍,計(jì)算量開銷大,計(jì)算速度慢,不支持在線學(xué)習(xí),這稱為Batchgradientdescent,批梯度下降。另一種,每看一個(gè)數(shù)據(jù)就算一下?lián)p失函數(shù),然后求梯度更新參數(shù),這個(gè)稱為隨機(jī)梯度下降,stochasticgradientdescent。這個(gè)方法速度比較快,但是收斂性能不太好,可能在最優(yōu)點(diǎn)附近晃來晃去,hit不到最優(yōu)點(diǎn)。兩次參數(shù)的更新也有可能互相抵消掉,造成目標(biāo)函數(shù)震蕩的比較劇烈。為了克服兩種方法的缺點(diǎn),現(xiàn)在一般采用的是一種折中手段,mini-batchgradientdecent,小批的梯度下降,這種方法把數(shù)據(jù)分為若干個(gè)批,按批來更新參數(shù),這樣,一個(gè)批中的一組數(shù)據(jù)共同決定了本次梯度的方向,下降起來就不容易跑偏,減少了隨機(jī)性。另一方面因?yàn)榕臉颖緮?shù)與整個(gè)數(shù)據(jù)集相比小了很多,所以計(jì)算量也不是很大?;旧犀F(xiàn)在的梯度下降都是基于mini-batch的,所以Keras的模塊中經(jīng)常會(huì)出現(xiàn)batch_size,就是指這個(gè)。順便說一句,Keras中用的優(yōu)化器SGD是stochasticgradientdescent的縮寫,但不代表是一個(gè)樣本就更新一回,而是基于mini-batch的。epochs簡單說,epochs指的就是訓(xùn)練過程中數(shù)據(jù)將被“輪詢”多少次,就這樣。安裝Python安裝Python2.7版本,具體安裝方法這里就不詳細(xì)說明了。安裝Theano從\h/Theano/Theano下載Theano的主版本,將theano目錄放到Python的Lib\site-packagesKeras目錄中。從github下載Keras源碼并安裝到Python環(huán)境中。安裝opencv圖像識(shí)別需要我們首先安裝python環(huán)境下的圖像處理庫。Python社區(qū)提供了許多的圖像處理庫,這里我們使用opencv作為圖像處理庫。筆者是下載opencv的whl安裝文件進(jìn)行安裝的,命令為:pipinstallopencv_python--cp27-cp27m-win_amd64.whlpipinstallopencv_python--cp27-cp27m-win_amd64.whl如果安裝過程中由于網(wǎng)絡(luò)的原因等造成依賴包無法下載安裝,則可以根據(jù)提示從:\h/pypi下載所需的依賴包版本,先安裝依賴再安裝opencv,直到最后安裝成功。安裝Keras從\h/fchollet/keras下載Keras源碼,將keras目錄放到Python的Lib\site-packages目錄中。注意這里Keras和Theano的版本要保持一致,否則容易出現(xiàn)不兼容的情況而導(dǎo)致示例代碼無法運(yùn)行,筆者安裝的是github上的master版本,可以正常運(yùn)行示例。CNN眼中的世界我們首先以Keras官網(wǎng)中一篇經(jīng)典的關(guān)于CNN原理的科普文章作為開始,從這篇文章中我們希望能了解到CNN模型的前世今生,以及對(duì)CNN原理有一個(gè)初步的感性認(rèn)識(shí)。卷積神經(jīng)網(wǎng)絡(luò)卷積神經(jīng)網(wǎng)絡(luò)是一個(gè)多層的神經(jīng)網(wǎng)絡(luò),每層由多個(gè)二維平面組成,而每個(gè)平面由多個(gè)獨(dú)立神經(jīng)元組成。上圖是卷積神經(jīng)網(wǎng)絡(luò)的概念示范:輸入圖像通過和三個(gè)可訓(xùn)練的濾波器及可加偏置進(jìn)行卷積,卷積后在C1層產(chǎn)生三個(gè)特征映射圖,然后特征映射圖中每組的四個(gè)像素再進(jìn)行求和,加權(quán)值,加偏置,通過一個(gè)Sigmoid函數(shù)得到三個(gè)S2層的特征映射圖。這些映射圖再進(jìn)過濾波得到C3層。這個(gè)層級(jí)結(jié)構(gòu)再和S2一樣產(chǎn)生S4。最終,這些像素值被光柵化,并連接成一個(gè)向量輸入到傳統(tǒng)的神經(jīng)網(wǎng)絡(luò),從而得到輸出。每個(gè)層有多個(gè)FeatureMap,每個(gè)FeatureMap通過一種卷積濾波器提取輸入的一種特征,然后每個(gè)FeatureMap有多個(gè)神經(jīng)元。卷積過程如下,比如矩陣[[1,2,3],[4,5,6]],假設(shè)卷積核為[2,2],初始偏移為0,假設(shè)權(quán)重為0.2,則卷積之后的結(jié)果為[0.6,0.8]。計(jì)算過程如下:(1*0.2+2*0.2+4*0.2+5*0.2)/4=2.4/4=0.6(2*0.2+3*0.2+5*0.2+6*0.2)/4=3.2/4=0.8CNN一個(gè)極具創(chuàng)新的地方就在于通過權(quán)值共享減少了神經(jīng)網(wǎng)絡(luò)需要訓(xùn)練的參數(shù)數(shù)目,所謂權(quán)值共享就是同一個(gè)FeatureMap中神經(jīng)元權(quán)值共享,該FeatureMap中的所有神經(jīng)元使用同一個(gè)權(quán)值。因此參數(shù)個(gè)數(shù)與神經(jīng)元的個(gè)數(shù)無關(guān),只與卷積核的大小及FeatureMap的個(gè)數(shù)相關(guān)。但是共有多少個(gè)連接個(gè)數(shù)就與神經(jīng)元的個(gè)數(shù)相關(guān)了,神經(jīng)元的個(gè)數(shù)也就是特征圖的大小。下面以最經(jīng)典的LeNet-5例子來逐層分析各層的參數(shù)及連接個(gè)數(shù)。C1層是一個(gè)卷積層,由6個(gè)特征圖FeatureMap構(gòu)成。特征圖中每個(gè)神經(jīng)元與輸入為5*5的鄰域相連。特征圖的大小為28*28,這樣能防止輸入的連接掉到邊界之外(32-5+1=28)。C1有156個(gè)可訓(xùn)練參數(shù)(每個(gè)濾波器5*5=25個(gè)unit參數(shù)和一個(gè)bias參數(shù),一共6個(gè)濾波器,共(5*5+1)*6=156個(gè)參數(shù)),共156*(28*28)=122,304個(gè)連接。S2層是一個(gè)下采樣層,有6個(gè)14*14的特征圖。特征圖中的每個(gè)單元與C1中相對(duì)應(yīng)特征圖的2*2鄰域相連接。S2層每個(gè)單元的4個(gè)輸入相加,乘以一個(gè)可訓(xùn)練參數(shù),再加上一個(gè)可訓(xùn)練偏置。每個(gè)單元的2*2感受野并不重疊,因此S2中每個(gè)特征圖的大小是C1中特征圖大小的1/4(行和列各1/2)。S2層有12(6*(1+1)=12)個(gè)可訓(xùn)練參數(shù)和5880(14*14*(2*2+1)*6=5880)個(gè)連接。C3層也是一個(gè)卷積層,它同樣通過5x5的卷積核去卷積層S2,然后得到的特征map就只有10x10個(gè)神經(jīng)元,但是它有16種不同的卷積核,所以就存在16個(gè)特征map了。C3中每個(gè)特征圖由S2中所有6個(gè)或者幾個(gè)特征map組合而成。為什么不把S2中的每個(gè)特征圖連接到每個(gè)C3的特征圖呢?原因有2點(diǎn)。第一,不完全的連接機(jī)制將連接的數(shù)量保持在合理的范圍內(nèi)。第二,也是最重要的,其破壞了網(wǎng)絡(luò)的對(duì)稱性。由于不同的特征圖有不同的輸入,所以迫使他們抽取不同的特征(希望是互補(bǔ)的)。例如,存在的一個(gè)方式是:C3的前6個(gè)特征圖以S2中3個(gè)相鄰的特征圖子集為輸入。接下來6個(gè)特征圖以S2中4個(gè)相鄰特征圖子集為輸入。然后的3個(gè)特征圖以不相鄰的4個(gè)特征圖子集為輸入。最后一個(gè)將S2中所有特征圖為輸入。這樣C3層有1516(6*(3*25+1)+6*(4*25+1)+3*(4*25+1)+(25*6+1)=1516)個(gè)可訓(xùn)練參數(shù)和151600(10*10*1516=151600)個(gè)連接。S4層是一個(gè)下采樣層,由16個(gè)5*5大小的特征圖構(gòu)成。特征圖中的每個(gè)單元與C3中相應(yīng)特征圖的2*2鄰域相連接,跟C1和S2之間的連接一樣。S4層有32個(gè)可訓(xùn)練參數(shù)(每個(gè)特征圖1個(gè)因子和一個(gè)偏置16*(1+1)=32)和2000(16*(2*2+1)*5*5=2000)個(gè)連接。C5層是一個(gè)卷積層,有120個(gè)特征圖。每個(gè)單元與S4層的全部16個(gè)單元的5*5鄰域相連。由于S4層特征圖的大小也為5*5(同濾波器一樣),故C5特征圖的大小為1*1(5-5+1=1):這構(gòu)成了S4和C5之間的全連接。之所以仍將C5標(biāo)示為卷積層而非全相聯(lián)層,是因?yàn)槿绻鸏eNet-5的輸入變大,而其他的保持不變,那么此時(shí)特征圖的維數(shù)就會(huì)比1*1大。C5層有48120(120*(16*5*5+1)=48120由于與全部16個(gè)單元相連,故只加一個(gè)偏置)個(gè)可訓(xùn)練連接。F6層有84個(gè)單元(之所以選這個(gè)數(shù)字的原因來自于輸出層的設(shè)計(jì)),與C5層全相連。有10164(84*(120*(1*1)+1)=10164)個(gè)可訓(xùn)練參數(shù)。如同經(jīng)典神經(jīng)網(wǎng)絡(luò),F(xiàn)6層計(jì)算輸入向量和權(quán)重向量之間的點(diǎn)積,再加上一個(gè)偏置。然后將其傳遞給sigmoid函數(shù)產(chǎn)生單元i的一個(gè)狀態(tài)。最后,輸出層由歐式徑向基函數(shù)(EuclideanRadialBasisFunction)單元組成,每類一個(gè)單元,每個(gè)有84個(gè)輸入。卷積過程包括:用一個(gè)可訓(xùn)練的濾波器fx去卷積一個(gè)輸入的圖像(第一階段是輸入的圖像,后面的階段就是卷積特征map了),然后加一個(gè)偏置bx,得到卷積層Cx包括:每鄰域四個(gè)像素求和變?yōu)橐粋€(gè)像素,然后通過標(biāo)量Wx+1加權(quán),再增加偏置bx+1,然后通過一個(gè)sigmoid激活函數(shù),產(chǎn)生一個(gè)大概縮小四倍的特征映射圖Sx+1。使用Keras探索卷積網(wǎng)絡(luò)的濾波器本文中我們將利用Keras觀察CNN到底在學(xué)些什么,它是如何理解我們送入的訓(xùn)練圖片Keras來對(duì)濾波器的激活值進(jìn)行可視化。本文使用的神經(jīng)網(wǎng)絡(luò)是VGG-16,數(shù)據(jù)集為ImageNet。本文的代碼可以在github找到。VGG-16又稱為OxfordNet,是由牛津視覺幾何組(VisualGeometryGroup)開發(fā)的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。該網(wǎng)絡(luò)贏得了ILSVR(ImageNet)2014的冠軍。時(shí)至今日,VGG仍然被認(rèn)為是一個(gè)杰出的視覺模型——盡管它的性能實(shí)際上已經(jīng)被后來的Inception和ResNet超過了。LorenzoBaraldi將Caffe預(yù)訓(xùn)練好的VGG16和VGG19模型轉(zhuǎn)化為了Keras權(quán)重文件,所以我們可以簡單的通過載入權(quán)重來進(jìn)行實(shí)驗(yàn)。該權(quán)重文件的下載需要自備梯子(這里有一個(gè)網(wǎng)盤保持的vgg16:\h/weights/vgg16_weights.h5趕緊下載)。首先,我們?cè)贙eras中定義VGG網(wǎng)絡(luò)的結(jié)構(gòu):fromkeras.modelsimportSequentialfromkeras.modelsimportSequentialfromkeras.layersimportConvolution2D,ZeroPadding2D,MaxPooling2Dimg_width,img_height=128,128#buildtheVGG16networkmodel=Sequential()model.add(ZeroPadding2D((1,1),batch_input_shape=(1,3,img_width,img_height)))first_layer=model.layers[-1]#thisisaplaceholdertensorthatwillcontainourgeneratedimagesinput_img=first_layer.input#buildtherestofthenetworkmodel.add(Convolution2D(64,3,3,activation='relu',name='conv1_1'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(64,3,3,activation='relu',name='conv1_2'))model.add(MaxPooling2D((2,2),strides=(2,2)))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(128,3,3,activation='relu',name='conv2_1'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(128,3,3,activation='relu',name='conv2_2'))model.add(Convolution2D(128,3,3,activation='relu',name='conv2_2'))model.add(MaxPooling2D((2,2),strides=(2,2)))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(256,3,3,activation='relu',name='conv3_1'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(256,3,3,activation='relu',name='conv3_2'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(256,3,3,activation='relu',name='conv3_3'))model.add(MaxPooling2D((2,2),strides=(2,2)))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv4_1'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv4_2'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv4_3'))model.add(MaxPooling2D((2,2),strides=(2,2)))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv5_1'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv5_2'))model.add(ZeroPadding2D((1,1)))model.add(Convolution2D(512,3,3,activation='relu',name='conv5_3'))model.add(MaxPooling2D((2,2),strides=(2,2)))#getthesymbolicoutputsofeach"key"layer(wegavethemuniquenames).layer_dict=dict([(,layer)forlayerinmodel.layers])注意我們不需要全連接層,所以網(wǎng)絡(luò)就定義到最后一個(gè)卷積層為止。使用全連接層會(huì)將輸入大小限制為224×224,即ImageNet原圖片的大小。這是因?yàn)槿绻斎氲膱D片大小不是224×224,在從卷積過度到全鏈接時(shí)向量的長度與模型指定的長度不相符。下面,我們將預(yù)訓(xùn)練好的權(quán)重載入模型,一般而言我們可以通過model.load_weights()載所以我們需要手工載入:importimporth5pyweights_path='vgg16_weights.h5'f=h5py.File(weights_path)importh5pyweights_path='vgg16_weights.h5'f=h5py.File(weights_path)forkinrange(f.attrs['nb_layers']):ifk>=len(model.layers):#wedon'tlookatthelast(fully-connected)layersinthesavefilebreakg=f['layer_{}'.format(k)]weights=[g['param_{}'.format(p)]forpinrange(g.attrs['nb_params'])]model.layers[k].set_weights(weights)f.close()print('Modelloaded.')下面,我們要定義一個(gè)損失函數(shù),這個(gè)損失函數(shù)將用于最大化某個(gè)指定濾波器的激活值。以該函數(shù)為優(yōu)化目標(biāo)優(yōu)化后,我們可以真正看一下使得這個(gè)濾波器激活的究竟是些什么東西?,F(xiàn)在我們使用Keras的后端來完成這個(gè)損失函數(shù),這樣代碼不用修改就可以在TensorFlow和Theano之間切換了。TensorFlow在CPU上進(jìn)行卷積要快的多,而目前為止Theano在GPU上進(jìn)行卷積要快一些。fromkerasimportbackendasKlayer_name='conv5_1'filter_index=0fromkerasimportbackendasKlayer_name='conv5_1'filter_index=0#buildalossfunctionthatmaximizestheactivation#ofthenthfilterofthelayerconsideredlayer_output=layer_dict[layer_name].outputloss=K.mean(layer_output[:,filter_index,:,:])#computethegradientoftheinputpicturewrtthislossgrads=K.gradients(loss,input_img)[0]#normalizationtrick:wenormalizethegradientgrads/=(K.sqrt(K.mean(K.square(grads)))+1e-5)#thisfunctionreturnsthelossandgradsgiventheinputpictureiterate=K.function([input_img],[loss,grads])注意這里有個(gè)小trick,計(jì)算出來的梯度進(jìn)行了正規(guī)化,使得梯度不會(huì)過小或過大。這種正規(guī)化能夠使梯度上升的過程平滑進(jìn)行。根據(jù)剛剛定義的函數(shù),現(xiàn)在可以對(duì)某個(gè)濾波器的激活值進(jìn)行梯度上升。importnumpyasnpimportnumpyasnp#westartfromagrayimagewithsomenoiseinput_img_data=np.random.random((1,3,img_width,img_height))*20+128.#rungradientascentfor20stepsforiinrange(20):loss_value,grads_value=iterate([input_img_data])input_img_data+=grads_value*step使用TensorFlow時(shí),這個(gè)操作大概只要幾秒。然后我們可以提取出結(jié)果,并可視化:fromscipy.miscimportimsavefromscipy.miscimportimsave#utilfunctiontoconvertatensorintoavalidimagedefdeprocess_image(x):#normalizetensor:centeron0.,ensurestdis0.1x-=x.mean()x/=(x.std()+1e-5)x*=0.1#clipto[0,1]x+=0.5x=np.clip(x,0,1)#converttoRGBarrayx*=255x=x.transpose((1,2,0))x=np.clip(x,0,255).astype('uint8')returnximg=input_img_data[0]img=deprocess_image(img)img=deprocess_image(img)imsave('%s_filter_%d.png'%(layer_name,filter_index),img)這里是第5卷基層第0個(gè)濾波器的結(jié)果:可視化所有的濾波器下面我們系統(tǒng)的可視化一下各個(gè)層的各個(gè)濾波器結(jié)果,看看CNN是如何對(duì)輸入進(jìn)行逐層分解的。第一層的濾波器主要完成方向、顏色的編碼,這些顏色和方向與基本的紋理組合,逐漸生成復(fù)雜的形狀??梢詫⒚繉拥臑V波器想像為基向量,這些基向量一般是過完備的?;蛄靠梢詫拥妮斎刖o湊地編碼出來。濾波器隨著其利用的空域信息的拓寬而更加精細(xì)和復(fù)雜。上圖只是展示了部分內(nèi)容??梢杂^察到,很多濾波器的內(nèi)容其實(shí)是一樣的,只不過旋轉(zhuǎn)了一個(gè)隨機(jī)的的角度(如90度)而已。這意味著我們可以通過使得卷積濾波器具有旋轉(zhuǎn)不變性而顯著減少濾波器的數(shù)目,這是一個(gè)有趣的研究方向。令人震驚的是,這種旋轉(zhuǎn)的性質(zhì)在高層的濾波器中仍然可以被觀察到,如Conv4_1。愚弄神經(jīng)網(wǎng)絡(luò)如果我們添加上VGG一張很像該類別的圖片嗎?讓我們?cè)囋?。這種情況下我們的損失函數(shù)長這樣:layer_output=model.layers\[-1].get_output()loss=K.mean(layer_output\[:,output_index])layer_output=model.layers\[-1].get_output()loss=K.mean(layer_output\[:,output_index])比方說我們來最大化輸出下標(biāo)為65的那個(gè)類,在ImageNet損失達(dá)到了0.999,即神經(jīng)網(wǎng)絡(luò)有99.9%的概率認(rèn)為我們生成的圖片是一條海蛇,它長這樣:不太像呀,換個(gè)類別試試,這次選喜鵲類(第18類)。OK,我們的網(wǎng)絡(luò)認(rèn)為是喜鵲的東西看起來完全不是喜鵲,往好了說,這個(gè)圖里跟喜鵲相似的,也不過就是一些局部的紋理,如羽毛、嘴巴之類的。那么,這就意味著卷積神經(jīng)網(wǎng)絡(luò)是個(gè)很差的工具嗎?當(dāng)然不是,我們按照一個(gè)特定任務(wù)來訓(xùn)練它,它就會(huì)在那個(gè)任務(wù)上表現(xiàn)的不錯(cuò)。但我們不能有網(wǎng)絡(luò)“理解”某個(gè)概念的錯(cuò)覺。我們不能將網(wǎng)絡(luò)人格化,它只是工具而已。比如一條狗,它能識(shí)別其為狗只是因?yàn)樗芤院芨叩母怕蕦⑵湔_分類而已,而不代表它理解關(guān)于“狗”的任何外延。展望未來所以,神經(jīng)網(wǎng)絡(luò)到底理解了什么呢?我認(rèn)為有兩件事是它們理解的。其一,神經(jīng)網(wǎng)絡(luò)理解了如何將輸入空間解耦為分層次的卷積濾波器組。其二,神經(jīng)網(wǎng)絡(luò)理解了從一系列濾波器的組合到一系列特定標(biāo)簽的概率映射。神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)到的東西完全達(dá)不到人類的“看見”的意義,從科學(xué)的的角度講,這當(dāng)然也不意味著我們已經(jīng)解決了計(jì)算機(jī)視覺的問題。想得別太多,我們才剛剛踩上計(jì)算機(jī)視覺天梯的第一步。這種說法可能對(duì)也可能不對(duì),但目前未知我們還沒有比較強(qiáng)的證據(jù)來承認(rèn)或否認(rèn)它。當(dāng)我們視覺世界的自然解耦(就像傅里葉變換是對(duì)周期聲音信號(hào)的一種解耦一樣自然)構(gòu)的真正目的目前還不得而知,這種結(jié)構(gòu)在我們的人工神經(jīng)網(wǎng)絡(luò)中還沒有出現(xiàn)(帝GeoffHinton正在在這個(gè)方面努力)。此外,人類有比給靜態(tài)圖像分類的感知器多得多等多種機(jī)制復(fù)雜控制??偠灾?,卷積神經(jīng)網(wǎng)絡(luò)的可視化工作是很讓人著迷的,誰能想到僅僅通過簡單的梯度下降法和合理的損失函數(shù),加上大規(guī)模的數(shù)據(jù)庫,就能學(xué)到能很好解釋復(fù)雜視覺信息的如此漂亮的分層模型呢。深度學(xué)習(xí)或許在實(shí)際的意義上并不智能,但它仍然能夠達(dá)到幾年前任何人都無法達(dá)到的效果?,F(xiàn)在,如果我們能理解為什么深度學(xué)習(xí)如此有效,那……嘿嘿。Keras模型Sequential模型Keras一般用Sequential模型做為搭建神經(jīng)網(wǎng)絡(luò)的開始,本節(jié)簡要論述Sequential模型接口的主要使用方法。add定義:add(self,layer)用途:向模型中添加一個(gè)層。參數(shù)layer是Layer對(duì)象,也即是層。pop定義:pop(self)用途:彈出模型最后的一層,無返回值,該方法一般很少用到。compile定義:compile(self,optimizer,loss,metrics=None,sample_weight_mode=None)compile(self,optimizer,loss,metrics=None,sample_weight_mode=None)該方法編譯用來配置模型的學(xué)習(xí)過程,其參數(shù)有以下這些:optimizer:字符串(預(yù)定義優(yōu)化器名)或優(yōu)化器對(duì)象,參考優(yōu)化器。loss:字符串(預(yù)定義損失函數(shù)名)或目標(biāo)函數(shù),參考損失函數(shù)。metrics:列表,包含評(píng)估模型在訓(xùn)練和測試時(shí)的網(wǎng)絡(luò)性能的指標(biāo),典型用法是metrics=['accuracy']。sample_weight_mode:如果你需要按時(shí)間步為樣本賦權(quán)(2D權(quán)矩陣),將該值設(shè)為“temporal”。默認(rèn)為“None”,代表按樣本賦權(quán)(1D權(quán))。kwargs:使用TensorFlow作為后端請(qǐng)忽略該參數(shù),若使用Theano作為后端,kwargs的值將會(huì)傳遞給K.function。例子:model=Sequential()model.add(Dense(32,model=Sequential()model.add(Dense(32,input_shape=(500,)))model.add(Dense(10,activation='softmax'))pile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])該例子添加兩個(gè)Dense層,并用rmsprop優(yōu)化器進(jìn)行優(yōu)化,損失函數(shù)定義為categorical_crossentroy,各種損失函數(shù)的含義在后面章節(jié)中會(huì)提高。模型在使用前必須編譯,否則在調(diào)用fit或evaluate時(shí)會(huì)拋出異常。fit定義:fit(self,fit(self,x,y,batch_size=32,epochs=10,verbose=1,callbacks=None,validation_split=0.0,val本函數(shù)將模型訓(xùn)練epoch輪,其參數(shù)有:x:輸入數(shù)據(jù)。如果模型只有一個(gè)輸入,那么x的類型是numpyarray,如果模型有多個(gè)輸入,那么x的類型應(yīng)當(dāng)為list,list的元素是對(duì)應(yīng)于各個(gè)輸入的numpyarray。y:標(biāo)簽向量,numpyarray類型。batch包含的樣本數(shù)。訓(xùn)練時(shí)一個(gè)batch的樣本會(huì)被計(jì)算一次梯度下降,使目標(biāo)函數(shù)優(yōu)化一步。epoch會(huì)把訓(xùn)練集輪一遍。verbose:日志顯示,0為不在標(biāo)準(zhǔn)輸出流輸出日志信息,1為輸出進(jìn)度條記錄,2為每個(gè)epoch輸出一行記錄。callbacks:list,其中的元素是keras.callbacks.Callback的對(duì)象。這個(gè)list中的回調(diào)函數(shù)將會(huì)在訓(xùn)練過程中的適當(dāng)時(shí)機(jī)被調(diào)用,參考回調(diào)函數(shù)validation_split:0~1之間的浮點(diǎn)數(shù),用來指定訓(xùn)練集的一定比例數(shù)據(jù)作為驗(yàn)證集。注意,validation_split的劃分在shuffle之前,因此如果你的數(shù)據(jù)本身是有序的,需要先手工打亂再指定validation_split,否則可能會(huì)出現(xiàn)驗(yàn)證集樣本不均勻。validation_data:形式為(X,y)的tuple,是指定的驗(yàn)證集。此參數(shù)將覆蓋validation_spilt參數(shù)。shuffle:布爾值或字符串,一般為布爾值,表示是否在訓(xùn)練過程中隨機(jī)打亂輸入樣本的順序。若為字符串“batch”,則是用來處理HDF5數(shù)據(jù)的特殊情況,它將在batch內(nèi)部將數(shù)據(jù)打亂。class_weight:字典,將不同的類別映射為不同的權(quán)值,該參數(shù)用來在訓(xùn)練過程中調(diào)整損失函數(shù)(只能用于訓(xùn)練)。sample_weight:權(quán)值的numpyarray,用于在訓(xùn)練時(shí)調(diào)整損失函數(shù)(僅用于訓(xùn)練)??梢詡鬟f一個(gè)1D的與樣本等長的向量用于對(duì)樣本進(jìn)行1對(duì)1的加權(quán),或者在面對(duì)時(shí)序數(shù)據(jù)時(shí),傳遞一個(gè)的形式為<samples,sequence_length>的矩陣來為每個(gè)時(shí)間步上的樣本賦不同的權(quán)。這種情況下請(qǐng)確定在編譯模型時(shí)添加了sample_weight_mode='temporal'。initial_epoch:從該參數(shù)指定的epoch開始訓(xùn)練,在繼續(xù)之前的訓(xùn)練時(shí)有用。fit函數(shù)返回一個(gè)History的對(duì)象,其History.history屬性記錄了損失函數(shù)和其他指標(biāo)的數(shù)值隨epoch變化的情況,如果有驗(yàn)證集的話,也包含了驗(yàn)證集的這些指標(biāo)變化情況。evaluate定義:evaluate(self,x,y,batch_size=32,verbose=1,sample_weight=None)evaluate(self,x,y,batch_size=32,verbose=1,sample_weight=None)本函數(shù)按batch計(jì)算在某些輸入數(shù)據(jù)上模型的誤差,其參數(shù)有:x:輸入數(shù)據(jù),與fit一樣,是numpyarray或numpyarray的list。y:標(biāo)簽,numpyarray。batch_size:整數(shù),含義同fit的同名參數(shù)。verbose:含義同fit的同名參數(shù),但只能取0或1。sample_weight:numpyarray,含義同fit的同名參數(shù)。本函數(shù)返回一個(gè)測試誤差的標(biāo)量值(如果模型沒有其他評(píng)價(jià)指標(biāo)),或一個(gè)標(biāo)量的list(如果模型還有其他的評(píng)價(jià)指標(biāo))。model.metrics_names將給出list中各個(gè)值的含義。如果沒有特殊說明,以下函數(shù)的參數(shù)均保持與fit的同名參數(shù)相同的含義。predictpredict(self,x,batch_size=32,verbose=0)predict(self,x,batch_size=32,verbose=0)本函數(shù)按batch獲得輸入數(shù)據(jù)對(duì)應(yīng)的預(yù)測結(jié)果,其中x是輸入向量,batch_size是每批次選取的數(shù)據(jù)集數(shù)量。函數(shù)的返回值是預(yù)測值的numpyarray。predict_classespredict_classes(self,x,batch_size=32,verbose=1)predict_classes(self,x,batch_size=32,verbose=1)本函數(shù)按batch產(chǎn)生輸入數(shù)據(jù)的類別預(yù)測結(jié)果,它和predict的區(qū)別是:Predict返回各個(gè)類別的可能性結(jié)果,是一個(gè)n維向量,n等于類別的數(shù)量;而predict_classes返回的是最可能的類別,對(duì)每個(gè)輸入返回的是類別名稱。函數(shù)的返回值是類別預(yù)測結(jié)果的numpyarray或numpy。train_on_batchtrain_on_batch(self,x,y,class_weight=None,sample_weight=None)train_on_batch(self,x,y,class_weight=None,sample_weight=None)本函數(shù)在一個(gè)batch的數(shù)據(jù)上進(jìn)行一次參數(shù)更新。函數(shù)返回訓(xùn)練誤差的標(biāo)量值或標(biāo)量值的list,與evaluate的情形相同。test_on_batchtest_on_batch(self,x,y,sample_weight=None)test_on_batch(self,x,y,sample_weight=None)本函數(shù)在一個(gè)batch的樣本上對(duì)模型進(jìn)行評(píng)估。函數(shù)的返回與evaluate的情形相同。predict_on_batchpredict_on_batch(self,x)predict_on_batch(self,x)本函數(shù)在一個(gè)batch的樣本上對(duì)模型進(jìn)行測試。函數(shù)返回模型在一個(gè)batch上的預(yù)測結(jié)果。fit_generatorfit_generator(self,fit_generator(self,generator,steps_per_epoch,epochs=1,verbose=1,callbacks=None,validatio利用Python的生成器,逐個(gè)生成數(shù)據(jù)的batch并進(jìn)行訓(xùn)練。生成器與模型將并行執(zhí)行以提高效率。例如,該函數(shù)允許我們?cè)贑PU上進(jìn)行實(shí)時(shí)的數(shù)據(jù)提升,同時(shí)在GPU上進(jìn)行模型訓(xùn)練。函數(shù)的參數(shù)是:的tuple。一個(gè)形如(inputstargets,sample_weight)的tuple。所有的返回值都應(yīng)該包含相同數(shù)目的樣本。生成器將無限在數(shù)據(jù)集上循環(huán)。每個(gè)epoch以經(jīng)過模型的樣本數(shù)達(dá)到samples_per_epoch時(shí),記一個(gè)epoch結(jié)束。steps_per_epoch:整數(shù),當(dāng)生成器返回steps_per_epoch次數(shù)據(jù)時(shí)計(jì)一個(gè)epoch結(jié)束,執(zhí)行下一個(gè)epoch。epochs:整數(shù),數(shù)據(jù)迭代的輪數(shù)。verbose:日志顯示,0為不在標(biāo)準(zhǔn)輸出流輸出日志信息,1為輸出進(jìn)度條記錄,2為每個(gè)epoch輸出一行記錄。validation_data:具有以下三種形式之一。生成驗(yàn)證集的生成器。一個(gè)形如(inputs,targets)的tuple。一個(gè)形如(inputs,targets,sample_weights)的tuple。validation_steps當(dāng)validation_data為生成器時(shí),本參數(shù)指定驗(yàn)證集的生成器返回次數(shù)。sample_weight:權(quán)值的numpyarray,用于在訓(xùn)練時(shí)調(diào)整損失函數(shù)(僅用于訓(xùn)練)??梢詡鬟f一個(gè)1D的與樣本等長的向量用于對(duì)樣本進(jìn)行1對(duì)1的加權(quán),或者在面對(duì)時(shí)序數(shù)據(jù)時(shí),傳遞一個(gè)的形式為(samples,sequence_length)的矩陣來為每個(gè)時(shí)間步上的樣本賦不同的權(quán)。這種情況下請(qǐng)確定在編譯模型時(shí)添加了sample_weight_mode='temporal'。workers:最大進(jìn)程數(shù)。max_q_size:生成器隊(duì)列的最大容量。pickle_safe:若為真,則使用基于進(jìn)程的線程。由于該實(shí)現(xiàn)依賴多進(jìn)程,不能傳遞nonpicklable(無法被pickle序列化)的參數(shù)到生成器中,因?yàn)闊o法輕易將它們傳入子進(jìn)程中。initial_epoch:從該參數(shù)指定的epoch開始訓(xùn)練,在繼續(xù)之前的訓(xùn)練時(shí)有用。函數(shù)返回一個(gè)History對(duì)象。例子:defgenerate_arrays_from_file(path):while1:defgenerate_arrays_from_file(path):while1:f=open(path)forlineinf:#createNumpyarraysofinputdata#andlabels,fromeachlineinthefilex,y=process_line(line)yield(x,y)f.close()model.fit_generator(generate_arrays_from_file('/my_file.txt'),samples_per_epoch=10000,epochs=10)evaluate_generatorevaluate_generator(self,generator,steps,max_q_size=10,workers=1,pickle_safe=False)evaluate_generator(self,generator,steps,max_q_size=10,workers=1,pickle_safe=False)本函數(shù)使用一個(gè)生成器作為數(shù)據(jù)源評(píng)估模型,生成器應(yīng)返回與test_on_batch的輸入數(shù)據(jù)相同類型的數(shù)據(jù)。該函數(shù)的參數(shù)與fit_generator同名參數(shù)含義相同,steps是生成器要返回?cái)?shù)據(jù)的輪數(shù)。predcit_generatorpredict_generator(self,predict_generator(self,generator,steps,max_q_size=10,workers=1,pickle_safe=False,verbose本函數(shù)使用一個(gè)生成器作為數(shù)據(jù)源預(yù)測模型,生成器應(yīng)返回與test_on_batch的輸入數(shù)據(jù)相同類型的數(shù)據(jù)。該函數(shù)的參數(shù)與fit_generator同名參數(shù)含義相同,steps是生成器要返回?cái)?shù)據(jù)的輪數(shù)。常用層Keras的層即是網(wǎng)絡(luò)層的意思。包括了常用層,卷積層,池化層,嵌入層,循環(huán)層,融合層,噪音層等多種類別。本書不打算介紹所有的層,只著重介紹與神經(jīng)網(wǎng)絡(luò)識(shí)別最相關(guān)的幾類層。如常用層,卷積層,池化層等。這一節(jié)介紹常用層,常用層對(duì)應(yīng)于core模塊,core內(nèi)部定義了一系列常用的網(wǎng)絡(luò)層,包括全連接、激活層等。所有的Keras層對(duì)象都有如下方法:layer.get_weights():返回層的權(quán)重(numpyarray)。layer.set_weights(weights):從numpyarray中將權(quán)重加載到該層中,要求numpyarray的形狀與layer.get_weights()的形狀相同。layer.get_config():返回當(dāng)前層配置信息的字典,層也可以借由配置信息重構(gòu)。例如:layer=Dense(32)config=layer.get_config()reconstructed_layer=Dense.from_config(config)或者:fromkerasimportlayersconfig=layer.get_config()layer=layers.deserialize({'class_name':layer.class.name,'config':config})如果層僅有一個(gè)計(jì)算節(jié)點(diǎn)(即該層不是共享層),則可以通過下列方法獲得輸入張量、輸出張量、輸入數(shù)據(jù)的形狀和輸出數(shù)據(jù)的形狀:layer.inputlayer.outputlayer.input_shapelayer.output_shape如果該層有多個(gè)計(jì)算節(jié)點(diǎn)(參考層計(jì)算節(jié)點(diǎn)和共享層)??梢允褂孟旅娴姆椒āayer.get_input_at(node_index)layer.get_output_at(node_index)layer.get_input_shape_at(node_index)layer.get_output_shape_at(node_index)Dense層Dense就是常用的全連接層,所實(shí)現(xiàn)的運(yùn)算是output=activation(dot(input,kernel)+bias)。其中activation是逐元素計(jì)算的激活函數(shù),kernel是本層的權(quán)值矩陣,bias為偏置向量,只有當(dāng)use_bias=True才會(huì)添加。keras.layers.core.Dense(units,activation=None,use_bias=True,keras.layers.core.Dense(units,activation=None,use_bias=True,kernel_initializer='glorot_unif如果本層的輸入數(shù)據(jù)的維度大于2,則會(huì)先被壓為與kernel相匹配的大小。這里是一個(gè)使用示例,將16個(gè)節(jié)點(diǎn)的層全連接到32個(gè)節(jié)點(diǎn):#asfirstlayerinasequential#asfirstlayerinasequentialmodel:model=Sequential()model.add(Dense(32,input_shape=(16,)))#nowthemodelwilltakeasinputarraysofshape(*,16)#andoutputarraysofshape(*,32)參數(shù)units:大于0的整數(shù),代表該層的輸出維度。activation:激活函數(shù),為預(yù)定義的激活函數(shù)名(參考激活函數(shù)),或逐元素(element-wise)的Theano函數(shù)。如果不指定該參數(shù),將不會(huì)使用任何激活函數(shù)(即使用線性激活函數(shù):a(x)=x)。use_bias:布爾值,是否使用偏置項(xiàng)。kernel_initializer:權(quán)值初始化方法,為預(yù)定義初始化方法名的字符串,或用于初始化權(quán)重的初始化器。參考initializers。bias_initializer:權(quán)值初始化方法,為預(yù)定義初始化方法名的字符串,或用于初始化權(quán)重的初始化器。參考initializers。kernel_regularizer:kernal權(quán)重向量的正則化函數(shù),是Regularizer對(duì)象。bias_regularizer:bias偏置向量的正則化函數(shù),是Regularizer對(duì)象。activity_regularizer:輸出函數(shù)或激活函數(shù)的正則化函數(shù),為Regularizer對(duì)象。kernel_constraints:kernal權(quán)重向量的約束函數(shù),是Constraints對(duì)象。bias_constraints:bias偏移向量的約束函數(shù),是Constraints對(duì)象。kernel_regularizer,bias_regularizer,activity_regularizer,kernel_constraints,bias_constraints這些參數(shù)一般都使用默認(rèn)值,不需要專門設(shè)置。輸入形如(nb_samples,...,input_shape[1])的nD張量,最常見的情況為(nb_samples,input_dim)的2D張量。輸出形如(nb_samplesunits)的nD張量,最常見的情況為(nb_samplesoutput_dim)的2D張量。Activation層Activation層用于設(shè)置激活函數(shù),激活函數(shù)用于在模型中引入非線性。激活函數(shù)sigmoid與tanh曾經(jīng)很流行,但現(xiàn)在很少用于視覺模型了,主要原因在于當(dāng)輸入的絕對(duì)值較大時(shí),其導(dǎo)數(shù)接近于零,梯度的反向傳播過程將被中斷,出現(xiàn)梯度消散的現(xiàn)象。ReLU是一個(gè)很好的替代:相比于sigmoid與tanh,它有兩個(gè)優(yōu)勢(shì):沒有飽和問題,大大緩解了梯度消散的現(xiàn)象,加快了收斂速度。實(shí)現(xiàn)起來非常簡單,加速了計(jì)算過程。ReLU有一個(gè)缺陷,就是它可能會(huì)永遠(yuǎn)“死”掉:X(x1,x2)x1:[0,1x2:[0,1]W(w1,w2)XReLU。F=w1*x1+w2*x2w1w21X如何取值,F(xiàn)ReLUF的導(dǎo)ReLU節(jié)點(diǎn)將永遠(yuǎn)不參與整個(gè)模型的學(xué)習(xí)過程。造成上述現(xiàn)象的原因是ReLU在負(fù)區(qū)間的導(dǎo)數(shù)為零,為了解決這一問題,人們發(fā)明了LeakyReLU,ParametricReLU,RandomizedReLU等變體。他們的中心思想都是為ReLU函數(shù)在負(fù)區(qū)間賦予一定的斜率,從而讓其導(dǎo)數(shù)不為零(這里設(shè)斜率為alpha)。LeakyReLU就是直接給alpha指定一個(gè)值,整個(gè)模型都用這個(gè)斜率:ParametricReLU將alpha作為一個(gè)參數(shù),通過學(xué)習(xí)獲取它的最優(yōu)值。RandomizedReLU為alpha規(guī)定一個(gè)區(qū)間,然后在區(qū)間內(nèi)隨機(jī)選取alpha的值。在實(shí)踐中,ParametricReLU和RandomizedReLU都是可取的。Keras中設(shè)置激活函數(shù)使用下列方法:keras.layers.core.Activation(activation)keras.layers.core.Activation(activation)參數(shù)Tensorflow/Theano的函數(shù)??蛇x值包括:tanh,relu,elu,softsign,linear,softmax等等,具體可參考預(yù)定義激活函數(shù)。輸入shape任意,當(dāng)使用激活層作為第一層時(shí),要指定input_shape輸出shape與輸入shape相同。預(yù)定義激活函數(shù)softmax:對(duì)輸入數(shù)據(jù)的最后一維進(jìn)行softmax,輸入數(shù)據(jù)應(yīng)形如(nb_samples,nb_timesteps,nb_dims)或(nb_samples,nb_dims)elusoftplussoftsignrelutanhsigmoidhard_sigmoidlinear高級(jí)激活函數(shù)對(duì)于簡單的Theano/TensorFlow不能表達(dá)的復(fù)雜激活函數(shù),如含有可學(xué)習(xí)參數(shù)的激活函數(shù),可通過高級(jí)激活函數(shù)實(shí)現(xiàn),如PReLU,LeakyReLU等。Dropout層keras.layers.core.Dropout(rate,noise_shape=None,seed=None)keras.layers.core.Dropout(rate,noise_shape=None,seed=None)為輸入數(shù)據(jù)施加Dropout。Dropout將在訓(xùn)練過程中每次更新參數(shù)時(shí)隨機(jī)斷開一定百分比(rate)的輸入神經(jīng)元,Dropout層用于防止過擬合。參數(shù)的浮點(diǎn)數(shù),控制需要斷開的神經(jīng)元的比例。noise_shape:整數(shù)張量,為將要應(yīng)用在輸入上的二值Dropoutmask的shape,例如你的輸入為(batch_sizetimestepsfeatures),并且你希望在各個(gè)時(shí)間步上的Dropoutmask都相同,則可傳入noise_shape=(batch_size1,features)。seed:整數(shù),使用的隨機(jī)數(shù)種子。Flatten層keras.layers.core.Flatten()keras.layers.core.Flatten()Flatten層用來將輸入“壓平”,即把多維的輸入一維化,常用在從卷積層到全連接層的過渡。Flatten不影響batch的大小。例子model=Sequential()model.add(Convolution2D(64,3,3,model=Sequential()model.add(Convolution2D(64,3,3,border_mode='same',input_shape=(3,32,32)))#now:model.output_shape==(None,64,32,32)model.add(Flatten())#now:model.output_shape==(None,65536)卷積操作將(3,32,32)格式的圖像數(shù)據(jù)轉(zhuǎn)換成(64,32,32)格式,F(xiàn)latten的結(jié)果則是64*32*32=65536。Reshape層keras.layers.core.Reshape(target_shape)keras.layers.core.Reshape(target_shape)Reshape層用來將輸入shape重新轉(zhuǎn)換為特定大小的shape。參數(shù)shape,為整數(shù)的tuple,不包含樣本數(shù)目的維度(batch大?。?。輸入shape任意,但輸入的shape必須固定。當(dāng)使用該層為模型首層時(shí),需要指定input_shape輸出shape(batch_size,)+target_shape例子model=Sequential()model=Sequential()model.add(Reshape((3,4),input_shape=(12,)))model.add(Reshape((6,2)))model.add(Reshape((-1,2,2)))#now:model.output_shape==(None,3,2,2)Permute層keras.layers.core.Permute(dims)keras.layers.core.Permute(dims)Permute層將輸入的維度按照給定模式進(jìn)行重排,例如,當(dāng)需要將RNN和CNN網(wǎng)絡(luò)連接時(shí),可能會(huì)用到該層。參數(shù)dims:整數(shù)tuple,指定重排的模式,不包含樣本數(shù)的維度。重拍模式的下標(biāo)從1開始。例如(2,1)代表將輸入的第二個(gè)維度重拍到輸出的第一個(gè)維度,而將輸入的第一個(gè)維度重排到第二個(gè)維度。例子model=Sequential()model.add(Permute((2,1),input_shape=(10,64)))這時(shí)候model.output_shape等于(None,64,10)。輸入shape任意,當(dāng)使用激活層作為第一層時(shí),要指定input_shape輸出shape與輸入相同,但是其維度按照指定的模式重新排列。RepeatVector層keras.layers.core.RepeatVector(n)keras.layers.core.RepeatVector(n)RepeatVector層將輸入重復(fù)n次。參數(shù)n輸入shape形如(nb_samplesfeatures)的2D張量。輸出shape形如(nb_samples,n,features)的3D張量。例子model=Sequential()model.add(Dense(32,input_dim=32))model=Sequential()model.add(Dense(32,input_dim=32))#這時(shí)候model.output_shape等于(None,32)。#繼續(xù)執(zhí)行:model.add(RepeatVector(3))#執(zhí)行完之后model.output_shape等于(None,3,32)Lambda層keras.layers.core.Lambda(function,output_shape=None,mask=None,arguments=None)keras.layers.core.Lambda(function,output_shape=None,mask=None,arguments=None)本函數(shù)對(duì)上一層的輸出施以任意Theano/TensorFlow表達(dá)式。參數(shù)function:要施加的函數(shù),該函數(shù)僅接受一個(gè)變量,即上一層的輸出。shape,可以是一個(gè)tuple,也可以是一個(gè)根據(jù)輸入shape計(jì)算得出輸出shape的函數(shù)。mask:掩膜。arguments:可選,字典,用來記錄向函數(shù)中傳遞的其他關(guān)鍵字參數(shù)。例子#addax->x^2layermodel.add(Lambda(lambdax:x**2))#addax->x^2layermodel.add(Lambda(lambdax:x**2))#addalayerthatreturnstheconcatenation#ofthepositivepartoftheinputand#theoppositeofthenegativepartdefantirectifier(x):x-=K.mean(x,axis=1,keepdims=True)x=K.l2_normalize(x,axis=1)pos=K.relu(x)neg=K.relu(-x)returnK.concatenate([pos,neg],axis=1)defantirectifier_output_shape(input_shape):shape=list(input_shape)assertlen(shape)==2#onlyvalidfor2Dtensorsshape[-1]*=2returntuple(shape)model.add(Lambda(antirectifier,output_shape=antirectifier_output_shape))輸入shape任意,當(dāng)使用該層作為第一層時(shí),要指定input_shape輸出shape由output_shape參數(shù)指定的輸出shape,當(dāng)使用tensorflow時(shí)可自動(dòng)推斷。卷積層以下內(nèi)容來自于Keras官網(wǎng),為簡單起見,本書只討論1D和2D卷積,并且舉一個(gè)2D卷積的例子。其他卷積方式可參考官網(wǎng)文檔。什么叫卷積?比如(3,3)卷積,其含義就是每次將3*3=9個(gè)特征值根據(jù)卷積算法合并成一個(gè)特征值,常用的卷積算法有以下幾種:平均值:取9個(gè)特征值的平均值作為新的特征值。最大值:取9個(gè)特征值中最大值作為新的特征值。最小值:取9個(gè)特征值中最小值作為新的特征值。當(dāng)然還可以有其他類型的卷積算法。卷積的時(shí)候還有個(gè)重要的概念就是步長,用參數(shù)strides表示。下面舉例說明:如果步長是(1,1),那么第一個(gè)卷積從[0,0]到[2,2]這9個(gè)特征合并成一個(gè)值,下一次卷積從[1,1]到[3,3],對(duì)于9*9大小的矩陣,全部卷積后就是7*7大小的矩陣。Conv1D層keras.layers.convolutional.Conv1D(filters,kernel_size,strides=1,padding='valid',keras.layers.convolutional.Conv1D(filters,kernel_size,strides=1,padding='valid',dilation_r一維卷積層(即時(shí)域卷積),作用是在一維輸入信號(hào)上進(jìn)行鄰域?yàn)V波。當(dāng)使用該層作為首層時(shí),需要提供關(guān)鍵參數(shù)input_shape。例如(10,128)代表一個(gè)長為10的序列,序列中每個(gè)信號(hào)為128向量。而(None,128)代表變長的128維向量序列。該層將輸入信號(hào)與卷積核按照單一的空域(或時(shí)域)方向進(jìn)行卷積。如果use_bias=True,則還會(huì)加上一個(gè)偏置項(xiàng),若activation不為None,則輸出為經(jīng)過激活函數(shù)的輸出。參數(shù)filters:卷積核的數(shù)目(即輸出的維度)。kernel_size:整數(shù)或由單個(gè)整數(shù)構(gòu)成的list/tuple,卷積核的空域或時(shí)域窗長度。strides:整數(shù)或由單個(gè)整數(shù)構(gòu)成的list/tuple,為卷積的步長。任何不為1的滑動(dòng)窗口。paddin

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論