Реализация слоя свапа в керасе - PullRequest
1 голос
/ 22 декабря 2019

В настоящее время я пытаюсь реализовать слой свопаута в кератах (как в: http://papers.nips.cc/paper/6205-swapout-learning-an-ensemble-of-deep-architectures.pdf). Если я правильно понял концепцию, то, например, просто получается вывод нормального плотного слоя. Таким образом, случайным образом выбирается междувыдача 0, x, F (x) и x + F (x), где x - это ввод, а F (x) - нормальный вывод, который будет производить слой.

Поэтому я попытался использовать плотныйслой в качестве основы и просто отредактируйте метод call следующим образом (все остальное точно так же, как в плотном слое):

def call(self, inputs):
        output = K.dot(inputs, self.kernel)
        if self.use_bias:
            output = K.bias_add(output, self.bias, data_format='channels_last')
#--------- edited -----------       
        theta1 = np.random.randint(2, size=(1, 256))
        theta2 = np.random.randint(2, size=(1, 256))
        theta1 = theta1.astype(np.float32)
        theta2 = theta2.astype(np.float32)

        output = tf.add(tf.multiply(theta1, inputs), tf.multiply(theta2, output))
# -----------------------------------
        if self.activation is not None:
            output = self.activation(output)
        return output

Так что я просто вычисляю результат, как в статье Y = Theta1* input + Theta2 * output, где * - поэлементное умножение. Форма вывода остается такой же, как и без этого вычисления, но когда я пытаюсь запустить его в следующей модели:

import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense, Flatten
from swapout import Swapout

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = Sequential()
model.add(Flatten(input_shape = (28,28)))
model.add(Swapout(256, activation='relu'))
model.add(Dense(10, activation='softmax'))

model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
res = model.evaluate(x_test, y_test, verbose=2)

Хотя я получаю следующую ошибку:

2019-12-21 22:59:31.924209: W tensorflow/core/common_runtime/base_collective_executor.cc:216] BaseCollectiveExecutor::StartAbort Invalid argument: Incompatible shapes: [32,784] vs. [1,256]
     [[{{node swapout_1/Mul}}]]
Traceback (most recent call last):
  File "/home/andreas/studium/semester9/vertiefungs/neural.py", line 294, in <module>
    runSingleMnistExperimant()
  File "/home/andreas/studium/semester9/vertiefungs/neural.py", line 220, in runSingleMnistExperimant
    model.fit(x_train, y_train, epochs=5)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/keras/engine/training.py", line 1239, in fit
    validation_freq=validation_freq)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/keras/engine/training_arrays.py", line 196, in fit_loop
    outs = fit_function(ins_batch)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/keras/backend.py", line 3740, in __call__
    outputs = self._graph_fn(*converted_inputs)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py", line 1081, in __call__
    return self._call_impl(args, kwargs)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py", line 1121, in _call_impl
    return self._call_flat(args, self.captured_inputs, cancellation_manager)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py", line 1224, in _call_flat
    ctx, args, cancellation_manager=cancellation_manager)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py", line 511, in call
    ctx=ctx)
  File "/home/andreas/studium/my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/eager/execute.py", line 67, in quick_execute
    six.raise_from(core._status_to_exception(e.code, message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.InvalidArgumentError:  Incompatible shapes: [32,784] vs. [1,256]
     [[node swapout_1/Mul (defined at /my_tensorflow/venv/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:1751) ]] [Op:__inference_keras_scratch_graph_761]

Function call stack:
keras_scratch_graph

Что я делаю неправильно в вычислениях? И есть ли лучший / более простой способ получить слой свопаута? Я очень новичок в Keras и tenorflow;)

Большое спасибо за помощь!


Обновление: Я только что решил проблему. Проблема заключалась в форме входных данных (None, 784). Конечно, это не может быть умножено поэлементно на вектор (1, 256). Также мне пришлось умножить одно из полученных слагаемых в сложении на матрицу, которая приводит их к одной и той же форме ... Я выбрал заполнение нулями.

Вот решение:

def call(self, inputs):
    output = K.dot(inputs, self.kernel)
    if self.use_bias:
        output = K.bias_add(output, self.bias, data_format='channels_last')

    inputLength = K.int_shape(inputs)[-1]
    outputLength = K.int_shape(output)[-1]
    theta1 = np.random.randint(2, size=(1,inputLength))
    theta2 = np.random.randint(2, size=(1,outputLength))
    theta1 = theta1.astype(np.float32)
    theta2 = theta2.astype(np.float32)

    zeroPadding = getZeroPaddingMatrix(inputLength, outputLength)

    output = tf.add(tf.matmul(tf.multiply(theta1, inputs), zeroPadding), tf.multiply(theta2, output))

    if self.activation is not None:
        output = s
    return output

Матрица заполнения нулями вычисляется следующим образом:

def getZeroPaddingMatrix(inputLength, outputLength):
    zeroPadding = np.identity(inputLength)
    if(outputLength > inputLength):
        zeros = np.zeros((inputLength, outputLength-inputLength))
        zeroPadding = np.concatenate((zeroPadding, zeros), axis=1)
    elif(outputLength < inputLength):
        zeroPadding =  zeroPadding[:,(inputLength-outputLength) :]
    return zeroPadding.astype(np.float32)

Осталось только добавить параметры для изменения theta1 и theta2.

...