【问题标题】:Computing cosine similarity between two tensor vectors in lambda layer?计算 lambda 层中两个张量向量之间的余弦相似度?
【发布时间】:2021-07-19 12:48:30
【问题描述】:

这是基本代码,

def euclidean_distance(vects):
    x, y = vects
    sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
    return K.sqrt(K.maximum(sum_square, K.epsilon()))

def eucl_dist_output_shape(shapes):
    shape1, shape2 = shapes
    return (shape1[0], 1)


# measure the similarity of the two vector outputs
output = Lambda(euclidean_distance, name="output_layer", output_shape=eucl_dist_output_shape)([output_a, output_b])

# specify the inputs and output of the model
model = Model([input_a, input_b], output)

我想使用余弦相似度(0 到 1 的尺度)而不是欧几里得距离来衡量两个向量之间的相似度,我尝试使用 scikit-learn 中的 cosine_similarity 但它不起作用。

那么,我们需要使用keras.backend 来构建它吗?谁能告诉我该怎么做?

【问题讨论】:

    标签: python tensorflow machine-learning keras deep-learning


    【解决方案1】:

    以前,在旧的keras 中,我们可以在merge 层中使用mode='cos',但在新的tf. keras 中已弃用。现在我们可以使用layers. Dot 层并指定normalize=True 表示余弦接近度余弦相似度 或(1 - 余弦距离)。根据doc

    tf.keras.layers.Dot(
        axes, normalize=False, **kwargs
    )
    

    normalize:在取点积之前是否沿点积轴L2-normalize样本。如果设置为 True,则 点积 的输出是两个样本之间的 余弦接近度

    因此,我们可以使用内置层计算两个样本的 余弦相似度。但是,当您寻求一种使用Lambda 层来包装自定义余弦相似度 函数的方法时,这里有一些使用它们的演示。

    from tensorflow.keras import backend as K
    from tensorflow.keras.layers import Lambda
    import tensorflow as tf 
    
    # computing cosine similarity 
    def cosine_similarity(vests):
        x, y = vests
        x = K.l2_normalize(x, axis=-1)
        y = K.l2_normalize(y, axis=-1)
        return K.batch_dot(x, y, axes=-1)
    
    def cos_sim_output_shape(shapes):
        shape1, shape2 = shapes
        return (shape1[0], 1)
    

    让我们抽取 2 个样本并运行它们以检查它们的相似性:

    # 2 samples 
    x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
    x2 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
    
    # (1). Wrap custom function into Lambda layer
    distance = Lambda(cosine_similarity, 
                      output_shape=cos_sim_output_shape)([x1, x2])
    print(distance.shape, distance.numpy())
    
    # (2). Use built-in method: Dot layer with normalize = True
    dotted = tf.keras.layers.Dot(axes=-1, normalize=True)([x1, x2])
    print(dotted.shape, dotted.numpy())
    
    (5, 1) [[-0.22463222]
     [-0.22639492]
     [-0.2283202 ]
     [-0.22915731]
     [-0.22962123]]
    
    (5, 1) [[-0.22463222]
     [-0.22639492]
     [-0.2283202 ]
     [-0.22915731]
     [-0.22962123]]
    

    【讨论】:

    • 其实这个我试过了,还是不行,我需要的不是度量或损失函数,而是一种计算模型中N维上两个密集向量的余弦相似度的方法,我可以在上面的 lambda 层中使用。输出应该是 (N, 1)
    • @user_12 立即查看。
    【解决方案2】:

    以下文章详细介绍了如何计算余弦相似度。我使用同一篇文章创建了一个简单的示例:

    文章: https://towardsdatascience.com/cosine-similarity-how-does-it-measure-the-similarity-maths-behind-and-usage-in-python-50ad30aad7db

    例子:

    import tensorflow as tf
    from tensorflow.keras.layers import Lambda
    
    A = tf.constant([7,3])
    B = tf.constant([3,7])
    
    # cosine similarity between A and B using numpy
    
    def cos_sim(vects):
      A, B = vects
      cos_sim=np.dot(A,B)/(np.linalg.norm(A)*np.linalg.norm(B))
      return cos_sim
    
    output = Lambda(cos_sim, name="output_layer")([A, B])
    
    >>>output: 0.7241379310344827
    

    【讨论】:

      猜你喜欢
      • 2017-09-07
      • 2018-12-02
      • 2019-12-27
      • 2010-10-05
      • 2016-03-06
      • 1970-01-01
      • 2019-12-02
      • 2015-07-21
      • 2018-07-28
      相关资源
      最近更新 更多