当前位置:   article > 正文

TF-IDF及相似度计算_tf-idf文本相似度计算

tf-idf文本相似度计算

一: 基于TF-IDF的关键词提取

TF-IDF:衡量某个词对文章的重要性由TF和IDF组成
TF:词频(因素:某词在同一文章中出现次数)
IDF:反文档频率(因素:某词是否在不同文章中出现)
TF-IDF = TF*IDF
TF :一个单词在一篇文章出现次数越多越重要
IDF: 每篇文章都出现的单词(如的,你,我,他) ,越不重要

 TFIDF的主要思想

如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TFIDF实际上是:TF * IDF, TF词频(Term Frequency),IDF反文档频率(Inverse Document Frequency)。
TF表示词条在文档d中出现的频率(另一说:TF词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数)。

IDF的主要思想是:

如果包含词条t的文档越少,也就是n越小,IDF越大(见后续公式),则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。(另一说:IDF反文档频率(Inverse Document Frequency)是指果包含词条的文档越少,IDF越大,则说明词条具有很好的类别区分能力。)但是实际上,有时候,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处.

TF-IDF例子:

词频 (TF) 是一词语出现的次数除以该文件的总词语数。假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (DF) 的方法是测定有多少份文件出现过“母牛”一词,然后除以文件集里包含的文件总数。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 log(10,000,000 / 1,000)=4。最后的TF-IDF的分数为0.03 * 4=0.12。
其他例子:
这里写图片描述

二: 相似度计算公式

(1)余弦相似度cosine
                举例:A(1,2,3) B(2,3,4)
                cosine(A, B) = 分子 / 分母 = 20 / 20.12 =
                分子:A*B = 1*2 + 2*3 + 3*4 = 20
                分母:    ||A||*    ||B|| = 3.74 * 5.38 = 20.12
                            ||A|| = sqrt(A*A) = sqrt(1*1 + 2*2 + 3* 3) = 3.74
                            ||B|| = sqrt(B*B) = sqrt(4*4 + 2*2 + 3* 3) = 5.38

A表示一个句子,B表示另外一个句子

            cosine(A, B) = 表示两个句子的相似程度
(二)Jaccard 相似度:
A 用户(香蕉、苹果、鸭梨)
B 用户(苹果、橘子、桃子)
A∩B=苹果 1
A∪B=香蕉、苹果、鸭梨、橘子、桃子 5
相似度为1/5=0.2
  1. # Step 1 文件整合 把不同文本整合到一起
  2. import os
  3. import sys
  4. import math
  5. file_path_dir = './data'
  6. raw_path = './raw.data'
  7. idf_path = './idf.data'
  8. def read_file_handler(f):
  9.     fd = open(f, 'r', encoding='utf-8')
  10.     return fd
  11. file_raw_out = open(raw_path, 'w', encoding='utf-8')
  12. # 遍历整个原始数据目录,将零散的文章整合到一个文件中,便于后续数据处理
  13. file_name = 0
  14. for fd in os.listdir(file_path_dir):
  15.     file_path = file_path_dir + '/' + fd
  16.     content_list = []
  17.     file_fd = read_file_handler(file_path)
  18.     for line in file_fd:
  19.         content_list.append(line.strip())
  20.     content = '\t'.join([str(file_name), ' '.join(content_list)]) + '\n'
  21.     file_raw_out.writelines(content)
  22.     file_name += 1
  23. file_raw_out.close()
  24. # Step 2 输出IDF
  25. docs_cnt = file_name
  26. wc_tulist = []
  27. with open(raw_path, 'r', encoding='utf-8'as fd:
  28.     for line in fd:
  29.         # 遍历每一篇文章,文章=line
  30.         ss = line.strip().split('\t')
  31.         if len(ss) != 2:
  32.             continue
  33.         # 对文章的解析,区分出文章的名字和文章的内容
  34.         file_name, file_content = ss
  35.         # 对文章的内容进行切词,因为内容已经按“ ”空格区分好了,所以直接按空格做split就好
  36.         word_list = file_content.strip().split(' ')
  37.         # 去重:对于idf,只关心词有没有出现在文章中,至于出现多少次,并不关心
  38.         word_set = set(word_list)
  39.         for word in word_set:
  40.             # 对于每个关键词,打一个标记“1”,来标识该次出现过
  41.             wc_tulist.append((word, '1'))
  42. # 将内容输出到指定目标文件中去
  43. file_idf_out = open(idf_path, 'w', encoding='utf-8')
  44. # 按照词的字典序,进行排序
  45. wc_sort_tulist = sorted(wc_tulist, key=lambda x: x[0])
  46. current_word = None
  47. sum = 0
  48. for tu in wc_sort_tulist:
  49.     word, val = tu
  50.     if current_word == None:
  51.         current_word = word
  52.     if current_word != word:
  53.         # 通过idf计算公式,得到每个关键词的idf score
  54.         idf = math.log(float(docs_cnt) / (float(sum) + 1.0)) idf公式
  55.         content = '\t'.join([current_word, str(idf)]) + '\n'
  56.         file_idf_out.write(content)
  57.         current_word = word
  58.         sum = 0
  59.     sum += int(val)
  60. idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
  61. content = '\t'.join([current_word, str(idf)]) + '\n'
  62. file_idf_out.write(content)
  63. file_idf_out.close()
  64. # Step 3
  65. input_str = '我们 带来 阿里巴巴 希望 差 我们 我们 我们'
  66. token_idf_dict = {}
  67. # 将idf字典加载到内存
  68. with open(idf_path, 'r', encoding='utf-8'as fd:
  69.     for line in fd:
  70.         ss = line.strip().split('\t')
  71.         if len(ss) != 2:
  72.             continue
  73.         token, idf_score = ss
  74.         token_idf_dict[token] = idf_score
  75. def get_tfidf(input_str):
  76.     token_dict = {}
  77.     # 对输入字符串的每一个词,计算tf
  78.     for t in input_str.strip().split(' '):
  79.         if t not in token_dict:
  80.             token_dict[t] = 1
  81.         else:
  82.             token_dict[t] += 1
  83.     # res_tu_list = []
  84.     for k, v in token_dict.items():
  85.         tf_score = token_dict[k]
  86.         if k not in token_idf_dict:
  87.             continue
  88.         idf_score = token_idf_dict[k]
  89.         tf_idf = tf_score * float(idf_score)
  90.         yield (k, tf_idf)
  91. for k, v in get_tfidf(input_str):
  92.     print(k, v)
  93. 求cos
  94. # Step 1: Cosine
  95. input1_str = '我们 带来 阿里巴巴 希望 差 差 差'
  96. # input2_str = '我们 带来 阿里巴巴 好 好 好'
  97. # input2_str = '我们 带来 搜狐 好 好 好'
  98. input2_str = '你们 带来 搜狐 希望 好 好 好'
  99. def cosine(input1_str, input2_str):
  100.     t1_dict = {}
  101.     sum = 0.
  102.     for k, v in get_tfidf(input1_str):
  103.         sum += pow(v, 2)
  104.     sum = math.sqrt(sum)
  105.     for k, v in get_tfidf(input1_str):
  106.         t1_dict[k] = float(v / sum)
  107.     sum = 0.
  108.     for k, v in get_tfidf(input2_str):
  109.         sum += pow(v, 2)
  110.     sum = math.sqrt(sum)
  111.     final_score = 0.
  112.     for k, v in get_tfidf(input2_str):
  113.         if k not in t1_dict:
  114.             continue
  115.         s1 = t1_dict[k]
  116.         s2 = float(v / sum)
  117.         final_score += s1 * s2
  118.     return final_score
  119. print(cosine(input1_str, input2_str))

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/753462
推荐阅读
相关标签
  

闽ICP备14008679号