Как я могу решить эту проблему формы stati c против динамика c в керасе / тензорном потоке? - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь создать многоголовый слой самоконтроля в Керасе. Слой будет следовать за слоем Bi-LSTM и иметь входную форму (размер партии, длина последовательности, размеры LSTM).

Слой самовосприятия работает нормально в модели. Многоголовая часть не имеет. Однако за пределами модели комбинация работает нормально и выдает тензор правильного размера (размер партии, размеры LSTM). Когда я пытаюсь включить его в свою модель, я получаю следующую ошибку:

ValueError: вход 0 несовместим со слоем permute_1: ожидается ndim = 3, найдено ndim = нет. Печать формы ввода перед возвращением перестановки (?,)

Из того, что я прочитал, это проблема типа * stati c vs dynamici c. Тем не менее, я не имею ни малейшего понятия, как это исправить.

class testAttention(Layer):
    def __init__(self,size,depth,seq_length,**kwargs):
        self.size=size
        self.depth=depth
        self.seq_length=seq_length
        self.Ws1, self.Ws2 = None, None
        super(testAttention,self).__init__(**kwargs)

    def get_config(self):
        base_config = super(testAttention, self).get_config()
        base_config['size'] = self.size
        return base_config


    def build(self,input_shape):

        print(input_shape)

        self.Ws1=self.add_weight(name="Ws1",shape=(self.size, self.depth),initializer="normal", trainable=True)
        self.b1=self.add_weight(name="b1",shape=(self.size,self.seq_length),initializer="zeros",trainable=True)
        self.Ws2=self.add_weight(name="Ws2",shape=(self.depth,self.size),initializer="normal", trainable=True)
        self.b2=self.add_weight(name="b2",shape=(self.depth,self.seq_length),initializer="zeros",trainable=True)
        super(testAttention, self).build(input_shape)

    def call(self,x):

        print(self.Ws1.shape)
        print(self.Ws2.shape)
        x_shape=K.shape(x)
        print(K.shape(x))


        print(self.b1.shape)
        print(self.b2.shape)
        Ws1=self.Ws1
        Ws2=self.Ws2
        b1=self.b1
        b2=self.b2

        Ws1=tf.tile(tf.expand_dims(Ws1,0),[x_shape[0],1,1])
        Ws2=tf.tile(tf.expand_dims(Ws2,0),[x_shape[0],1,1])
        b1=tf.tile(tf.expand_dims(b1,0),[x_shape[0],1,1])
        b2=tf.tile(tf.expand_dims(b2,0),[x_shape[0],1,1])

        hT = Permute(dims=(2, 1))(x)
        hT=tf.linalg.matmul(Ws1,hT)+b1
        hT=Activation('relu')(hT)
        hT=(tf.linalg.matmul(Ws2,hT))+b2
        hT=Permute(dims=(2, 1))(hT)
        a=Activation('softmax')(hT)
        weights=a/K.sum(a,axis=1,keepdims=True)
        output=x*weights

        outputV=K.sum(output,axis=1)

        return outputV

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

class makeMulti(Layer):
  def __init__(self, d, num_heads, seq_length, **kwargs):

    self.num_heads = int(num_heads)
    self.d = int(d)
    self.depth=int(d/num_heads)
    self.seq_length=seq_length

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

  def split_heads(self, inputs, batch_size):
    inputs = tf.reshape(
        inputs, shape=(batch_size, -1, self.num_heads, self.depth))
    return tf.transpose(inputs, perm=[0, 2, 1, 3])

  def divide_heads(self,inputs,num_heads):

    spl=tf.split(inputs,num_heads,axis=1)   
    for i in range(len(spl)):
        spl[i]=tf.squeeze(spl[i])
    return spl

  def build(self,input_shape):

     self.Wo=self.add_weight(name="Wo",shape=(self.d,),initializer="glorot_normal", trainable=True)
     self.bo=self.add_weight(name="bo",shape=(self.d,),initializer="zeros",trainable=True)

     super(makeMulti, self).build(input_shape)

  def call(self, x):

    x_shape=K.shape(x)
    self.Wo=tf.tile(tf.expand_dims(self.Wo,0),[x_shape[0],1])
    self.bo=tf.tile(tf.expand_dims(self.bo,0),[x_shape[0],1])

    batch_size = x_shape[0]

    sectioned=self.split_heads(x,batch_size)
    divd=self.divide_heads(sectioned,self.num_heads)
    outputs=[]
    for i in range(len(divd)):
        outputs.append(testAttention(70,self.depth,self.seq_length)(divd[i]))

    concatted=tf.concat(outputs,axis=1)
    res=(concatted*self.Wo)+self.bo 


    return res

У меня были похожие проблемы, когда я пытался справиться с переменным размером пакета, отсюда и все время. линии плитки.

...