Keras 介紹

by allenlu2007

 

Reference:  一份不負責任的Keras介紹

 

Keras:宏觀特性Keras是最近蒸蒸日上的深度學習框架, 非常的蒸蒸日上,5月的時候有這麼個圖:

NewImage

Caffe是老牌選手,Tensorflow有個神爹Google,不跟這倆比Keras的表現還是十分亮眼的,我想現在如果有排名也會一樣出色(注意mxnet是萬年老5雖然我一直覺得mxnet其實非常出色……)

那麼,Keras有啥特點呢,我想下面這些可能是屬於Keras的關鍵詞:

  • 符號主義
  • Python
  • 快速原型
  • 輕量級,高度模塊化
  • 易擴展 

Keras事實上是一個基於Theano和Tensorflow上的一個包裝,所謂站在巨人的肩膀上也不外如是了。 因為Theano和Tensorflow都是符號主義的東西(下面講再說這是啥),因此Keras自然也是符號主義的。

Keras由純Python編寫,這意味著它的原始碼簡單易懂,你可以隨時進去看看它都做了什麼,怎麼做的。並且,當你需要修改原始碼的時候,大膽修改就可以了,它會立刻生效。儘管Python的運行效率要低於C++,但Keras只是Tensorflow和Theano的包裝而已,這層包裝的運行代價是很小的。

Keras是一款高度模塊化的框架,使用它搭建網絡和訓練網絡將會非常容易,如果你需要深入模型中控制細節,通常使用Keras提供的一些函數就可以了,很少需要深入到Tensorflow或Theano那一層。因此,Keras適合於快速原型生成,如果你經常需要很快的實現一下自己的idea,Keras會是一個不錯的選擇。

另外,Keras的預訓練模型庫也在逐步建設,目前有VGG-16,VGG-19,resnet50,Inceptionv3四種預訓練好的模型供大家使用。

計算圖,符號主義和張量

符號主義,Google一下會發現是一個機器學習的名詞,但我們這說的符號主義不是那個東西,這裡說的符號主義,指的是使用符號式編程的一種方法。 另一種相對的方法是命令式編程。或者是

要說Theano/Tensorflow/Keras,就不能不提它的符號主義特性

事實上,Theano也好,Tensorflow也好,其實是一款符號主義的計算框架,未必是專為深度學習設計的。假如你有一個與深度學習完全無關的計算任務想運行在GPU上,你完全可以通過Theano/Tensorflow編寫和運行。

假如我們要求兩個數a和b的和,通常只要把值賦值給a和b,然後計算a+b就可以了,正常人類都是這麼寫的:

a=3
b=5
z = a + b

運行到第一行,a真的是3.運行到第2行,b真的是5,然後運行第三行,電腦真的把a和b的值加起來賦給z了。

一點兒都不神奇。

但總有不正常的,不正常的會這麼想問題:a+b這個計算任務,可以分為三步。(1)聲明兩個變量a,b。建立輸出變量z(2)確立a,b和z的計算關係,z=a+b(3)將兩個數值a和b賦值到變量中,計算結果z

後面那種「先確定符號以及符號之間的計算關係,然後才放數據進去計算」的辦法,就是符號式編程 (latent instantiate)。當你聲明a和b時,它們裡面是空的。當你確立z=a+b的計算關係時,a,b和z仍然是空的,只有當你真的把數據放入a和b了,程序才開始做計算。

符號之間的運算關係,就稱為運算圖。

這樣做當然不是閒的無聊,符號式計算的一大優點是,當確立了輸入和輸出的計算關係後,在進行運算前我們可以對這種運算關係進行自動化簡,從而減少計算量,提高計算速度。另一個優勢是,運算圖一旦確定,整個計算過程就都清楚了,可以用內存復用的方式減少程序占用的內存。

在Keras,theano和Tensorflow中,參與符號運算的那些變量統一稱作張量。張量是矩陣的進一步推廣。

規模最小的張量是0階張量,即標量,也就是一個數。

當我們把一些數有序的排列起來,就形成了1階張量,也就是一個向量

如果我們繼續把一組向量有序的排列起來,就形成了2階張量,也就是一個矩陣

把矩陣摞起來,就是3階張量,我們可以稱為一個立方體,具有3個顏色通道的彩色圖片就是一個這樣的立方體

把矩陣摞起來,好吧這次我們真的沒有給它起別名了,就叫4階張量了,不要去試圖想像4階張量是什麼樣子,它就是個數學上的概念。

一言以蔽之,Keras的計算過程,就是建立一個從張量到張量的映射函數,然後再放入真實數據進行計算。對深度學習而言,這個「映射函數」就是一個神經網絡,而神經網絡中的每個層自然也都是從張量到張量的映射。

Keras框架結構

我想畫一個圖,可是想了半天畫不明白……我就羅列就好了,Keras的結構大致是這樣的:

  • backend:後端,對Tensorflow和Theano進行封裝,完成低層的張量運算、計算圖編譯等
  • models:模型,模型是層的有序組合,也是層的「容器」,是「神經網絡」的整體表示
  • layers:層,神經網絡的層本質上規定了一種從輸入張量到輸出張量的計算規則,顯然,整個神經網絡的模型也是這樣一種張量到張量的計算規則,因此keras的model是layer的子類

上面的三個模塊是Keras最為要緊和核心的三塊內容,搭建一個神經網絡,就只用上面的內容即可。注意的是,backend雖然很重要,但其內容多而雜,大部分內容都是被其他keras模塊調用,而不是被用戶直接使用。所以它不是新手馬上就應該學的,初學Keras不妨先將backend放一旁,從model和layers學起。

為了訓練神經網絡,必須定義一個神經網絡優化的目標和一套參數更新的方式,這部分就是目標函數和優化器:

  • objectives:目標函數,規定了神經網絡的優化方向
  • optimizers:優化器,規定了神經網絡的參數如何更新

上面的兩個模塊的內容,是在訓練一個網絡時必須提供的。此外,Keras提供了一組模塊用來對神經網絡進行配置:

  • initialization:初始化策略,規定了網絡參數的初始化方法
  • regularizers:正則項,提供了一些用於參數正則的方法,以對抗過擬合
  • constraints:約束項,提供了對網絡參數進行約束的方法

為了方便調試、分析和使用網絡,處理數據,Keras提供了下面的模塊:

  • callbacks:回調函數,在網絡訓練的過程中返回一些預定義/自定義的信息
  • visualization:可視化,用於將網絡結構繪製出來,以直觀觀察
  • preprocessing:提供了一組用於對文本、圖像、序列信號進行預處理的函數
  • utils:常用函數庫,比較重要的是utils.np_utils中的to_categorical,用於將1D標籤轉為one-hot的2D標籤和convert_kernel函數,用於將卷積核在theano模式和Tensorflow模式之間轉換。最新的代碼顯示utils的utils.layer_utils里提供了將模型中全部卷積核進行模式轉換的函數。大部分其他utils的函數你或許很難用到,但有空不妨一讀,或有進益。

最後,為了能讓用戶一上手就能跑一些模型,Keras提供了一個常用資料庫的模塊,用來載入常用的資料庫:

  • datasets:提供了一些常用資料庫的接口,用戶將通過這些接口下載和載入數據集

額外的一點是,如果用戶希望將Keras與scikit-learn聯動,Keras也提供了這種聯動機制,這個模塊是:

  • wrappers.scikit-learn

上回書我們簡單的把Keras的框架理了一下,下面我們深入(也不怎麼深)具體的模塊理一下Keras,主要聊一聊每個模塊的具體功能和核心函數

backend:百貨商店

backend這個模塊的主要作用,是對tensorflow和theano的底層張量運算進行了包裝。用戶不用關心具體執行張量運算的是theano還是tensorflow,就可以編寫出能在兩個框架下可以無縫對接的程序。backend中的函數要比文檔里給出的多得多,完全就是一家百貨商店。但一般情況下,文檔里給出的那些就已經足夠你完成大部分工作了,事實上就連文檔里給出的函數大部分情況也不會用,這裡提幾個比較有用的函數——當然是對我來說比較有用,畢竟這是一份不怎麼負責任的介紹,如果你想找對你有用的函數,就去backend淘一淘吧~:

  • function:毫無疑問這估計是最有用的一個函數了,function用於將一個計算圖(計算關係)編譯為具體的函數。典型的使用場景是輸出網絡的中間層結果。
  • image_ordering和set_image_ordering:這組函數用於返回/設置圖片的維度順序,由於Theano和Tensorflow的圖片維度順序不一樣,所以有時候需要獲取/指定。典型應用是當希望網絡自適應的根據使用的後端調整圖片維度順序時。
  • learning_phase:這個函數的主要作用是返回網絡的運行狀態,0代表測試,1代表訓練。當你需要便攜一個在訓練和測試是行為不同的層(如Dropout)時,它會很有用。
  • int_shape:這是我最常用的一個函數,用於以整數tuple的形式返回張量的shape。要知道從前網絡輸出張量的shape是看都看不到的,int_shape可以在debug時起到很大作用。
  • gradients: 求損失函數關於變量的導數,也就是網絡的反向計算過程。這個函數在不訓練網絡而只想用梯度做一點奇怪的事情的時候會很有用,如圖像風格轉移。

backend的其他大部分函數的函數名是望而知義的,什麼max,min,equal,eval,zeros,ones,conv2d等等。函數的命名方式跟numpy差不多,下次想用時不妨先『.』一下,說不定就有。

models/layers:Keras的核心主題

使用Keras最常見的目的,當然還是訓練一個網絡。之前說了網絡就是張量到張量的映射,所以Keras的網絡,其實是一個由多個子計算圖構成的大計算圖。當這些子計算圖是順序連接時,稱為Sequential,否則就是一般的model,我們稱為泛型模型。

模型不但是張量的計算方式,還是層對象的容器,模型用來將它所含有的層整合起來,大家手拉手一起走

模型有兩套訓練和測試的函數,一套是fit,evaluate等,另一套是fit_generator,evaluate_generator,前者適用於普通情況,後者適用於數據是以疊代器動態生成的情況。疊代器可以在內存/顯存不足,實時動態數據提升進行網絡訓練,所以使用Keras的話,Python的疊代器這一部分是一定要掌握的內容。對模型而言,最核心的函數有兩個:

  • compile:編譯,模型在訓練前必須編譯,這個函數用於完成添加正則項啊,確定目標函數啊,確定優化器啊等等一系列模型配置功能。這個函數必須指定的參數是優化器和目標函數,經常還需要指定一個metrics來評價模型。

  • fit/fit_generator:用來訓練模型,參數較多,是需要重點掌握的函數,對於keras使用者而言,這個函數的每一個參數都需要掌握。

其他的函數請自己學習。

另外,模型還有幾個常用的屬性和函數:

  • layers:該屬性是模型全部層對象的列表,是的就是一個普通的python list
  • get_layer:這個函數通過名字來返回模型中某個層對象
  • pop:這個函數文檔里沒有,但是可以用。作用是彈出模型的最後一層,從前進行finetune時沒有pop,大家一般用model.layers.pop來完成同樣的功能。

當然,因為Model是Layer的子類,Layer的所有屬性和方法也自動被Model所有,這些有用的屬性稍後介紹。

Keras的層對象是構築模型的基石,除了卷積層,遞歸神經網絡層,全連接層,激活層這種爛大街的Layer對象外,Keras還有一些不是那麼爛大街的東西:

  • Adacanced Activation:高級激活層,主要收錄了包括leakyReLU,pReLU,ELU,SReLU等一系列高級激活函數,這些激活函數不是簡單的element-wise計算,所以單獨拿出來實現一下
  • Merge層:這個層用於將多個層對象的輸出組合起來,支持級聯、乘法、餘弦等多種計算方式,它還有個小兄弟交merge,這個函數完成與Merge相同的作用,但輸入的對象是張量而不是層對象。
  • Lambda層:這是一個神奇的層,看名字就知道它用來把一個函數作用在輸入張量上。這個層可以大大減少你的工作量,當你需要定義的新層的計算不是那麼複雜的時候,可以通過lambda層來實現,而不用自己完全重寫。
  • Highway/Maxout/AtrousConvolution2D層:這個就不多說了,懂的人自然懂,keras還是在一直跟著潮流走的
  • Wrapper層:Wrapper層用於將一個普通的層對象進行包裝升級,賦予其更多功能。目前,Wrapper層里有一個TimeDistributed層,用於將普通的層包裝為對時間序列輸入處理的層,而BiDirectional(這個層還沒發布,只能在github中看到)可以將輸入的遞歸神經網絡層包裝為雙向的(如把LSTM做成BLSTM)
  • Input:補一個特殊的層,Input,這個東西實際上是一個Keras tensor的占位符,主要用於在搭建Model模型時作為輸入tensor使用,這個Input可以通過keras.layers來import。
  • stateful與unroll:Keras的遞歸神經網絡層,如SimpleRNN,LSTM等,支持兩種特殊的操作。一種是stateful,設置stateful為True意味著訓練時每個batch的狀態都會被重用於初始化下一個batch的初始狀態。另一種是unroll,unroll可以將遞歸神經網絡展開,以空間換取運行時間。

Keras的層對象還有一些有用的屬性和方法,比較有用的是:

  • name:別小看這個,從茫茫層海中搜索一個特定的層,如果你對數數沒什麼信息,最好是name配合get_layer來用。
  • trainable:這個參數確定了層是可訓練的還是不可訓練的,在遷移學習中我們經常需要把某些層凍結起來而finetune別的層,凍結這個動作就是通過設置trainable來實現的。
  • input/output:這兩個屬性是層的輸入和輸出張量,是Keras tensor的對象,這兩個屬性在你需要獲取中間層輸入輸出時非常有用
  • get_weights/set_weights:這是兩個方法用於手動取出和載入層的參數,set_weights傳入的權重必須與get_weights返回的權重具有同樣的shape,一般可以用get_weights來看權重shape,用set_weights來載入權重

既然是核心主題,我們就多嘮兩句,在Keras中經常有的一個需求是需要自己編寫一個新的層,如果你的計算比較簡單,那可以嘗試通過Lambda層來解決,如果你不得不編寫一個自己的層,那也不是什麼大不了的事兒。前兩天群里有朋友想編寫一個卷積核大小不一樣的卷積層(雖然不知道為啥他這麼想不開……活著不好嗎?),這個顯然就要自己編寫層了。

要在Keras中編寫一個自己的層,需要開一個從Layer(或其他層)繼承的類,除了init以為你需要覆蓋三個函數:

  • build,這個函數用來確立這個層都有哪些參數,哪些參數是可訓練的哪些參數是不可訓練的。

  • call,這個函數在調用層對象是自動使用,裡面就是該層的計算邏輯,或計算圖了。顯然,這個層的核心應該是一段符號式的輸入張量到輸出張量的計算過程。
    get_output_shape_for:如果你的層計算後,輸入張量和輸出張量的shape不一致,那麼你需要把這個函數也重新寫一下,返回輸出張量的shape,以保證Keras可以進行shape的自動推斷

其實也不難~是吧,不要忘記Keras是基於Python的框架,你可以隨時隨地查看那些已經寫好的層的代碼,模仿著看看你自己的層要怎麼寫~

優化器,目標函數,初始化策略,等等…

和model,layers這種核心功能相比,這些模塊的重要性就沒有那麼大,我們簡單介紹一下,裡面的具體技術,(下)篇可能會說,也可能不會……我還沒想好,但是基本上不說也沒什麼影響

objectives是優化目標, 它本質上是一個從張量到數值的函數,當然,是用符號式編程表達的。具體的優化目標有mse,mae,交叉熵等等等等,根據具體任務取用即可,當然,也支持自己編寫。需要特別說明的一點是,如果選用categorical_crossentropy作為目標函數,需要將標籤轉換為one-hot編碼的形式,這個動作通過utils.np_utils.to_categorical來完成(記得上篇我就提過了)

optimizers是優化器,沒什麼可說了,如何選用合適的優化器不在本文討論範疇。注意模型是可以傳入優化器對象的,你可以自己配置一個SGD,然後將它傳入模型中。 另外,最新版本的Keras為所有優化器額外設置了兩個參數clipnorm和clipvalue,用來對梯度進行裁剪。

activation是激活函數,這部分的內容一般不直接使用,而是通過激活層Activation來調用,此處的激活函數是普通的element-wise激活函數,如果想使用高級激活函數,請翻到高級激活函數層。

callback是回調函數,這其實是一個比較重要的模塊,回調函數不是一個函數而是一個類,用於在訓練過程中收集信息或進行某種動作。比如我們經常想畫一下每個epoch的訓練誤差和測試誤差,那這些信息就需要在回調函數中收集。預定義的回調函數中CheckPoint,History和EarlyStopping都是比較重要和常用的。其中CheckPoint用於保存模型,History記錄了訓練和測試的信息,EarlyStopping用於在已經收斂時提前結束訓練。回調函數LearningRateScheduler支持按照用戶的策略調整學習率,做模型精調或研究優化器的同學可能對這個感興趣。

值得注意的是,History是模型訓練函數fit的返回值,也就是說即使你沒有使用任何回調函數,找一個變量接著model.fit,還是能得到不少訓練過程中的有用信息。

另外,回調函數還支持將信息發送到遠程伺服器,以及與Tensorflow的tensorboard聯動,在網頁上動態展示出訓練和測試的情況(需要使用tensorflow為後端)

回調函數支持用戶自定義,定義方法也非常簡單,請參考文檔說明編寫即可

初始化方法,正則項,約束項,可視化沒有什麼特別值得注意的,就略過了。Keras中所有的模塊都是可以用戶自己定義的,這就是開源和Python的魅力,講真你讓我拿C++寫這麼個東西……我光把結構摸清楚就要吐血了!

另一個文檔中沒有但實際上有的東西是metrices,這裡面定義了一系列用於評價模型的指標,例如「accuracy」。在訓練模型時,可以選擇一個或多個指標來衡量模型性能。

數據預處理和utils

數據預處理是Keras提供的用於預處理圖像、文本和序列數據的一套工具,這個地方就屬於各回各家各找各媽了,你處理什麼問題就從這裡面找什麼工具。

特別指出的是,數據預處理的圖像預處理部分,提供了一套用於實時圖像數據提升的工具,這個東西支持用各種各樣的方法對輸入圖像進行數據提升,然後以生成器的形式返回。另外,該工具還支持從文件夾中自動生成數據和標籤,簡直方便的不要不要的。

utils文檔中沒有,裡面包含的函數也不必怎麼了解,除了兩個。一個是說了很多遍的to_catgoraical,另一個是convert_kernel。後者的主要作用是把卷積濾波器的卷積核在th和tf之間互相轉換。theano和tensorflow相愛想殺,到處搞對抗。其中之一就是卷積核,卷積這個東西,按照信號與系統(哼,才不會告訴你們我是信號系統助教咧)的定義,是翻轉->平移->相乘->相加。但反正卷積網絡的卷積核都是訓練出來的,翻轉不翻轉有什麼關係?

所以有些人沒翻轉,有些人翻轉了。是的,說的就是你倆,theano和tensorflow。於是如果一個網絡預訓練權重是由其中一種後端訓練出來的,又要在另一種後端上跑,那麼你就需要用kernel_convert這個函數搞一搞了。

估計這事兒太不地道,作者也看不下去了。現在utils出了一個新的layer_utils,裡面有一個convert_all_kernels_in_model函數,用來把一個模型的所有卷積核全部進行轉換,以後就用這個吧~

與scikit-learn聯動

有人留言說希望多講點這塊的內容,很抱歉……我……我也不怎麼會,原諒我畢竟是一隻菜雞

雖然不怎麼會,但是不妨礙我知道這應該是一個非常重要和有潛力的功能。Keras與scikit-learn的協作通過keras.wrapper實現,在這個腳本里定義了兩個類,分別是KerasClassifier和KerasRegressor,搭建好Sequential模型(只能是Sequential)將被它們包裝為sklearn的分類器和疊代器加入的sklearn的工作流中。

這裡有一個使用sklearn對Keras進行超參數調整的例子,大家可以參考這篇文章學習Keras和sklearn的聯動:Keras/Python深度學習中的網格搜索超參數調優(附源碼)

下篇主要說一下Keras的有用特性,以及一些常見問題,如果還有精力的話,補一些使用Keras的陷阱,沒精力這部分就留到番外篇了。理解這些特性對深入了解Keras有比較重要的幫助。

callable,全部Layer都要callable!

Keras的一大性質是所有的layer對象都是callable的。所謂callable,就是能當作函數一樣來使用,層的這個性質不需要依賴任何模型就能成立。比方說你想算算一個向量x的sigmoid值是多少,如果用keras的話,你可以這樣寫:

importkeras.backendasKfromkeras.layersimportActivationimportnumpyasnp x = K.placeholder(shape=(3,)) y = Activation('sigmoid')(x) f = K.function([x],[y]) out = f([np.array([123])])

很顯然,我絕對不會寫這種代碼來求sigmoid,這個例子只是說明,可以這麼幹,而可以這麼幹的話很多工作就會很方便。比方說有一次我想給目標函數加一項全變差的正則項,而全變差可以用特定的卷積來實現, 那麼我的目標函數的全變差正則項完全就可以用一個Convolution2D層來實現。把層和模型當作張量的函數來使用,是需要認真貫徹落實的一個東西。

順便我們也複習一下上一篇文章說的符號式計算方法。正文第1行先定義了一個「占位符」,它的shape是一個長為3的向量。所謂占位符就是「先占個位置 「的符號,翻譯成中文就是」此處應有一個長為3的向量「。注意第2行,這行我們使用了一個激活層,激活層的激活函數形式是sigmoid,在激活層的後面 又有一個括號,括號內是我們的輸入張量x,可以看到,層對象『Activation(『sigmoid』)』是被當做一個函數來使用的。上篇文章說層就是 張量到張量的運算,那麼其輸出y自然也是一個張量。

第3行通過調用function函數對計算圖進行編譯,這個計算圖很簡單,就是輸入張量經過sigmoid作用變成輸出向量,計算圖的各種優化通過這一步得以完成,現在,f就是一個真正的函數了,就可以按照一般的方法使用了。

之前說了,模型也是張量到張量的映射,所以Layer是Model的父類,因此,一個模型本身也可以像上面一樣使用。總而言之,在Keras中,層對象是callable的。

Node:Keras的網絡層復用

Keras的網絡層復用是一個很常用的需求,例如當某一層與多個層相連時,實際上這層是將同一種計算方式復用多次。再比如你用一個網絡來抽取兩條微博的特徵,然後在後面用網絡來判斷二者是否是同一個主題,那麼抽取兩次微博的特徵這一工作就可以復用同一個網絡。

Keras的網絡復用由一個叫「Node」,或稱「計算節點」的東西來實現。籠統地說,每當在某個輸入上調用層時,就會為網絡層添加一個節點。這個節點將輸入張量映射為輸出的張量,當你多次調用該層,就會產生多個結點,結點的下標是0,1,2,3…

如果僅僅是這樣,這部分的東西你依然不需要了解,問題在於,當一個層有多個計算節點時,它的input,output,input_shape,output_shape等屬性可能是ill-defined的,因為不清楚你想要的output或input是哪一個。

此時,需要使用get_output_at,get_input_at,get_output_shape_at等以at為後綴結尾的函數,at的對象就是層的節點編號。例如get_output_shape_at(2)就會返回第3個輸出張量的shape。

Shape與Shape自動推斷

使用過Keras的都知道,Keras的所有的層有一個「input_shape」的參數,用來指定輸入張量的shape。然而這個input_shape,或者有時候是input_dim,只需要在模型的首層加以指定。一旦模型的首層的input_shape指定了,後面的各層就不用再指定,而會根據計算圖自動推斷。這個功能稱為shape的自動推斷。

Keras的自動推斷依賴於Layer中的get_output_shape_for函數來實現,如果大家還記得上一篇文章的話,在提到如何編寫自己的Keras層時,我們提到如果你的網絡層改變了輸入張量的shape,就應該複寫get_output_shape_for這個函數,以使後面的層能知道本層輸出的shape。

在所有的Keras中都有這樣一個函數,因此後面的層可以通過查看這個函數的返回值獲取前層的輸入shape,並通過自己的get_output_shape_for將這個信息傳遞下去。

然而,有時候,這個自動推斷會出錯。這種情況發生在一個RNN層後面接Flatten然後又接Dense的時候,這個時候Dense的output_shape無法自動推斷出。這時需要指定RNN的輸入序列長度input_length,或者在網絡的第一層通過input_shape就指定。這種情況極少見,大致有個印象即可,遇到的話知道大概是哪裡出了問題就好。

一般而言,神經網絡的數據是以batch為單位的,但在指明input_shape時不需要說明一個batch的樣本數。假如你的輸入是一個224*224*3的彩色圖片,在內部運行時數據的shape是(None,224,224,3),這點在你自己編寫層是需要注意。

TH與TF的相愛相殺

相愛沒有,全是相殺

Keras提供了兩套後端,Theano和Tensorflow,這是一件幸福的事,手中拿著饅頭,想蘸紅糖蘸紅糖,想蘸白糖蘸白糖

th和tf的大部分功能都被backend統一包裝起來了,但二者還是存在不小的衝突,有時候你需要特別注意Keras是運行在哪種後端之上,它們的主要衝突有:

  • dim_ordering,也就是維度順序。比方說一張224*224的彩色圖片,theano的維度順序是(3,224,224),即通道維在前。而tf的維度順序是(224,224,3),即通道維在後。dim_ordering不是一個必須和後端搭配的指標,它只規定了輸入圖片的維度順序,只要輸入圖片按此維度順序設置即可正確運行。然而,如果dim_ordering與後端搭配的話——我指的是所有層的dim_ordering都與後端搭配,會提高程序的運行效率。否則,數據的shape會在計算過程中不斷轉來轉去,效率會低一些。
  • 卷積層權重的shape:從無到有訓練一個網絡,不會有任何問題。但是如果你想把一個th訓練出來的卷積層權重載入風格為tf的卷積層……說多了都是淚。我一直覺得這個是個bug,數據的dim_ordering有問題就罷了,為啥卷積層權重的shape還需要變換咧?我遲早要提個PR把這個bug修掉!
  • 然後是卷積層kernel的翻轉不翻轉問題,這個我們說過很多次了,就不再多提。

總而言之,相愛沒有,全部都是相殺。儘管Keras已經在統一theano和tensorflow上走了很多很多步,但還需要走更多的一些步。

FAQ與學習資料

FAQ模塊請參考這裡:FAQ – Keras中文文檔

另外,在這裡有一些使用示範,包括與TensorFlow的聯動,分布式訓練等:

CNN眼中的世界

花式自動編碼器

面向小數據集構建圖像分類模型

在Keras模型中使用預訓練的詞向量

將Keras作為tensorflow的精簡接口

Keras/Python深度學習中的網格搜索超參數調優(附源碼)

Keras已經開始組建自己的Keras Zoo,也就是預訓練的模型庫,這個github在:

GitHub – fchollet/fchollet/deep-learning-models

關於我們老提的TH和TF的卷積核轉換,這裡是使用示範:

TF kernel – TH kernel

學習Keras最快的方法莫過於直接閱讀示例代碼了,這裡是example:

keras examples

 

 

 

Advertisements