我的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,但有一个热点(两个暗淡的[矩阵])输出。
答案 0 :(得分:2)
在损失函数中使用K.eval
或if
不是一个好主意。关于张量的所有想法都是它们具有由tensorflow / keras管理的内部连接,通过它可以计算渐变和其他事物。
使用eval
并处理numpy值会破坏此连接并破坏模型。仅使用eval
查看结果,而不是创建功能。
使用if
s将无效,因为张量值不可用。但有一些keras函数,例如K.switch
,K.greater
,K.less
等,都列在backend documentation中。
您可以使用这些功能重新创建功能。
但老实说,我认为你应该选择"掩盖"或者"班级加权"代替。
如果你正在使用嵌入图层,你可以故意保留零值,而不会在结束后保留任何值#34;
然后,您可以在嵌入图层中使用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)
请注意y_pred
永远不会#34;等于"到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)