我一直在关注一个教程,该教程显示了如何制作word2vec模型。
本教程使用以下代码:
similarity = merge([target, context], mode='cos', dot_axes=0)
(未提供其他信息,但我想这来自keras.layers
)
现在,我已经对merge
方法进行了一些研究,但是找不到很多。
据我了解,它已被layers.Add(), layers.Concat()...
之类的许多功能所取代。
我应该使用什么?有.Dot()
,它有一个axis
参数(看起来是正确的),但没有mode
参数。
在这种情况下我可以使用什么?
答案 0 :(得分:12)
Keras文档中有一些尚不清楚的地方,我认为必须理解:
在keras文档中,Merge
的每个函数都有一个小写和一个大写的定义,即add()
和Add()
。
在Github上,farizrahman4u
概述了差异:
Merge is a layer.
Merge takes layers as input
Merge is usually used with Sequential models
merge is a function.
merge takes tensors as input.
merge is a wrapper around Merge.
merge is used in Functional API
Using Merge:
left = Sequential()
left.add(...)
left.add(...)
right = Sequential()
right.add(...)
right.add(...)
model = Sequential()
model.add(Merge([left, right]))
model.add(...)
using merge:
a = Input((10,))
b = Dense(10)(a)
c = Dense(10)(a)
d = merge([b, c])
model = Model(a, d)
要回答您的问题,由于Merge
已过时,我们必须为cosine similarity
定义并构建一个层。通常,这将涉及使用小写的函数,这些函数将我们包装在Lambda
中,以创建可在模型中使用的层。
我找到了解决方法here:
from keras import backend as K
def cosine_distance(vests):
x, y = vests
x = K.l2_normalize(x, axis=-1)
y = K.l2_normalize(y, axis=-1)
return -K.mean(x * y, axis=-1, keepdims=True)
def cos_dist_output_shape(shapes):
shape1, shape2 = shapes
return (shape1[0],1)
distance = Lambda(cosine_distance, output_shape=cos_dist_output_shape)([processed_a, processed_b]
根据您的数据,您可能需要删除L2规范化。需要注意的是该解决方案是使用Keras函数api构建的,例如K.mean()
-我认为在定义自定义图层甚至损失函数时这是必要的。
希望我很清楚,这是我的第一个SO答案!
答案 1 :(得分:10)
Keras中的Dot
层现在支持使用normalize = True
参数的内置余弦相似度。
来自Keras文档:
keras.layers.Dot(axes, normalize=True)
归一化:在获取点积之前是否沿点积轴对样本进行L2归一化。如果设置为True,则点积的输出是两个样本之间的余弦接近度。
答案 2 :(得分:0)
如果您按如下方式更改本教程的最后一个代码块,您可以看到(平均)损失在使用 SantoshGuptaz7 建议的 Dot 解决方案时很好地降低(在上述问题中的评论):
display_after_epoch = 10000
display_after_epoch_2 = 10 * display_after_epoch
loss_sum = 0
for cnt in range(epochs):
idx = np.random.randint(0, len(labels)-1)
arr_1[0,] = word_target[idx]
arr_2[0,] = word_context[idx]
arr_3[0,] = labels[idx]
loss = model.train_on_batch([arr_1, arr_2], arr_3)
loss_sum += loss
if cnt % display_after_epoch == 0 and cnt != 0:
print("\nIteration {}, loss={}".format(cnt, loss_sum / cnt))
loss_sum = 0
if cnt % display_after_epoch_2 == 0:
sim_cb.run_sim()