一、Lambda層的使用
keras.layers.Lambda(function, output_shape=None, mask=None, arguments=None)
作用:將任意表達式封裝為 Layer
對象
from keras.layers import Input, Dense,Lambda,merge from keras.models import Model from keras import backend as K import numpy as np # 輸入層,注意表示的輸入維度是[batch,5],默認不顯示batch的,即batch的大小是任意的 inputs = Input(shape=(5,)) #Input(shape=None, batch_shape=None, name=None, dtype=None, sparse=False,tensor=None): #如果用batch_shape則可以顯示配置batch def square(x): return x**2 y=Lambda(square)(inputs) model = Model(inputs=inputs, outputs=[y]) # a=np.array([[1,2,3,4,5],[1,2,2,1,1]])
#直接根據輸入預測結果 print(model.predict(a))#這里的a必須是numpy.array類型,否則報錯
out:
[[1 2 3 4 5] [1 2 2 1 1]] [[ 1. 4. 9. 16. 25.] [ 1. 4. 4. 1. 1.]]
二、可以不要輸出
普通模型都是有標准的輸入輸出結構,然后loss是根據模型輸出與真實label的運算。然而,對於比較復雜的模型,如自編碼器、GAN、Seq2Seq,這種寫法有時候不夠方便,loss並不總是需要真實label的。幸好,比較新的Keras版本已經支持更加靈活的loss定義,比如我們可以這樣寫一個自編碼器:
x_in = Input(shape=(784,)) x = x_in x = Dense(100, activation='relu')(x) x = Dense(784, activation='sigmoid')(x) model = Model(x_in, x) loss = K.mean((x - x_in)**2) model.add_loss(loss) model.compile(optimizer='adam') model.fit(x_train, None, epochs=5)
上述寫法的幾個特點是:
1、compile
的時候並沒有傳入loss,而是在compile
之前通過另外的方式定義loss,然后通過add_loss
加入到模型中,這樣可以隨意寫足夠靈活的loss,比如這個loss可以跟中間層的某個輸出有關、跟輸入有關,等等。
2、fit
的時候,原來的目標數據,現在是None
,因為這種方式已經把所有的輸入輸出都通過Input
傳遞進來了。
三、更隨意的metric
另一種輸出是訓練過程中用來觀察的metric。這里的metric,就是指衡量模型性能的一些指標,比如正確率、F1等,Keras內置了一些常見的metric。像開頭例子的accuracy
一樣,將這些metric的名字加入到model.compile
中,就可以在訓練過程中動態地顯示這些metric。
當然,你也可以參考Keras中內置的metric來自己定義新metric,但問題是在標准的metric定義方法中,metric是“輸出層”與“目標值”之間的運算結果,而我們經常要在訓練過程中觀察一些特殊的量的變化過程,比如我想觀察中間某一層的輸出變化情況,這時候標准的metric定義就無法奏效了。
那可以怎么辦呢?我們可以去看Keras的源碼,去追溯它的metric相關的方法,最終我發現metric實際上定義在兩個list
之中,通過修改這兩個list
,我們可以非常靈活地顯示需要觀察的metric,比如
x_in = Input(shape=(784,)) x = x_in x = Dense(100, activation='relu')(x) x_h = x x = Dense(10, activation='softmax')(x) model = Model(x_in, x) model.compile(loss='categorical_crossentropy ', optimizer='adam', metrics=['accuracy']) # 重點來了 model.metrics_names.append('x_h_norm') model.metrics_tensors.append(K.mean(K.sum(x_h**2, 1)))#可以觀察到中間結果x_h的變化。 model.fit(x_train, y_train, epochs=5)
上述代碼展示了在訓練過程中觀察中間層的平均模長的變化情況。可以看到,主要涉及到兩個list
:model.metrics_names
是metric的名稱,是字符串列表;model.metrics_tensors
是metric的張量。只要在這里把你需要展示的量添加進去,就可以在訓練過程中顯示了。當然,要注意的是,一次性只能添加一個標量