1. 程式人生 > >深度學習【3】keras:儲存keras學習好的深度神經網路模型引數為二進位制和txt檔案

深度學習【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)