Как добавить тензор обучаемых весов в тензор Кераса? - PullRequest
0 голосов
/ 08 мая 2018

Следуя разделу «Временное кодирование» на стр. 5 из https://arxiv.org/pdf/1503.08895.pdf (кстати, отличный документ), я сказал N многих встроенных векторов измерения M. Поэтому мой тензор Кераса равен (размер партии, N , M) и я хочу добавить матрицу весов N на M к каждой из выборок размера партии. Для этого я создал свой собственный слой Keras:

from constants import BATCH_SIZE
class Added_Weights(Layer):

  def __init__(self, input_dim, output_dim, **kwargs):
      self.output_dim = output_dim
      self.input_dim = input_dim

      super(Added_Weights, self).__init__(**kwargs)

  def build(self, input_shape):
      # Create a trainable weight variable for this layer.
      self.kernel = self.add_weight(name='kernel',
                                  shape=(BATCH_SIZE, self.input_dim[0], self.input_dim[1]),
                                  initializer=RandomNormal(mean=0., stddev=0.05, seed=None),
                                  trainable=True)

      print("kernel has shape "+self.kernel.shape + " or "+K.int_shape(self.kernel))
      super(Added_Weights, self).build(input_shape)  

  def call(self, x, **kwargs):
      return Add()([x, self.kernel])

  def compute_output_shape(self, input_shape):
      return (BATCH_SIZE, self.input_dim[0], self.input_dim[1])

И это РАБОТАЕТ, но проблема в том, что каждая из многих матриц BATCH_SIZE имеет веса DifrenT. Мне нужно добавить одинаковые веса для каждого из образцов в партии.

Итак, я попробовал пару вещей. Keras имеет встроенный слой RepeatVector, поэтому я попытался задать форму ядра (N, M) и выполнить RepeatVector (BATCH_SIZE) (kernel), но по какой-то причине это заканчивается формой (N, BATCH_SIZE, M). Я бы хотел использовать Reshape там, но Reshape () рассматривает первое измерение как batch_size и не позволяет мне его изменять. У Permute () такая же проблема.

Еще одна мысль состояла в том, чтобы создать начальную фигуру в том виде, как она есть в коде, а затем зациклить тензор, чтобы установить срезы с 1 по BATCH_SIZE-1 равными срезу 0, чтобы они все содержали одинаковые веса, но я Нельзя назначать значения тензорам Кераса таким образом.

Единственная другая мысль, которая у меня возникла, это просто попробовать его с формой (N, M) и надеяться, что Керас достаточно умен, чтобы добавить его к каждому срезу ввода, но после того, как Add () будет применен к моему (?, N, M) и (N, M) ядро, так или иначе я получаю тензор (N, N, M), и в этот момент мы мертвы.

1 Ответ

0 голосов
/ 08 мая 2018

Я думаю, вы слишком усложняете. Просто определите веса как тензор N x M в build и выполните сумму с входным тензором в call. Я подправил ваш код следующим образом:

from keras.engine.topology import Layer
from keras.models import Model
from keras.layers import Input
import numpy as np

N = 3
M = 4
BATCH_SIZE = 1

class Added_Weights(Layer):
    def __init__(self, **kwargs):
        super(Added_Weights, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel',
                                      shape=(input_shape[1], input_shape[2]),
                                      initializer='ones',  # TODO: Choose your initializer
                                      trainable=True)
        super(Added_Weights, self).build(input_shape)

    def call(self, x, **kwargs):
        # Implicit broadcasting occurs here.
        # Shape x: (BATCH_SIZE, N, M)
        # Shape kernel: (N, M)
        # Shape output: (BATCH_SIZE, N, M)
        return x + self.kernel

    def compute_output_shape(self, input_shape):
        return input_shape


a = Input(shape=(N, M))
layer = Added_Weights()(a)
model = Model(inputs=a,
              outputs=layer)

a = np.zeros(shape=(BATCH_SIZE, N, M))
pred = model.predict(a)
print(pred)

Обратите внимание, что self.kernel неявно транслируется в call для соответствия форме x, поэтому к каждому образцу в пакете добавляются одинаковые веса.

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