Я пытаюсь создать многоголовый слой самоконтроля в Керасе. Слой будет следовать за слоем 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
У меня были похожие проблемы, когда я пытался справиться с переменным размером пакета, отсюда и все время. линии плитки.