Регуляризация возбужденных значений активации в Tensorflow 2.0 Keras - PullRequest
2 голосов
/ 16 октября 2019

Для конкретной проблемы я хочу упорядочить возбужденные активации слоя в моей модели 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)

Утрата классификации уменьшается, тогда как вторая потеря становится больше. Я ожидаю, что вторая потеря будет минимизирована.

1 Ответ

3 голосов
/ 16 октября 2019

Ваша пользовательская потеря не дифференцируется в тех точках, где это имеет значение: когда значение превышает порог, ваша потеря совершает скачок. Это означает, что его нельзя минимизировать методами, основанными на градиенте. Однако, если вы сделаете свой убыток пропорциональным сумме, на которую превышен ваш порог, он будет дифференцируемым и, следовательно, может быть минимизирован с помощью градиентных методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...