我试图用Keras实现一个暹罗网络,我有两个输入数据,
X1形状:(10000,52)X2形状:(10000,600)
假设X1中的每个样本与X2中的样本相似。例如:X1[0]与X2[0]相似。因此,当两个输入合并时,我使用"余弦相似度"。我试图使用以下代码:
def contrastive_loss(y_true, y_pred):
'''Contrastive loss from Hadsell-et-al.'06
http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
'''
margin = 1
return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0)))
left_branch = Sequential()
left_branch.add(Embedding(1000, 32, input_length=52))
left_branch.add(LSTM(64))
left_branch.add(Dense(256))
right_branch = Sequential()
right_branch.add(Embedding(1000, 32, input_length=600))
right_branch.add(LSTM(64))
right_branch.add(Dense(256))
merged = Merge([left_branch, right_branch], mode='cos',dot_axes=1)
final_model = Sequential()
final_model.add(merged)
final_model.summary()
x1 = np.random.randint(1000, size=(10000, 52))
x2 = np.random.randint(1000, size=(10000, 600))
y = np.ones((10000,),dtype=np.int)
final_model.compile(optimizer='adam', loss=contrastive_loss)
final_model.fit([x1, x2], y, nb_epoch=2, batch_size=32)
getoutput_t = K.function([merged.layers[0].layers[0].input], [merged.layers[0].layers[2].output])
getoutput_d = K.function([merged.layers[1].layers[0].input], [merged.layers[1].layers[2].output])
t1 = getoutput_t([x1])[0]
t2 = getoutput_d([x2])[0]
我的问题是:训练后,t1[0]与t1[1]非常相似,但与t2[0]非常不同。我检查了t1和t2的输出,生成的输出很奇怪:
t1:
array([[-3.48182112e-01, 6.57344190e-03, -6.75882818e-03,4.11706511e-03, -2.41146213e-03, -1.14028137e-02,2.49683809 e + 00, -9.19755269 e 03, -2.37327255 e-02…]
[-3.48182231e-01, 6.57369522e-03, -6.75880583e-03]4.11719829e-03, -2.41167075e-03, -1.14026833e-02,[2.49683785e+00, -9.19752941e-03, -2.37324722e-02,…].......]])
t1[0]与t1[1]基本相同,t2也存在相同的问题。
因此,我不得不考虑:
我的暹罗模型有问题吗?(如损失函数或层设计)
到目前为止我没有负采样,因此,目标值是"1",这是问题吗?
只有正对才是问题
目标值是"1",这是问题吗?
你的意思是你没有负/异对,那么是的,这是一个问题。如果这不是你的情况,请忽略这个答案的其余部分。
为什么只有正对是一个问题
在源代码中引用的论文的第3页:
涉及不同对的对比项LD是至关重要的。在所有相似对的集合上简单地最小化DW (X~ 1, X~ 2)通常会导致一个崩溃的解决方案,因为DW和损失L通过将GW设置为常数,可以使为零。大部分能源模型要求在损失中使用明确的对比项函数。
其中"对比项"是依赖于负对的损失函数项。方程3中的L_D。请注意,GW是从输入到输出向量的模型/映射。基本上,在没有负对的情况下,学习器可以通过学习一个简单的模型来实现其优化目标(即最小化相似/正对之间的距离),该模型只是将输入向量映射到相同的输出向量。
直观地说,对比损耗可以帮助你找到最优模型,通过迫使它平衡最小化相似对之间的距离,同时使用相同的参数在GW中设置最大化不同对之间的距离。
如果没有负对,如何生成负对
如果你没有负对,你可以尝试通过随机配对数据集中的元素来生成负对。
在Keras主库中有一个使用对比丢失的例子:
https://github.com/fchollet/keras/blob/master/examples/mnistrongiamese_graph.py