簡體   English   中英

Keras:多輸出和自定義損失函數的清晰實現?

[英]Keras: clean implementation for multiple outputs and custom loss functions?

來自TensorFlow,我覺得除了在Keras中實現基本的順序模型之外,還可以實現其他任何技巧。 有這么多東西會自動進行。 在TensorFlow中,您始終知道占位符(輸入/輸出),形狀,結構等,因此例如設置自定義損失非常容易。

定義多個輸出和自定義損失函數的干凈方法是什么?

讓我們以簡單的自動編碼器為例,並使用MNIST:

(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
X_train = X_train.reshape(-1, 28, 28, 1)

簡短的卷積編碼器:

enc_in = Input(shape=(28, 28, 1), name="enc_in")
x = Conv2D(16, (3, 3))(enc_in)
x = LeakyReLU()(x)
x = MaxPool2D()(x)
x = Conv2D(32, (3, 3))(x)
x = LeakyReLU()(x)
x = Flatten()(x)
z = Dense(100, name="z")(x)

enc = Model(enc_in, z, name="encoder")

解碼器的類似架構。 我們不關心填充和卷積導致的維數減少,因此我們只在末尾應用雙線性調整大小以再次匹配(batch, 28, 28, 1)

def resize_images(inputs, dims_xy):
    x, y = dims_xy
    return Lambda(lambda im: K.tf.image.resize_images(im, (y, x)))(inputs)

# decoder
dec_in = Input(shape=(100,), name="dec_in")
x = Dense(14 * 14 * 8)(dec_in)
x = LeakyReLU()(x)
x = Reshape((14, 14, 8))(x)
x = Conv2D(32, (3, 3))(x)
x = LeakyReLU()(x)
x = UpSampling2D()(x)
x = Conv2D(16, (3, 3))(x)
x = LeakyReLU()(x)
x = Conv2D(1, (3, 3), activation="linear")(x)
dec_out = resize_images(x, (28, 28))

dec = Model(dec_in, dec_out, name="decoder")

我們定義自己的MSE有一個簡單的例子...

def custom_loss(y_true, y_pred):
    return K.mean(K.square(y_true - y_pred))

...最后建立完整的模型:

outputs = dec(enc(enc_in))
ae = Model(enc_in, outputs, name="ae")
ae.compile(optimizer=Adam(lr=1e-4), loss=custom_loss)

# training
ae.fit(x=X_train, y=X_train, batch_size=256, epochs=10)

如果我在解碼器的最后一層中定義了activation="sigmoid"以獲取漂亮的圖像(輸出間隔[0.0,1.0]),則訓練損失有所不同,因為Keras沒有自動使用logit,而是將Sigmoid激活饋入損失中。 因此,對於訓練來說,在最后一層中使用activation="linear"會更好,更快。 在TensorFlow中,我將簡單定義兩個logits=xoutput=sigmoid(x) ,以便能夠在任何自定義損失函數和output使用logits進行繪圖或其他應用程序。

我將如何在Keras中做這樣的事情?

另外,如果我有多個輸出,如何在自定義損失函數中使用它們? 例如VAE的KL差異或GAN的虧損條件。

功能的API指南是不是非常有幫助的(特別是如果你比較這對TensorFlow的超級廣泛的指南),因為它僅包括基本LSTM例子,你不必自己定義任何東西,但只使用預定義的損失函數。

在TensorFlow中,我將簡單定義兩個Tensors logits = x和output = sigmoid(x),以便能夠在任何自定義損失函數和輸出中使用logit進行繪圖或其他應用程序。

在Keras中,您執行的操作完全相同:

x = Conv2D(1, (3, 3), activation="linear")(x)
dec_out = resize_images(x, (28, 28))  # Output tensor used in training, for the loss function

training_model = Model(dec_in, dec_out, name="decoder")

...

sigmoid = Activation('sigmoid')(dec_out)
inference_model = Model(dec_in, sigmoid)

training_model.fit(x=X_train, y=X_train, batch_size=256, epochs=10)

prediction = inference_model.predict(some_input)

在Keras世界中,如果只有一個輸出張量,您的生活將變得更加輕松。 然后,您可以使用標准的Keras功能。 對於兩個輸出/損耗,一種可能的解決方法是在輸出之前將它們連接起來,然后在損耗函數中再次分割。 一個很好的例子是SSD實現,它具有分類和本地化的損失: https : //github.com/pierluigiferrari/ssd_keras/blob/master/keras_loss_function/keras_ssd_loss.py#L133

總的來說,我不理解那些抱怨。 可以理解,新的框架起初會造成挫敗感,但是Keras很棒,因為當您需要標准的東西時它很簡單,而當需要超越標准時它就很靈活。 Keras模型動物園中 ,復雜模型的實現數量就是一個很好的證明。 通過閱讀該代碼,您可以學習在Keras中構建模型的各種模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM