【问题标题】:Measuring similarity between binary lists测量二进制列表之间的相似性
【发布时间】:2019-03-27 12:38:44
【问题描述】:

我有两个要比较的二进制列表。为了比较我对每个对应值相等的地方求和并将其转换为百分比:

import numpy as np

l1 = [1,0,1]
l2 = [1,1,1]

print(np.dot(l1 , l2) / len(l1) * 100)

打印 66.666

所以在这种情况下,l1 和 l2 的接近度为 61.666。由于每个列表不太相似,因此接近度值会降低。

例如使用值:

l1 = [1,0,1]
l2 = [0,1,0]

返回 0.0

如何绘制描述l1l2 之间关系的l1l2?有没有使用这种方法来测量二进制值之间相似度的名称?

使用散点图:

import matplotlib.pyplot as plt

plt.scatter( 'x', 'y', data=pd.DataFrame({'x': l1, 'y': l2 }))

产生:

但这没有意义?

更新:

"如果两个条目都是 0,这不会有助于你的“相似性”

使用下面的更新代码来计算相似度,这个更新的相似度度量在计算最终分数时包含对应的 0 值。

import numpy as np

l1 = [0,0,0]
l2 = [0,1,0]

print(len([a for a in np.isclose(l1 , l2) if(a)]) / len(l1) * 100)

返回:

66.66666666666666

或者,使用下面的代码和度量 normalized_mutual_info_score 对于相同或不同的列表返回 1.0,因此 normalized_mutual_info_score 不是合适的相似性度量?

from sklearn.metrics.cluster import normalized_mutual_info_score

l1 = [1,0,1]
l2 = [0,1,0]

print(normalized_mutual_info_score(l1 , l2))

l1 = [0,0,0]
l2 = [0,0,0]

print(normalized_mutual_info_score(l1 , l2))

打印:

1.0
1.0

【问题讨论】:

  • 为什么不简单地取两个集合的并集,并将其与集合的长度进行比较。似乎更容易
  • 您正在计算互相关(以百分比表示)。您确实意识到,这是一个不完美的相似性度量?具体来说,如果两个条目都是0,这不会有助于您的“相似性”。对于真正的相似性度量(在这种情况下,无论如何),我会计算归一化的互信息(例如,scikit-learn 中有一个实现)。
  • @PaulBrodersen 请查看问题更新。

标签: python matplotlib data-science similarity


【解决方案1】:

不,情节没有意义。您所做的本质上是向量之间的内积。根据这个度量,l1l2 应该是 3D(在这种情况下)空间中的向量,这可以衡量它们是否面向相同的相似方向并具有相似的长度。输出是一个标量值,所以没有什么要绘制的。

如果你想展示每个组件的个人贡献,你可以做类似的事情

contributions = [a==b for a, b in zip(l1, l2)]
plt.plot(list(range(len(contributions)), contributions)

但我仍然不确定这是否有意义。

【讨论】:

    【解决方案2】:
    import numpy as np
    import matplotlib.pyplot as plt
    
    def unpackbits(a, n):
        ''' Unpacks an integer `a` to n-length binary list. ''' 
        return [a >> i & 1 for i in range(n-1,-1,-1)]
    
    
    def similarity(a, b, n):
        ''' Similarity between n-length binary lists obtained from unpacking
        the integers a and b. '''
        a_unpacked = unpackbits(a, n)
        b_unpacked = unpackbits(b, n)
        return np.sum(np.isclose(a_unpacked, b_unpacked))/n
    
    
    # Plot
    n = 3
    x = np.arange(2**n+1)
    y = np.arange(2**n+1)
    xx, yy = np.meshgrid(x, x)
    z = np.vectorize(similarity)(yy[:-1,:-1], xx[:-1,:-1], n)
    
    labels = [unpackbits(i, n) for i in x]
    cmap = plt.cm.get_cmap('binary', n+1)
    
    fig, ax = plt.subplots()
    pc = ax.pcolor(x, y, z, cmap=cmap, edgecolor='k', vmin = 0, vmax=1)
    ax.set_xticks(x + 0.5)
    ax.set_yticks(y + 0.5)
    ax.set_xlim(0, 2**n)
    ax.set_ylim(0, 2**n)
    ax.set_xticklabels(labels, rotation=45)
    ax.set_yticklabels(labels)
    cbar = fig.colorbar(pc, ax=ax, ticks=[i/n for i in range(n+1)])
    cbar.ax.set_ylabel('similarity', fontsize=14)
    ax.set_aspect('equal', adjustable='box')
    plt.tight_layout()
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2014-04-08
      • 2018-01-29
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      相关资源
      最近更新 更多