本文將會介紹如何利用Keras來實現(xiàn)模型的保存、讀取以及加載。
本文使用的模型為解決IRIS數(shù)據(jù)集的多分類問題而設計的深度神經網絡(DNN)模型,模型的結構示意圖如下:
DNN模型結構圖
具體的模型參數(shù)可以參考文章:Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題。
模型保存
Keras使用HDF5文件系統(tǒng)來保存模型。模型保存的方法很容易,只需要使用save()方法即可。
以Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題中的DNN模型為例,整個模型的變量為model,我們設置模型共訓練10次,在原先的代碼中加入Python代碼即可保存模型:
????#?save?model
????print("Saving?model?to?disk?\n")
????mp?=?"E://logs/iris_model.h5"
????model.save(mp)
保存的模型文件(.h5)如下:
模型文件
模型讀取
保存后的.h5以HDF5文件系統(tǒng)的形式儲存,在我們使用Python讀取h5文件里面的數(shù)據(jù)之前,我們先用HDF5的可視化工具HDFView來查看里面的數(shù)據(jù):
我們感興趣的是這個模型中的各個神經層之間的連接權重及偏重,也就是上圖中的紅色部分,里面包含了各個神經層之間的連接權重及偏重,分別位于dense_1,dense_2,dense_3中。藍色部分為dense_3/dense_3/kernel:0的數(shù)據(jù),即最后輸出層的連接權重矩陣。
有了對模型參數(shù)的直觀認識,我們要做的下一步工作就是讀取各個神經層之間的連接權重及偏重。我們使用Python的h5py這個模塊來這個.h5這個文件。關于h5py的快速入門指南,可以參考文章:h5py快速入門指南()。
使用以下Python代碼可以讀取各個神經層之間的連接權重及偏重數(shù)據(jù):
import?h5py
#?模型地址
MODEL_PATH?=?'E://logs/iris_model.h5'
#?獲取每一層的連接權重及偏重
print("讀取模型中...")
with?h5py.File(MODEL_PATH,?'r')?as?f:
????dense_1?=?f['/model_weights/dense_1/dense_1']
????dense_1_bias?=??dense_1['bias:0'][:]
????dense_1_kernel?=?dense_1['kernel:0'][:]
????dense_2?=?f['/model_weights/dense_2/dense_2']
????dense_2_bias?=?dense_2['bias:0'][:]
????dense_2_kernel?=?dense_2['kernel:0'][:]
????dense_3?=?f['/model_weights/dense_3/dense_3']
????dense_3_bias?=?dense_3['bias:0'][:]
????dense_3_kernel?=?dense_3['kernel:0'][:]
print("第一層的連接權重矩陣:\n%s\n"%dense_1_kernel)
print("第一層的連接偏重矩陣:\n%s\n"%dense_1_bias)
print("第二層的連接權重矩陣:\n%s\n"%dense_2_kernel)
print("第二層的連接偏重矩陣:\n%s\n"%dense_2_bias)
print("第三層的連接權重矩陣:\n%s\n"%dense_3_kernel)
print("第三層的連接偏重矩陣:\n%s\n"%dense_3_bias)
輸出的結果如下:
讀取模型中...
第一層的連接權重矩陣:
[[?0.04141677??0.03080632?-0.02768146??0.14334357??0.06242227]
?[-0.41209617?-0.77948487??0.5648218??-0.699587???-0.19246106]
?[?0.6856315???0.28241938?-0.91930366?-0.07989818??0.47165248]
?[?0.8655262???0.72175753??0.36529952?-0.53172135??0.26573092]]
第一層的連接偏重矩陣:
[-0.16441862?-0.02462054?-0.14060321??0.?????????-0.14293939]
第二層的連接權重矩陣:
[[?0.39296603??0.01864707??0.12538083??0.07935872??0.27940807?-0.4565802?]
?[-0.34312084??0.6446907??-0.92546445?-0.00538039??0.95466876?-0.32819661]
?[-0.7593299??-0.07227057??0.20751365??0.40547106??0.35726753??0.8884158?]
?[-0.48096?????0.11294878?-0.29462305?-0.410536???-0.23620337?-0.72703975]
?[?0.7666149??-0.41720924??0.29576775?-0.6328017???0.43118536??0.6589351?]]
第二層的連接偏重矩陣:
[-0.1899569???0.?????????-0.09710662?-0.12964155?-0.26443157??0.6050924?]
第三層的連接權重矩陣:
[[-0.44450542??0.09977101??0.12196152]
?[?0.14334357??0.18546402?-0.23861367]
?[-0.7284191???0.7859063??-0.878823??]
?[?0.0876545???0.51531947??0.09671918]
?[-0.7964963??-0.16435687??0.49531657]
?[?0.8645698???0.4439873???0.24599855]]
第三層的連接偏重矩陣:
[?0.39192322?-0.1266532??-0.29631865]
值得注意的是,我們得到的這些矩陣的數(shù)據(jù)類型都是numpy.ndarray。
OK,既然我們已經得到了各個神經層之間的連接權重及偏重的數(shù)據(jù),那我們能做什么呢?當然是去做一些有趣的事啦,那就是用我們自己的方法來實現(xiàn)新數(shù)據(jù)的預測向量(softmax函數(shù)作用后的向量)。so, really?
新的輸入向量為[6.1, 3.1, 5.1, 1.1],使用以下Python代碼即可輸出新數(shù)據(jù)的預測向量:
import?h5py
import?numpy?as?np
#?模型地址
MODEL_PATH?=?'E://logs/iris_model.h5'
#?獲取每一層的連接權重及偏重
print("讀取模型中...")
with?h5py.File(MODEL_PATH,?'r')?as?f:
????dense_1?=?f['/model_weights/dense_1/dense_1']
????dense_1_bias?=??dense_1['bias:0'][:]
????dense_1_kernel?=?dense_1['kernel:0'][:]
????dense_2?=?f['/model_weights/dense_2/dense_2']
????dense_2_bias?=?dense_2['bias:0'][:]
????dense_2_kernel?=?dense_2['kernel:0'][:]
????dense_3?=?f['/model_weights/dense_3/dense_3']
????dense_3_bias?=?dense_3['bias:0'][:]
????dense_3_kernel?=?dense_3['kernel:0'][:]
#?模擬每個神經層的計算,得到該層的輸出
def?layer_output(input,?kernel,?bias):
????return?np.dot(input,?kernel)?+?bias
#?實現(xiàn)ReLU函數(shù)
relu?=?np.vectorize(lambda?x:?x?if?x?>=0?else?0)
#?實現(xiàn)softmax函數(shù)
def?softmax_func(arr):
????exp_arr?=?np.exp(arr)
????arr_sum?=?np.sum(exp_arr)
????softmax_arr?=?exp_arr/arr_sum
????return?softmax_arr
#?輸入向量
unkown?=?np.array([[6.1,?3.1,?5.1,?1.1]],?dtype=np.float32)
#?第一層的輸出
print("模型計算中...")
output_1?=?layer_output(unkown,?dense_1_kernel,?dense_1_bias)
output_1?=?relu(output_1)
#?第二層的輸出
output_2?=?layer_output(output_1,?dense_2_kernel,?dense_2_bias)
output_2?=?relu(output_2)
#?第三層的輸出
output_3?=?layer_output(output_2,?dense_3_kernel,?dense_3_bias)
output_3?=?softmax_func(output_3)

#?最終的輸出的softmax值
np.set_printoptions(precision=4)
print("最終的預測值向量為:?%s"%output_3)
其輸出的結果如下:
讀取模型中...
模型計算中...
最終的預測值向量為:?[[0.0242?0.6763?0.2995]]
額,這個輸出的預測值向量會是我們的DNN模型的預測值向量嗎?這時候,我們就需要回過頭來看看Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題中的代碼了,注意,為了保證數(shù)值的可比較性,筆者已經將DNN模型的訓練次數(shù)改為10次了。讓我們來看看原來代碼的輸出結果吧:
Using?model?to?predict?species?for?features:?
[[6.1?3.1?5.1?1.1]]
Predicted?softmax?vector?is:?
[[0.0242?0.6763?0.2995]]
Predicted?species?is:?
Iris-versicolor
Yes,兩者的預測值向量完全一致!因此,我們用自己的方法也實現(xiàn)了這個DNN模型的預測功能,棒!
模型加載
當然,在實際的使用中,我們不需要再用自己的方法來實現(xiàn)模型的預測功能,只需使用Keras給我們提供好的模型導入功能(keras.models.())即可。使用以下Python代碼即可加載模型
????#?模型的加載及使用
????from?keras.models?import?load_model
????print("Using?loaded?model?to?predict...")
????load_model?=?load_model("E://logs/iris_model.h5")
????np.set_printoptions(precision=4)
????unknown?=?np.array([[6.1,?3.1,?5.1,?1.1]],?dtype=np.float32)
????predicted?=?load_model.predict(unknown)
????print("Using?model?to?predict?species?for?features:?")
????print(unknown)
????print("\nPredicted?softmax?vector?is:?")
????print(predicted)
????species_dict?=?{v:?k?for?k,?v?in?Class_dict.items()}
????print("\nPredicted?species?is:?")
????print(species_dict[np.argmax(predicted)])
輸出結果如下:
Using?loaded?model?to?predict...
Using?model?to?predict?species?for?features:?
[[6.1?3.1?5.1?1.1]]
Predicted?softmax?vector?is:?
[[0.0242?0.6763?0.2995]]
Predicted?species?is:?
Iris-versicolor
總結
本文主要介紹如何利用Keras來實現(xiàn)模型的保存、讀取以及加載。
本文將不再給出完整的Python代碼,如需完整的代碼,請參考Github地址:
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。