深度學習【3】keras:儲存keras學習好的深度神經網路模型引數為二進位制和txt檔案
http://blog.csdn.net/linmingan/article/details/50906141
由於工程需要,儲存為hdf5的keras權值在c/c++中的讀取比較不方便。因此將keras中的權值剝離出來,並儲存為二進位制檔案或者txt檔案。在進行程式碼的編寫之前我們必須先知道keras中model類對於每一層的引數如何表示的。以下,我將以加入Batch Normalization的5層神經網路(每層的節點數為[500 400 300 200 100],輸入為:39)作為例子,來解讀keras的引數表示。
假設我們已經學習好了上述的神經網路,怎麼我們可以得到一個包含有各種物件的keras物件:model。model的具體內容如下圖(model內部結構的顯示由Pycharm除錯功能中的觀察變數功能得來)。圖中有非常多變數,但是我們只關心其中的layers變數。
我們可以展開layers變數,得到下圖。從_len_={int} 17,知道我們的模型共有17層(按正常理解應該只有5層,但是在keras中,將上一層的輸出乘以該層的權值,以及通過啟用函式這兩個都看做是一層。因為我們的模型加入了BN操作,所有BN操作也看做一層。這樣一來我們理解的一層就擴充套件到了三層。),接下來的00,01,...16就是裡面具體的層的內容了,我們要儲存的引數也都在裡面。
以第一層隱藏層作為例子,來看看裡面具體的內容。第一層隱藏層由00,01,02這三個變數構成,分別展開,得到下面三個圖。可以看到引數W和b都在00層,但在01層也會有記錄(在previous變數中)。02中主要記錄BN中的gamma,beta,running_mean和running_std。其他隱藏層的引數也是這樣的,我們不具體看了。keras中的每一層都是用list型別來表示,其中的元素是TesorType(float32,matrix)或者TesorType(float32,vector)的型別(theano的矩陣和向量型別)。theano提供了對每一層的引數獲得函式get_params(),這個函式能夠從model變數中獲取每一層的引數,也就是我們上面講的list型別。由於獲得後的list中是theano的矩陣和向量,為了進一步得到我們可以觀察的矩陣和向量theano提供了get_value()函式,通過這個函式可以將TesorType(float32,matrix)或者TesorType(float32,vector)轉化為numpy中的ndarray格式的矩陣和向量。這樣就能夠利用numpy提供的二進位制儲存函式tofile()和txt儲存函式savetxt()儲存學習好的神經網路模型引數。
00
01
02
通過上面的分析,我編寫了如下的程式碼,來儲存每一層的W,b,gamma,beta,mean和std。程式碼如下:
model = model_from_json(open('model54321_architecture.json').read()) model.load_weights('model54321_weights.h5') for i in range(2,16,3):#save the BN params param = model.layers[i].get_params() gamma = param[0][0].get_value() #get the gamma beta = param[0][1].get_value() #get the beta mean = param[3][0][0].get_value() #get the mean std = param[3][1][0].get_value() #get the std bn = np.c_[gamma,beta,mean,std] # combine the gamma beta mean std as a n*4 matrix bn_name = str(i)+'bn'+'.txt' np.savetxt(bn_name,bn,fmt='%f') #save as txt bn_name = str(i)+'bn'+'.bin' bn.tofile(bn_name) #save as bin for i in range(0,16,3):#save the W and b var = model.layers[i].get_params() w = var[0][0].get_value() #get W b = var[0][1].get_value() #get b #save as txt w_name = str(i)+'w'+'.txt' np.savetxt(w_name,w,fmt='%f') b_name = str(i)+'b'+'.txt' np.savetxt(b_name,b,fmt='%f') #save as bin w_name = str(i)+'w'+'.bin' w.tofile(w_name) b_name = str(i)+'b'+'.bin' b.tofile(b_name)