Функция динамической активации в Керасе - PullRequest
3 голосов
/ 20 апреля 2019

Я работаю над исследовательским проектом, который предполагает замену определенных активаций ReLu полиномиальными активациями. Унаследованный код использует Keras с бэкэндом TensorFlow, с чем у меня мало опыта.

По сути, я строю ванильный график ResNet, и мне нужно постепенно поменять несколько ReLus с пользовательскими функциями. Другими словами, моя пользовательская активация должна сделать следующее:

def activation(x)
    approx = .1992 + .5002*x + .1997*x**2
    relu = tf.nn.relu(x)
    diff = (TOTAL_EPOCHS - CURRENT_EPOCH) / TOTAL_EPOCHS
    return (1-diff)*approx + diff*relu

Проблема, с которой я столкнулся, заключается в том, чтобы выяснить, как сделать функцию динамической в ​​текущей эпохе, используя keras и model.fit. Я пробовал несколько вещей, таких как определение пользовательского слоя, передача переменной счетчика и попытка использовать глобальную переменную шага tenorflow, но с каждой из этих попыток сталкивался с досадными ошибками. Мне было интересно, есть ли простой способ сделать это, что я пропускаю? Кажется, это должно быть тривиально, но мне просто не хватает опыта работы с фреймворком.

1 Ответ

2 голосов
/ 20 апреля 2019

Вы можете использовать keras.callbacks.Callback, чтобы сделать функцию динамической через текущую эпоху, используя керасы и model.fit.Вот пример, чтобы сделать возвращаемое значение функции активации равным текущей эпохе.Из значения MSE вы можете быстро увидеть, что текущая эпоха участвует в вычислении функции активации.

from keras.models import Model
from keras.layers import Activation,Input
from keras.utils.generic_utils import get_custom_objects
import keras.backend as K
from keras.callbacks import Callback

class MonitorCallback(Callback):
    def __init__(self, CURRENT_EPOCH):
        self.parm = CURRENT_EPOCH
    def on_epoch_begin(self, epoch, logs=None):
        K.set_value(self.parm, epoch)

CURRENT_EPOCH = K.variable(0)
TOTAL_EPOCHS = 8
def custom_activation(x):
    return CURRENT_EPOCH

num_input = Input(shape=(1,))
get_custom_objects().update({'custom_activation': Activation(custom_activation)})
output = Activation(custom_activation)(num_input)
model = Model(num_input,output)
model.compile(optimizer='rmsprop',loss='mse',metrics=['mse'])

model.fit(x=[1],y=[2],epochs=TOTAL_EPOCHS,callbacks=[MonitorCallback(CURRENT_EPOCH)])

# print
Using TensorFlow backend.
Epoch 1/8
1/1 [==============================] - 2s 2s/step - loss: 4.0000 - mean_squared_error: 4.0000
Epoch 2/8
1/1 [==============================] - 0s 2ms/step - loss: 1.0000 - mean_squared_error: 1.0000
Epoch 3/8
1/1 [==============================] - 0s 2ms/step - loss: 0.0000e+00 - mean_squared_error: 0.0000e+00
Epoch 4/8
1/1 [==============================] - 0s 2ms/step - loss: 1.0000 - mean_squared_error: 1.0000
Epoch 5/8
1/1 [==============================] - 0s 3ms/step - loss: 4.0000 - mean_squared_error: 4.0000
Epoch 6/8
1/1 [==============================] - 0s 3ms/step - loss: 9.0000 - mean_squared_error: 9.0000
Epoch 7/8
1/1 [==============================] - 0s 3ms/step - loss: 16.0000 - mean_squared_error: 16.0000
Epoch 8/8
1/1 [==============================] - 0s 3ms/step - loss: 25.0000 - mean_squared_error: 25.0000

Имейте в виду, что эпоха отсчитывает от нуля в keras.callbacks.Callback.Вы можете попробовать заменить custom_activation функцией активации.

...