2016-09-15 7 views
3
... 
print('Build model...') 
model = Sequential() 
model.add(Embedding(max_features, 128)) 
model.add(LSTM(size, return_sequences=True, dropout_W=0.2 dropout_U=0.2)) 
model.add(GlobalAveragePooling1D()) 
model.add(Dense(1)) 
model.add(Activation('sigmoid')) 
.... 

мне нужно, чтобы быть в состоянии взять среднее или максимальные векторов для всех временных шагов в образце после LSTM слоя, прежде чем дать это среднее или максимальный вектор к плотному слою в Keras.среднего или максимальное объединение с маскирующей поддержкой в ​​Keras

Думаю, timedistributedmerge смог это сделать, но это было устарело. Используя return_sequences=True, я могу получить векторы для всех временных шагов в образце после слоя LSTM. Тем не менее, GlobalAveragePooling1D() несовместим с маскировкой, и он рассматривает все временные шаги, тогда как мне нужны только незаметные временные шаги.

Я видел сообщения, рекомендующие слой Lambda, но они также не учитывают маскировку. Любая помощь будет оценена по достоинству.

ответ

1

Поскольку средний пул только делает среднее значение по одной оси, вам просто нужно исправить количество элементов в среднем, так как в конце будет выполняться маскирование потерь, а не здесь. Вы можете сделать это, вероятно, что-то вроде этого:

class GlobalAveragePooling1DMasked(GlobalAveragePooling1D): 
    def call(self, x, mask=None): 
     if mask != None: 
      return K.sum(x, axis=1)/K.sum(mask, axis=1) 
     else: 
      return super().call(x) 
+1

Обратите внимание, что вы не можете быть уверены в том, что Keras маскированные значения в 'x' равны нулю! Поэтому эта реализация дала бы неправильные результаты. – pir

+0

Сама маска, введенная слоем 'Masking' и' Embedding', является двоичной. Конечно, у вас всегда могут быть слои, которые реализуют 'compute_mask' по-другому, но это не происходит в самом керасе, насколько я могу судить. – nemo

+0

Да, маска двоичная. Это не то, что я говорю :) – pir

1

Чтобы маскированные значения в х равна нулю, вы можете сделать это: ответ

class MeanPool(Layer): 
def __init__(self, **kwargs): 
    self.supports_masking = True 
    super(MeanPool, self).__init__(**kwargs) 

def compute_mask(self, input, input_mask=None): 
    # do not pass the mask to the next layers 
    return None 

def call(self, x, mask=None): 
    if mask is not None: 
     # mask (batch, time) 
     mask = K.cast(mask, K.floatx()) 
     # mask (batch, time, 'x') 
     mask = mask.dimshuffle(0, 1, 'x') 
     # to make the masked values in x be equal to zero 
     x = x * mask 
    return K.sum(x, axis=1)/K.sum(mask, axis=1) 

def get_output_shape_for(self, input_shape): 
    # remove temporal dimension 
    return input_shape[0], input_shape[2] 
1

Jacoxu является правильным. Но если вы используете бэкендо тензора для keras, тип Tensor не поддерживает функцию dimshuffle, попробуйте это вместо этого.

def call(self, x, mask=None): 
    if mask is not None: 
     # mask (batch, time) 
     mask = K.cast(mask, K.floatx()) 
     # mask (batch, x_dim, time) 
     mask = K.repeat(mask, x.shape[-1]) 
     # mask (batch, time, x_dim) 
     mask = tf.transpose(mask, [0,2,1]) 
     x = x * mask 
    return K.sum(x, axis=1)/K.sum(mask, axis=1)