繁体   English   中英

Seq2Seq模型和损失函数(在keras中)

[英]Seq2Seq models and loss functions( in keras)

我的seq2seq模型有一些问题,在某些情况下它的工作很好但在某些情况下它的返回结果只有结束标记。

例如 :

For given vector :
[2, #start token
3,
123,
1548, #end token
1548,
1548,
1548,
1548,
1548,
1548]

The model predict :
[1548, 
1548,
1548,
1548,
1548,
1548,
1548,
1548,
1548,
1548]

我试图使用来自keras的SaveModel回调监视“丢失”,但它仍然给出相同的结果。

所以我想,也许我应该使用自己的损失功能。

keras提供的简单损失函数:

def mean_absolute_error(y_true, y_pred):
    return K.mean(K.abs(y_pred - y_true), axis=-1)

y_true和y_pred都是tensorflow对象(我们只得到指向真实数组的指针)所以..为了创建一些逻辑,我们需要从gpu获取数组或将我自己的数组上传到gpu ..

我想要的损失功能

def mean_absolute_error(y_true, y_pred):
    sum = 0
    for y , _y in zip(y_true , y_pred):
         if (y == _y) and (y == self.startToken or y == self.endToken):
              continue
         else:
              sum += abs(y - _y)
    return sum

我试图使用y_true.eval(),它应该将数组作为numpy对象引入cpu(无法使用eval()来评估张量:没有注册默认会话)

我没有设法找到如何将我自己的数组上传到tensorflow。

如果您有解决方案或任何建议,我将非常乐意听到它。

谢谢..

(不是太重要但......)

该模型基于: https//blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html ,但有一个热点(两个暗淡[矩阵] )输出。

使用K.evalif in loss函数不是一个好主意。 关于张量的所有想法都是它们有一个由tensorflow / keras管理的内部连接,通过它可以计算渐变和其他东西。

使用eval并处理numpy值会破坏此连接并破坏模型。 仅使用eval查看结果,而不是创建功能。

使用if s将无效,因为张量值不可用。 但是有一些keras函数,如K.switchK.greaterK.less等,都在后端文档中列出。

您可以使用这些功能重新创建功能。

但老实说,我认为你应该选择“掩盖”或“阶级加权”。

掩蔽(解决方案1)

如果您正在使用嵌入图层,则可以有意为“结束后没有任何内容”保留零值。

然后,您可以在嵌入图层中使用mask_zero=True ,并输入如下:

[2, #start token
3,
123,
1548, #end token
0, #nothing, value to be masked
0,
0,
0,
0,
0]

另一个选择是没有“结束标记”而是使用“零”。

类权重(解决方案2)

由于这种情况很可能发生,因为您在期望的输出中拥有的结束标记多于其他任何结尾标记,因此可以降低结束标记的相关性。

计算输出中每个类的出现次数并计算结束标记的比率。 一个例子:

  • 计算所有其他类的出现的平均值
  • 计算结束标记的出现次数
  • ratio = other_classes_mean / end_token_occurences

然后在fit方法中,使用:

class_weight = {0:1, 1:1, 2:1, ...., 1548:ratio, 1549:1,1550:1,...}

可轻松实现:

class_weight = {i:1. for i in range(totalTokens)}
class_weight[1548] = ratio
model.fit(...,...,....., class_weight = class_weight,...)

(在这种情况下,确保您有0作为可能的类,或者将索引移动1)

类似的损失函数(解决方案3)

请注意, y_pred永远不会与y_true “相等”。

  • y_pred是可变的,连续的和可微分的
  • y_true是精确且恒定的

为了进行比较,您应该使用“argmax”,这与类索引(如果不完全相同)非常相似。

def mean_absolute_error(y_true, y_pred):

    #for comparing, let's take exact values
    y_true_max = K.argmax(y_true)
    y_pred_max = K.argmax(y_pred)

    #compare with a proper tensor function
    equal_mask = K.equal(y_true_max,y_pred_max)
    is_start = K.equal(y_true_max, self.startTokenAsIndex)
    is_end = K.equal(y_true_max, self.endTokenAsIndex)

    #cast to float for multiplying and summing
    equal_mask = K.cast(equal_mask, K.floatx()) 
    is_start = K.cast(is_start, K.floatx())
    is_end = K.cast(is_end, K.floatx())
        #these are tensors with 0 (false) and 1 (true) as float

    #entire condition as you wanted
    condition = (is_start + is_end) * equal_mask
        # sum = or ||| multiply = and
        # we don't have to worry about the sum resulting in 2
            # because you will never have startToken == endToken

    #reverse condition:
    condition = 1 - condition

    #result
    return condition * K.mean(K.abs(y_pred - y_true), axis=-1)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM