Для конкретной проблемы я хочу упорядочить возбужденные активации слоя в моей модели Keras. Поэтому я создал пользовательские потери, основанные на количестве значений активации, которые превышают определенный порог.
Потеря обнаруживается, но не уменьшается оптимизатором. Минимизируются только потери при классификации.
Использование последней версии tenorflow 2.0 с Keras для построения модели. Моя текущая попытка добавляет второй вывод с пользовательской потерей, зависящей от определенного слоя. Я уже пытался представить потери в качестве второго ввода и добавить их к плотным потерям, что дало мне те же результаты, пользовательские потери не были минимизированы.
Я полагаю, что градиент второй потери не может быть рассчитан,но у меня есть рабочий пример в PyTorch, где это, кажется, работает.
import tensorflow as tf
import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Conv2D, Flatten, MaxPooling2D, SpatialDropout2D, Input
from tensorflow.keras.optimizers import SGD
import tensorflow.keras.backend as K
from tensorflow.python.keras.layers import Layer
import get_prepare_dataset
# config
REGULARIZATION_HYPERP = 0.01
(train_images, train_labels), (test_images, test_labels) = get_prepare_dataset.mnist10()
class Taboo(Layer):
def compute_output_signature(self, input_signature):
pass
def __init__(self, thresholds, **kwargs):
super(Taboo, self).__init__(**kwargs)
self.thresholds = thresholds
def call(self, x, mask=None):
return x
def taboo_loss(y_true, y_pred):
above_threshold = tf.math.greater(y_pred, y_true[0])
return REGULARIZATION_HYPERP * K.mean(tf.reduce_sum(tf.cast(above_threshold, tf.float32)))
if __name__ == "__main__":
y_input = Input(shape=(28, 28, 1))
layer1 = Conv2D(filters=10, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding="same")(y_input)
layer2 = MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='valid')(layer1)
layer3 = Conv2D(filters=20, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding="valid")(layer2)
layer4 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid')(layer3)
layer5 = SpatialDropout2D(0.5)(layer4)
layer6 = Flatten()(layer5)
output_layer = Dense(units=10, activation='softmax')(layer6)
thresholds = [0.5]
cr = Taboo(thresholds)(layer3)
model = Model(inputs=y_input, outputs=[output_layer, cr])
model.compile(optimizer=SGD(lr=0.1), loss=[K.binary_crossentropy, taboo_loss])
model.fit(train_images, [train_labels, np.asarray([thresholds] * len(train_images))],
validation_data=[test_images, [test_labels, np.asarray([thresholds] * len(test_images))]], epochs=40)
Утрата классификации уменьшается, тогда как вторая потеря становится больше. Я ожидаю, что вторая потеря будет минимизирована.