1. 程式人生 > 程式設計 >keras小技巧——獲取某一個網路層的輸出方式

keras小技巧——獲取某一個網路層的輸出方式

前言:

keras預設提供瞭如何獲取某一個層的某一個節點的輸出,但是沒有提供如何獲取某一個層的輸出的介面,所以有時候我們需要獲取某一個層的輸出,則需要自己編寫程式碼,但是鑑於keras高層封裝的特性,編寫起來實際上很簡單,本文提供兩種常見的方法來實現,基於上一篇文章的模型和程式碼: keras自定義回撥函式檢視訓練的loss和accuracy

一、模型載入以及各個層的資訊檢視

從前面的定義可知,參見上一篇文章,一共定義了8個網路層,定義如下:

model.add(Convolution2D(filters=6,kernel_size=(5,5),padding='valid',input_shape=(img_rows,img_cols,1),activation='tanh'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Convolution2D(filters=16,2)))
model.add(Flatten())
model.add(Dense(120,activation='tanh'))
model.add(Dense(84,activation='tanh'))
model.add(Dense(n_classes,activation='softmax'))

這裡每一個層都沒有起名字,實際上最好給每一個層取一個名字,所以這裡就使用索引來訪問層,如下:

for index in range(8):
 layer=model.get_layer(index=index)
 # layer=model.layers[index] # 這樣獲取每一個層也是一樣的
 print(model)
 
'''執行結果如下:
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
<keras.engine.sequential.Sequential object at 0x0000012A4F232E10>
'''

當然由於 model.laters是一個列表,所以可以一次性打印出所有的層資訊,即

print(model.layers) # 打印出所有的層

二、模型的載入

準備測試資料

# 訓練引數
learning_rate = 0.001
epochs = 10
batch_size = 128
n_classes = 10
 
# 定義影象維度reshape
img_rows,img_cols = 28,28
 
# 載入keras中的mnist資料集 分為60,000個訓練集,10,000個測試集
(x_train,y_train),(x_test,y_test) = mnist.load_data()
 
# 將圖片轉化為(samples,width,height,channels)的格式
x_train = x_train.reshape(x_train.shape[0],img_rows,1)
x_test = x_test.reshape(x_test.shape[0],1)
 
# 將X_train,X_test的資料格式轉為float32
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# 將X_train,X_test歸一化0-1
x_train /= 255
x_test /= 255
 
# 輸出0-9轉換為ont-hot形式
y_train = np_utils.to_categorical(y_train,n_classes)
y_test = np_utils.to_categorical(y_test,n_classes)

模型的載入

model=keras.models.load_model('./models/lenet5_weight.h5')

注意事項:

keras的每一個層有一個input和output屬性,但是它是隻針對單節點的層而言的哦,否則就不需要我們再自己編寫輸出函數了,

如果一個層具有單個節點 (i.e. 如果它不是共享層),你可以得到它的輸入張量、輸出張量、輸入尺寸和輸出尺寸:

layer.input
layer.output
layer.input_shape
layer.output_shape

如果層有多個節點 (參見: 層節點和共享層的概念),您可以使用以下函式:

layer.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)

三、獲取某一個層的輸出的方法定義

3.1 第一種實現方法

def get_output_function(model,output_layer_index):
 '''
 model: 要儲存的模型
 output_layer_index:要獲取的那一個層的索引
 '''
 vector_funcrion=K.function([model.layers[0].input],[model.layers[output_layer_index].output])
 def inner(input_data):
  vector=vector_funcrion([input_data])[0]
  return vector
 
 return inner
 
# 現在僅僅測試一張圖片
#選擇一張圖片,選擇第一張
x= np.expand_dims(x_test[1],axis=0) #[1,28,1] 的形狀
 
get_feature=get_output_function(model,6) # 該函式的返回值依然是一個函式哦,獲取第6層輸出
 
feature=get_feature(x) # 相當於呼叫 定義在裡面的inner函式
print(feature)
'''執行結果為
[[-0.99986297 -0.9988328 -0.9273474 0.9101525 -0.9054705 -0.95798373
 0.9911243 0.78576803 0.99676156 0.39356467 -0.9724135 -0.74534595
 0.8527011 -0.9968267 -0.9420816 -0.32765102 -0.41667578 0.99942905
 0.92333794 0.7565034 -0.38416263 -0.994241 0.3781617 0.9621943
 0.9443946 0.9671554 -0.01000021 -0.9984282 -0.96650964 -0.9925837
 -0.48193568 -0.9749565 -0.79769516 0.9651831 0.9678705 -0.9444472
 0.9405674 0.97538495 -0.12366439 -0.9973782 0.05803521 0.9159217
 -0.9627071 0.99898154 0.99429387 -0.985909 0.5787794 -0.9789403
 -0.94316894 0.9999644 0.9156823 0.46314353 -0.01582102 0.98359734
 0.5586145 -0.97360635 0.99058044 0.9995654 -0.9800733 0.99942625
 0.8786553 -0.9992093 0.99916387 -0.5141877 0.99970615 0.28427476
 0.86589384 0.7649907 -0.9986046 0.9999706 -0.9892468 0.99854743
 -0.86872625 -0.9997323 0.98981035 -0.87805724 -0.9999373 -0.7842255
 -0.97456616 -0.97237325 -0.729563 0.98718935 0.9992022 -0.5294769 ]]
'''

但是上面的實現方法似乎不是很簡單,還有更加簡單的方法,思想來源與keras中,可以將整個模型model也當成是層layer來處理,實現如下面。

3.2 第二種實現方法

import keras
import numpy as np
from keras.datasets import mnist
from keras.models import Model
 
model=keras.models.load_model('./models/lenet5_weight.h5')
 
#選擇一張圖片,1] 的形狀
 
# 將模型作為一個層,輸出第7層的輸出
layer_model = Model(inputs=model.input,outputs=model.layers[6].output)
 
feature=layer_model.predict(x)
 
print(feature)
'''執行結果為:
[[-0.99986297 -0.9988328 -0.9273474 0.9101525 -0.9054705 -0.95798373
 0.9911243 0.78576803 0.99676156 0.39356467 -0.9724135 -0.74534595
 0.8527011 -0.9968267 -0.9420816 -0.32765102 -0.41667578 0.99942905
 0.92333794 0.7565034 -0.38416263 -0.994241 0.3781617 0.9621943
 0.9443946 0.9671554 -0.01000021 -0.9984282 -0.96650964 -0.9925837
 -0.48193568 -0.9749565 -0.79769516 0.9651831 0.9678705 -0.9444472
 0.9405674 0.97538495 -0.12366439 -0.9973782 0.05803521 0.9159217
 -0.9627071 0.99898154 0.99429387 -0.985909 0.5787794 -0.9789403
 -0.94316894 0.9999644 0.9156823 0.46314353 -0.01582102 0.98359734
 0.5586145 -0.97360635 0.99058044 0.9995654 -0.9800733 0.99942625
 0.8786553 -0.9992093 0.99916387 -0.5141877 0.99970615 0.28427476
 0.86589384 0.7649907 -0.9986046 0.9999706 -0.9892468 0.99854743
 -0.86872625 -0.9997323 0.98981035 -0.87805724 -0.9999373 -0.7842255
 -0.97456616 -0.97237325 -0.729563 0.98718935 0.9992022 -0.5294769 ]]
'''

可見和上面的結果是一樣的,

總結:

由於keras的層與模型之間實際上的轉化關係,所以提供了非常靈活的輸出方法,推薦使用第二種方法獲得某一個層的輸出。總結為以下幾個主要的步驟(四步走):

import keras
import numpy as np
from keras.datasets import mnist
from keras.models import Model
 
# 第一步:準備輸入資料
x= np.expand_dims(x_test[1],1] 的形狀
 
# 第二步:載入已經訓練的模型
model=keras.models.load_model('./models/lenet5_weight.h5')
 
# 第三步:將模型作為一個層,輸出第7層的輸出
layer_model = Model(inputs=model.input,outputs=model.layers[6].output)
 
# 第四步:呼叫新建的“曾模型”的predict方法,得到模型的輸出
feature=layer_model.predict(x)
 
print(feature)

以上這篇keras小技巧——獲取某一個網路層的輸出方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。