如何在张量流中对张量的列执行相似函数

how to perform similarity function over columns of a tensor in tensorflow

我有这样的张量:

tf_a1 =      [[-0.65 0.   0.   0.   0.42  0.   0.   0.51 0.   0.34 0.]
              [0.   -0.51 0.   0.  -0.52  0.   0.   0.   0.53 0.42 0.]
              [0.    0.32 0.  -0.50 0.34  0.   0.   0.39 0.32 0.52 0.]
              [0.    0.23 0.37 0.   0.    0.37 0.37 0.   0.47 0.39 0.3 ]]

我想对这个张量的每一列应用 cosine similarity。所以,我想找出第一列与其余列的相似性。同样,第二列与其余列相对应。

我是这样使用 for 循环完成的:

def cosine_score(x):
    for i, arr in enumerate(x):
        if i == 0 :
            first = cosine_similarity(x[i,].reshape(1, -1), x)
        else:
            second = cosine_similarity(x[i,].reshape(1, -1), x)
            final = tf.concat((first, second), axis=0)
            first = final
    return final
sim_topics = cosine_score(tf_a1)

现在,当我想将它包含在我的模型中时,我不能按原样使用 foor 循环。看来我必须使用 tf.map_fn 来检查它。

我也这样做过:

def cosine_score(x):
    def cos_similarity(col):
        for i, arr in enumerate(col):
            if i == 0:
                first = cosine_similarity(col[i, ].reshape(1, -1), col)
            else:
                second = cosine_similarity(col[i, ].reshape(1, -1), col)
                final = tf.concat((first, second), axis=0)
                first = final
        return final
    sim = tf.map_fn(cos_similarity, x, dtype=tf.float32)
    return sim

但是这里我需要去掉for loop。我的问题是,如果我删除 for loop 并分别访问每一列,我如何访问其余列以比较和应用 cosine similarity.

如果不清楚请告诉我。

余弦相似度只不过是一个 L2 归一化点积。所以,在 Tensorflow 中,这应该可以解决问题:

# Normalize the columns of the tensor
normalized_tensor = tf.math.l2_normalize(tf_a1, axis=0)
# Get the dot product between the columns
scores = tf.matmul(normalized_tensor, normalized_tensor, transpose_a=True)

张量scores包含tf_a1列之间的余弦相似度。此外,下面是一个 Numpy 等效的实现:

# Normalize the columns of the tensor
normalized_tensor = tf_a1 / np.linalg.norm(tf_a1, axis=0)
# Get the dot product between the columns
scores = np.dot(normalized_tensor.T, normalized_tensor)

最后,如果只想保留其中一个三角形(例如上三角),将主对角线设置为0,可以在Tensorflow中进行如下操作:

zero_diag = tf.linalg.set_diag(scores, tf.zeros(tf.shape(scores)[0]))
triangular = tf.matrix_band_part(zero_diag, 0, -1)