Jaccard笔记

计算两个集合的交集和并集的之间的比率,叫作 Jaccard 相似度(雅可比相似度)。似乎 Jaccard 又和 Tanimoto 有着相同的意思,只是 Tanimoto 在处理图形时,公式才不一样。

有两个集合,比如:

S集合:S = {1,2,3}

T集合:T = {1,3,5}

|S 交 T| / |S 并 T|,就可以得到它们之间的 Jaccard 相似度。

产生的值的范围是 0~1,也就说,结果的区间为 [0,1]。如果结果等于 0,则两个集合不相交;当结果为 1 时,两个集合相等;其他情况中,结果越趋向于 1,相似度越高,反之更不相似。

Jaccard 有个缺点:分子如果不变,随着分母越大,产生的值就越小。

这个方法可以应用到简单的文章抄袭识别上。比如《网络协议本质论》中有这么一段话:

NetBIOS 全称 NetWork Basic Input/Output System (网络基本输入/输出系统) 该协议是由IBM 公司开发,主要用于数十台计算机的小型局域网。NetBIOS 协议是一种局域网上程序可 以使用的应用程序编程接口(API),为程序提供了请求低级服务的统一的命令集,作用是为了给局域网提供网络以及其他特殊功能,几乎所有的局域网都是在NetBIOS协议的基础上工作的。在 Windows 操作系统中,默认情况下在安装 TCP/IP 协议后会自动安装 NetBIOS。比 如在 Windows 2000/XP 中,当选择“自动获得 IP”后会启用DHCP服务器,从该服务器使用 NetBIOS 设置;如果使用静态 IP 地址或 DHCP 服务器不提供 NetBIOS 设置,则启用 TCP/IP 上的 NetBIOS。具体的设置方法如下:首先打开“控制面板” ,双击“网络连接”图标,打开 本地连接属性。接着,在属性窗口的“常规”选项卡中选择“Internet 协议(TCP/IP),单击 ” “属性”按钮。然后在打开的窗口中,单击“高级”按钮;在“高级 TCP/IP 设置”窗口中选 择“WINS”选项卡,在“NetBIOS 设置”区域中就可以进行相应的 NetBIOS 设置。

另外 NetBIOS 在百度百科是这么描述的:

NETBIOS协议是由IBM公司开发,主要用于数十台计算机的小型局域网。该协议是一种在局域网上的程序可以使用的应用程序编程接口(API),为程序提供了请求低级服务的统一的命令集,作用是为了给局域网提供网络以及其他特殊功能,系统可以利用WINS服务、广播及Lmhost文件等多种模式将NetBIOS名解析为相应IP地址,实现信息通讯,所以在局域网内部使用NetBIOS协议可以方便地实现消息通信及资源的共享。因为它占用系统资源少、传输效率高,所以几乎所有的局域网都是在NetBIOS协议的基础上工作的。

然后我们计算 Jaccard 相似度:

def splitWord(content):
   '''按逗号和句号分割句子'''
   sentence = []

   if content.find(','):
      sentence.extend(content.split(','))

   if content.find('。'):
      sentence.extend(content.split('。'))

   return sentence

if __name__ == '__main__':
   with open('fromBook','r') as fromBook:
      fromBookContent = splitWord(fromBook.read())

   with open('fromBaike','r') as fromBaike:
      fromBaikeContent = splitWord(fromBaike.read())

   fromBookSet = set(fromBookContent)
   fromBaikeSet = set(fromBaikeContent)

   # 交集/并集。+0.0 是为了让结果成为 float 类型
   print(len(fromBookSet.intersection(fromBaikeSet))+0.0)/len(fromBookSet.union(fromBaikeSet))

代码原理是这样的:把一段文字看作是一个集合,每一句话(通过句号和逗号分割)是集合中的一个元素,然后计算两个集合的 Jaccard 相似度。

运行结果:

$ python jaccard.py
0.0606060606061