首页 > 解决方案 > Keras:如何实现 LSTM 的目标复制?

问题描述

使用Lipton 等人 (2016)的示例,目标复制基本上是计算 LSTM(或 GRU)的每个时间步(除了最终时间步)的损失,并在训练时平均该损失并将其添加到主要损失中。在数学上,它由 -

损失方程

在图形上,它可以表示为 -

在此处输入图像描述

那么我该如何在 Keras 中实现这一点呢?说,我有二进制分类任务。假设我的模型是下面给出的简单模型 -

model.add(LSTM(50))    
model.add(Dense(1))
model.compile(loss='binary_crossentropy', class_weights={0:0.5, 1:4}, optimizer=Adam(), metrics=['accuracy'])
model.fit(x_train, y_train)
  1. 我认为y_train需要从 (batch_size, 1) 重塑/平铺到 (batch_size, time_step) 对吗?
  2. 设置后需要将密集层TimeDistributed正确应用到 LSTMreturn_sequences=True吗?
  3. 我如何准确地实现上面给出的确切损失函数?class_weights需要修改吗?
  4. 目标复制仅在训练期间进行。如何仅使用主要损失来实现验证集评估?
  5. 我应该如何处理目标复制中的零填充?我的序列被填充为max_len15,平均长度为 7。由于目标复制损失在所有步骤中平均,我如何确保它在计算损失时不使用填充词?基本上,动态分配T实际序列长度。

标签: pythonneural-networkkeraslstm

解决方案


问题一:

因此,对于目标,您需要将其塑造为(batch_size, time_steps, 1). 只需使用:

y_train = np.stack([y_train]*time_steps, axis=1)

问题2:

你是对的,但TimeDistributed在 Keras 2 中是可选的。

问题 3:

我不知道类权重会如何表现,但是常规的损失函数应该是这样的:

from keras.losses import binary_crossentropy

def target_replication_loss(alpha):

    def inner_loss(true,pred):
        losses = binary_crossentropy(true,pred)

        return (alpha*K.mean(losses[:,:-1], axis=-1)) + ((1-alpha)*losses[:,-1])

    return inner_loss

model.compile(......, loss = target_replication_loss(alpha), ...)

问题 3a:

由于上述方法不适用于类权重,我创建了一个替代方案,其中权重进入损失:

def target_replication_loss(alpha, class_weights):

    def get_weights(x):
        b = class_weights[0]
        a = class_weights[1] - b
        return (a*x) + b

    def inner_loss(true,pred):
        #this will only work for classification with only one class 0 or 1
        #and only if the target is the same for all classes
        true_classes = true[:,-1,0]
        weights = get_weights(true_classes)

        losses = binary_crossentropy(true,pred)

        return weights*((alpha*K.mean(losses[:,:-1], axis=-1)) + ((1-alpha)*losses[:,-1]))

    return inner_loss

问题4:

metric为避免复杂性,我会说您应该在验证中使用附加功能:

def last_step_BC(true,pred):
    return binary_crossentropy(true[:,-1], pred[:,-1])

model.compile(...., 
              loss = target_replication_loss(alpha), 
              metrics=[last_step_BC])

问题 5:

这是一个很难的,我需要研究一点....

作为初始解决方法,您可以使用输入形状设置模型(None, features),并单独训练每个序列。


没有 class_weight 的工作示例

def target_replication_loss(alpha):

    def inner_loss(true,pred):
        losses = binary_crossentropy(true,pred)
        #print(K.int_shape(losses))
        #print(K.int_shape(losses[:,:-1]))
        #print(K.int_shape(K.mean(losses[:,:-1], axis=-1)))
        #print(K.int_shape(losses[:,-1]))

        return (alpha*K.mean(losses[:,:-1], axis=-1)) + ((1-alpha)*losses[:,-1])

    return inner_loss

alpha = 0.6

i1 = Input((5,2))
i2 = Input((5,2))

out = LSTM(1, activation='sigmoid', return_sequences=True)(i1)
model = Model(i1, out)

model.compile(optimizer='adam', loss = target_replication_loss(alpha))

model.fit(np.arange(30).reshape((3,5,2)), np.arange(15).reshape((3,5,1)), epochs = 200)

具有类权重的工作示例:

def target_replication_loss(alpha, class_weights):

    def get_weights(x):
        b = class_weights[0]
        a = class_weights[1] - b
        return (a*x) + b

    def inner_loss(true,pred):
        #this will only work for classification with only one class 0 or 1
        #and only if the target is the same for all classes
        true_classes = true[:,-1,0]
        weights = get_weights(true_classes)

        losses = binary_crossentropy(true,pred)
        print(K.int_shape(losses))
        print(K.int_shape(losses[:,:-1]))
        print(K.int_shape(K.mean(losses[:,:-1], axis=-1)))
        print(K.int_shape(losses[:,-1]))
        print(K.int_shape(weights))

        return weights*((alpha*K.mean(losses[:,:-1], axis=-1)) + ((1-alpha)*losses[:,-1]))

    return inner_loss

alpha = 0.6
class_weights={0: 0.5, 1:4.}

i1 = Input(batch_shape=(3,5,2))
i2 = Input((5,2))

out = LSTM(1, activation='sigmoid', return_sequences=True)(i1)
model = Model(i1, out)

model.compile(optimizer='adam', loss = target_replication_loss(alpha, class_weights))

model.fit(np.arange(30).reshape((3,5,2)), np.arange(15).reshape((3,5,1)), epochs = 200)

推荐阅读