本节书摘来自异步社区《Python数据科学指南》一书中的第1章,第1.5节,作者[印度] Gopi Subramanian ,方延风 刘丹 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。
除了不能存在重复值,集合和列表十分相似。集合是无序的同类元素的集合,通常情况下,集合被用来删除列表中的重复值。集合支持交集、并集、差集和对称差等操作,这些操作在许多用例中都十分便于使用。
在这节中,我们会写一小段代码来帮助理解集合数据结构的不同用途。在这个实例里,我们将使用Jaccard系数来计算两句话的相似度,并对Jaccard系数进行详细的讲述,在后续的章节里,我们还会介绍相似的其他度量方法。先给Jaccard系数来一个简要的介绍:它是介于0到1的数值,1表示高相似度,它的计算方法基于两个集合中存在的共同元素数量。
让我们来看看创建和维护集合的Python代码。
# 1.初始化两个句子 st_1 = "dogs chase cats" st_2 = "dogs hate cats" # 2.从字符串中创建词的集合 st_1_wrds = set(st_1.split()) st_2_wrds = set(st_2.split()) # 3.找出每个集合中不重复的词总数,即词表大小 no_wrds_st_1 = len(st_1_wrds) no_wrds_st_2 = len(st_2_wrds) # 4.找出两个集合中共有的词,保存到列表中,并统计总数 cmn_wrds = st_1_wrds.intersection(st_2_wrds) no_cmn_wrds = len(st_1_wrds.intersection(st_2_wrds)) # 5.找出两个集合并集中不重复的词,保存到列表中,并统计总数 unq_wrds = st_1_wrds.union(st_2_wrds) no_unq_wrds = len(st_1_wrds.union(st_2_wrds)) # 6.计算Jaccard相似度 similarity = no_cmn_wrds / (1.0 * no_unq_wrds) # 7.打印输出 print "No words in sent_1 = %d"%(no_wrds_st_1) print "Sentence 1 words =", st_1_wrds print "No words in sent_2 = %d"%(no_wrds_st_2) print "Sentence 2 words =", st_2_wrds print "No words in common = %d"%(no_cmn_wrds) print "Common words =", cmn_wrds print "Total unique words = %d"%(no_unq_wrds) print "Unique words=",unq_wrds print "Similarity = No words in common/No unique words, %d/%d \ =%.2f"%(no_cmn_wrds,no_unq_wrds,similarity)在第1步和第2步中,我们将两句话切分成多个词,并用set()函数创建了两个集合,set()函数可以将列表或者元组转为集合类型,请看下面的示例。
>>> a =(1,2,1) >>> set(a) set([1, 2]) >>> b =[1,2,1] >>> set(b) set([1, 2])在这个示例中,a是一个元组,b是一个列表,通过set()函数,重复的元素被丢弃,并返回一个集合对象。st_1.split()和st_2.split()方法返回一个列表,我们将它传递给set函数来获取集合对象。
现在我们用Jaccard系数计算两个句子之间的相似度,并对Jaccard系数进行详细的讲述,在后续的章节里,我们还会在“相似度计算”部分介绍其他的度量方法。我们使用union()和intersection ()函数对集合进行操作来计算相似度。
我们在第4步执行了两个操作,第1个是intersection ()函数,由此我们找出了两个集合中的共有的词分别是“cats”和“dogs”,共有的词数量为2。接下来,我们用union()将两个集合进行并集,然后将不重复的那些词列出来,分别是:“cats”“hate”“dogs”和“chase”。这在自然语言处理中被称为词表。最后,我们在第6步中计算Jaccard系数,即两个集合共有的词数量与两个集合并集中不重复的词总数的比值。
输出的结果如下。
No words in sent_1 = 3 Sentence 1 words = set(['cats', 'dogs', 'chase']) No words in sent_2 = 3 Sentence 2 words = set(['cats', 'hate', 'dogs']) No words in common = 2 Common words = set(['cats', 'dogs']) Total unique words = 4 Unique words= set(['cats', 'hate', 'dogs', 'chase']) Similarity = No words in common/No unique words, 2/4 = 0.50我们在上面的实例中演示了集合的函数的用法。此外,你也可以从scikit-learn之类的库中使用内置函数。我们将尽可能多地使用这些函数,而不必自己亲自写那些集合的应用函数。
# 加载库 from sklearn.metrics import jaccard_similarity_score # 1.初始化两个句子 st_1 = "dogs chase cats" st_2 = "dogs hate cats" # 2.从字符串中创建词的集合 st_1_wrds = set(st_1.split()) st_2_wrds = set(st_2.split()) unq_wrds = st_1_wrds.union(st_2_wrds) a =[ 1 if w in st_1_wrds else 0 for w in unq_wrds ] b =[ 1 if w in st_2_wrds else 0 for w in unq_wrds] print a print b print jaccard_similarity_score(a,b)输出的结果如下。
[1, 0, 1, 1] [1, 1, 1, 0] 0.5