Как я могу использовать скалярную константу для взвешивания скрытых скалярных выходов в Keras - PullRequest
1 голос
/ 14 июля 2020

Спасибо за ваше время!

Я пытаюсь построить нейронную сеть для регрессионного предсказания дискретного значения, но с особым поворотом. Входные данные должны обрабатываться двумя способами (модели A и B), а затем взвешенно объединяться. Выходы объединяются по формуле A G + B (1-G) с G = 1 / (1 + exp (-gamma * (input_weighting - c))). И гамма, и c следует изучать в процессе. Я борюсь с обеими переменными гамма и c, а также с вычитанием (1-G). Мой текущий код не работает в двух разных местах:

    # two models for time series (convolutional approach)
    input_model_A = keras.Input(shape=(12,))
    model_A = Dense(12)(input_model_A)
    input_model_B = keras.Input(shape=(12,))
    model_B = Dense(24)(input_model_B)

    # input for model weighting
    input_weighting = keras.Input(shape=[1,], name="vola_input")

    # exponent = gamma * (input_weighting - c)
    class MyLayer(Layer):
        def __init__(self, **kwargs):
            super(MyLayer, self).__init__(**kwargs)

        def build(self, input_shape=[[1,1],[1,1]]):
            self._c = K.variable(0.5)
            self._gamma = K.variable(0.5)
            self.trainable_weights = [self._c, self._gamma]

            super(MyLayer, self).build(input_shape)  # Be sure to call this at the end

        def call(self, vola, **kwargs):
            intermediate = substract([vola, self._c])
            result = multiply([self._gamma, intermediate])
            return result

        def compute_output_shape(self, input_shape):
            return input_shape[0]

    exponent = MyLayer()(input_weighting)
    # G = 1/(1+exp(-exponent)) 
    G = keras.layers.Dense(1, activation="sigmoid", name="G")(exponent)

    # output = G*A + (1-G)*B
    weighted_A = keras.layers.Multiply(name="layer_A")([model_A.outputs[0], G])
    weighted_B = keras.layers.Multiply(name="layer_B")
    pseudoinput = Input(shape=[1, 1], name="pseudoinput_input",
                        tensor=K.variable([1])) ([model_B.outputs[0], keras.layers.Subtract()([pseudoinput, G])])
    merge_layer = keras.layers.Add(name="merge_layer")([weighted_A, weighted_B])
    output_layer = keras.layers.Dense(units=1, activation='relu', name="output_layer")(merge_layer)
    
    model = keras.Model(inputs=[input_model_A, input_model_B, input_weighting], outputs=[output_layer])
    optimizer = SGD(learning_rate=0.01, momentum=0.0, nesterov=False)
    model.compile(optimizer=optimizer, loss='mean_squared_error')
  1. В моем пользовательском слое есть ошибка, я не понимаю, где что-то в определении входного измерения кажется неправильным.
File "...\keras\layers\merge.py", line 74, in build
    batch_sizes = [s[0] for s in input_shape if s is not None]
  File "...\keras\layers\merge.py", line 74, in <listcomp>
 batch_sizes = [s[0] for s in input_shape if s is not None]
IndexError: tuple index out of range
Моя «1» (в 1-G) просто не хочет работать. Я подозреваю, что способ, которым я пытаюсь создать экземпляр константы Tensor / Layer, - это flaud.
File "...\keras\backend\tensorflow_backend.py", line 75, in symbolic_fn_wrapper
    return func(*args, **kwargs)
  File "...\keras\engine\base_layer.py", line 446, in __call__
    self.assert_input_compatibility(inputs)
  File "...\keras\engine\base_layer.py", line 358, in assert_input_compatibility
    str(K.ndim(x)))
ValueError: Input 0 is incompatible with layer c: expected min_ndim=2, found ndim=1

Я нашел и попробовал оба этих предложения, но не добился успеха: Создание постоянного значения в Keras Как дать постоянный ввод для keras

Честно говоря, меня интересует одна (или обе) причины моих проблем, но я предпочитаю просто найти решение, которое обеспечивает описанную архитектуру.

1 Ответ

1 голос
/ 18 июля 2020

Это мое предложение с некоторыми комментариями

input_model_A = Input(shape=(12,))
model_A = Dense(24)(input_model_A)
input_model_B = Input(shape=(12,))
model_B = Dense(24)(input_model_B)
# model_A and model_B must have the same last dimensionality
# otherwise it is impossible to apply Add operation below

# input for model weighting
input_weighting = Input(shape=(1,), name="vola_input")

class MyLayer(Layer):
    def __init__(self, **kwargs):
        
        super(MyLayer, self).__init__(**kwargs)
        self._c = K.variable(0.5)
        self._gamma = K.variable(0.5)

    def call(self, vola, **kwargs):
        x = self._gamma * (vola - self._c) # gamma * (input_weighting - c)
        result = tf.nn.sigmoid(x) # 1 / (1 + exp(-x))
        return result

G = MyLayer()(input_weighting) # 1/(1+exp(-gamma * (input_weighting - c)))

weighted_A = Lambda(lambda x: x[0]*x[1])([model_A,G]) # A*G
weighted_B = Lambda(lambda x: x[0]*(1-x[1]))([model_B,G]) # B*(1-G)

merge_layer = Add(name="merge_layer")([weighted_A, weighted_B]) # A*G + B*(1-G)
output_layer = Dense(units=1, activation='relu', name="output_layer")(merge_layer)

model = Model(inputs=[input_model_A, input_model_B, input_weighting], outputs=[output_layer])
model.compile(optimizer='adam', loss='mean_squared_error')


# create dummy data and fit
n_sample = 100
Xa = np.random.uniform(0,1, (n_sample,12))
Xb = np.random.uniform(0,1, (n_sample,12))
W = np.random.uniform(0,1, n_sample)
y = np.random.uniform(0,1, n_sample)

model.fit([Xa,Xb,W], y, epochs=3)

вот рабочий блокнот: https://colab.research.google.com/drive/1MA6qs4IK9e41TbBK1mAebtALA2fMcNPY?usp=sharing

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