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

标签 python tensorflow keras keras-layer loss-function

我的 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() 评估张量:没有注册默认 session )

而且我没能找到如何将我自己的数组上传到 tensorflow 中。

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

谢谢..

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

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

最佳答案

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

使用 eval 并处理 numpy 值将打破这种联系并破坏模型。使用 eval 只是为了查看结果,而不是为了创建函数。

使用 if 将不起作用,因为张量的值不可用。但是还有keras函数,比如K.switch, K.greater, K.less等,都列在backend documentation中。

您可以使用这些函数重新创建您的函数。

但老实说,我认为您应该改用“屏蔽”或“类权重”。

掩蔽(方案一)

如果您正在使用嵌入层,您可以有意为“结束后什么都没有”保留零值。

然后您可以在嵌入层中使用 mask_zero=True 并具有如下所示的输入:

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

另一种选择是不使用“结束标记”,而是使用“零”。

类加权(方案二)

由于这很可能会发生,因为您的结束标记比所需输出中的任何其他内容都多得多,因此您可以降低结束标记的相关性。

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

  • 计算所有其他类出现的平均值
  • 统计结束标记的出现次数
  • 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)

关于python - Seq2Seq 模型和损失函数(在 keras 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49473541/

相关文章:

python - 无法将类型 'myFuncDef *' 分配给 'void (*)(double *, double *)'

查找连续重复的单词时 Python 后视正则表达式 "fixed-width pattern"错误

machine-learning - "logits and labels must be same size: logits_size=[10,2] labels_size=[10,11]"

python - 获取与 TensorFlow 中特定张量相关的所有 tf​​.Variables

Python3错误: AttributeError: module 'urllib' has no attribute 'request'

python - Pandas :用 0 替换非数字单元格

python - 使用 protobuf 从 tfrecords 文件中提取图像而不运行 TensorFlow session

tensorflow - 在 Keras 中使用 binary_crossentropy 损失(Tensorflow 后端)

tensorflow - 在每个时间步提取 LSTM 模型的隐藏状态向量

python - Keras Python自定义损失函数给出张量(绝对差)的最大值?