Python Seq2Seq模型和损失函数(单位:keras)
我的seq2seq模型有些问题 在某些情况下,它的工作很好,但在某些情况下,它的返回结果只是结束标记 例如:Python Seq2Seq模型和损失函数(单位:keras),python,tensorflow,keras,keras-layer,loss-function,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的Sav
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中
如果你有一个解决方案或任何建议,我将非常高兴听到
谢谢
(不太重要,但…)
该模型基于:,但具有一个热(两维[矩阵])输出。在损失函数中使用
K.eval
或if
,不是一个好主意。关于张量的所有想法是,它们有一个由tensorflow/keras管理的内部连接,通过它可以计算梯度和其他东西
使用eval
并处理numpy值将中断此连接并破坏模型。使用eval
只能查看结果,不能创建函数
因为张量值不可用,所以如果使用if
s将不起作用。但也有keras功能,如K.switch
、K.greater
、K.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)
由于这很可能是因为您在所需输出中拥有比其他任何东西多得多的结束标记,因此您可以降低结束标记的相关性
计算输出中出现的每个类,并计算结束标记的比率。例如:
- 计算所有其他类别的平均值
- 统计结束标记的出现次数
比率=其他类别\u平均值/结束\u标记\u发生次数
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
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)
在您提供的链接中,他们在看到结束标记后停止预测;明确地在
decode_sequence
函数中:#退出条件:点击最大长度或查找停止字符。
它们还使用起始字符预先填充模型的输出数组:#使用起始字符填充目标序列的第一个字符。
我想知道您是否使用了类似的函数对于他们的decode\u sequence
功能?不,使用:model.predict([x,x])可以更容易地完成,但这可能是问题的原因。试着完全按照他们的decode\u序列
功能进行操作,然后看看是否可以先执行。这可能是在Keras中预测的唯一方法。我已经检查过了。。。这是一样的…哇,老兄,你太棒了。。我从来不知道重量选项。我想在Keras的服务器端站稳脚跟,所以你帮了我大忙。。谢谢