发现更大的SEO世界
 找回密码
 注册
搜索
»首页»SEO培训 SEO论坛 SEO交流 帖子
发新帖
刀心,前来膜拜各位大神    

分享自用小工具:TF-IDF计算文档相似性的python实现

本帖最后由 刀心 于 2016-4-7 15:16 编辑

最近要失业了,过渡期上班没太多活,于是捣鼓一下这些东西。

先来说说实现思路
1、我从我的数据库中获取了一些文章的title
2、将title用jieba分词进行分词
3、使用一些第三方库计算出词频向量(其中计算方法不明)
4、根据每两篇文档的词频向量计算其余弦相似性。公式如下图
公式.png
5、根据人肉观察和计算结果,设定一个阀值,作为相似性推荐的参数值

需要安装的库有:
sklearn,jieba,simplejson,还有一个翻译包,不过可以改改代码 然后不安装这个包。

测试结果:
        1、两个完全相同的标题,得到的最大值是1.0。
        2、两个完全不相同的标题,得到的最小值是0.0。
        3、150行标题,计算速度是0.0xxx,速度还算可以。
        4、10万行标题,计算速度是40秒左右,算是非常慢了。如果后续有优化版本,我会再放上来,毕竟支持大量文章中筛选出相似文章才是硬需求。
        5、感觉0.5以上就挺相似的了。

脚本包注意事项:
1、我的站点是个繁体的站点,从中选出的标题jieba不能进行分词,于是我翻译后再分词的,还需要一个翻译包点击我
2、开始是想自己用,于是中间在用json转来转去,现在感觉没必要,大家可以改改。

代码如下,我觉得可以扩展一下直接使用。这里的代码高亮看起来舒服些

  1. #!/usr/local/bin/python
  2. #coding=utf-8
  3. # daoxin 2016-3
  4. import json, simplejson, sys, re
  5. reload(sys)
  6. sys.setdefaultencoding('utf8')
  7. import jieba, time
  8. import string
  9. from sklearn import feature_extraction
  10. from sklearn.feature_extraction.text import TfidfTransformer
  11. from sklearn.feature_extraction.text import CountVectorizer
  12. from collections import Counter
  13. import math
  14. #导入翻译模块;去git下载吧
  15. sys.path.append('/Users/movespeed/Desktop/Python/fanti_jianti')  #文件路径自己修改
  16. from zhtools.langconv import *
  17. #翻译模块结束
  18. """
  19.     cutWord function , save cut word results into json file
  20. """


  21. def cutWord():
  22.     f = open('/Users/movespeed/Desktop/Python/title.json')  #文件路径自己修改
  23.     """
  24.         Open source file
  25.     """
  26.     jiebafile = open('/Users/movespeed/Desktop/Python/jiebafile.json', 'w+'
  27.                      )  #文件路径自己修改
  28.     """
  29.         save cutword result into a json file
  30.     """
  31.     while 1:
  32.         line = f.readline()
  33.         if not line:
  34.             break
  35.         else:
  36.             title = json.loads(line)['title']
  37.             t_id = json.loads(line)['id']
  38.             tf_idf = json.loads(line)['tf-idf']
  39.             #seg_list =  jieba.cut(title, cut_all=True)#the jieba cut function
  40.             title = Converter('zh-hans').convert(
  41.                 title.decode('utf-8')
  42.             )  # Translate func for jieba can't cut cht.
  43.             #print title
  44.             seg_list = jieba.cut(title, cut_all=True)  #the jieba cut function

  45.             seg_list = str(",".join(seg_list))
  46.             seg_list = seg_list.split(',')
  47.             #print seg_list
  48.             result = []
  49.             for seg in seg_list:
  50.                 seg = ','.join(seg.split(',')).decode('utf-8')
  51.                 if (seg != '' and seg != "\n" and seg != "\n\n" and
  52.                         seg != "_" and seg != "," and seg != "|"):
  53.                     result.append(seg)
  54.             jsoninfo = json.dumps({"id": t_id,
  55.                                    "title": title,
  56.                                    "cut_word": result,
  57.                                    "tf_idf": None})
  58.             jiebafile.write(jsoninfo + '\n')

  59. #The testting of cut word function
  60. #cutWord()
  61. """
  62.     vector-values counter function
  63. """
  64. filelist = open('/Users/movespeed/Desktop/Python/jiebafile.json', 'r'
  65.                 )  #文件路径自己修改


  66. # Change json infomation into list , every item contains some chinese word split by one space
  67. def ChangeJsonIntoList(filelist):
  68.     vectorList = list()
  69.     for doc in filelist.readlines():
  70.         #jsoninfo = str(json.loads(doc)['cut_word']).replace(',', '')
  71.         jsoninfo = ' '.join(json.loads(doc)['cut_word'])
  72.         #print jsoninfo
  73.         #print type(jsoninfo)
  74.         vectorList.append(jsoninfo)
  75.     return vectorList


  76. # tf_idf function, return tfidf array
  77. def Tf_Idf(vectorList):
  78.     vectorizer = CountVectorizer()

  79.     X = vectorizer.fit_transform(vectorList)
  80.     counts = X.toarray()

  81.     transformer = TfidfTransformer()
  82.     tfidf = transformer.fit_transform(counts)

  83.     tfidf__ = tfidf.toarray()
  84.     return tfidf__


  85. #Calculating cosine similarity
  86. def CosValues(data1, data2):
  87.     tfidf__ = Tf_Idf(vectorList)
  88.     #print tfidf__ #输出全量文本词频向量稀疏矩阵。
  89.     #print tfidf__[16] #某行文本的向量
  90.     #print tfidf__[17] #某行文本的向量
  91.     Numb = 0
  92.     Agen = 0
  93.     Bgen = 0
  94.     for v, k in zip(tfidf__[data1], tfidf__[data2]):
  95.         Numb += v * k
  96.         Agen += v**2
  97.         Bgen += k**2

  98.     print Numb / (math.sqrt(Agen) * math.sqrt(Bgen))


  99. start = time.clock()

  100. #vector-values function testing
  101. vectorList = ChangeJsonIntoList(filelist)
  102. print type(vectorList[0]), 'type check---!==!--!=='
  103. print vectorList[17]  #可以目测一下第A段文本

  104. #print ' '.join(eval(vectorList[0]))
  105. print '---------'
  106. print vectorList[16]  #可以目测一下第B段文本

  107. #cutWord() #调用切词程序,生成分词json
  108. CosValues(17, 16)  #计算两段文本的相似性。两个参数是对应文本的行号。
  109. end = time.clock()
  110. print end - start  # Take xxx seconds
  111. """
  112.     测试结果:
  113.         最大值:1.0
  114.         最小值:0.0
  115.         150段文本的速度:0.0xx秒
  116.         10万段文本的速度:40秒
  117. """
复制代码




zip包下载。改改就可以自己测试了。

tf-idf-api.zip (16.87 KB, 下载次数: 583)
QQ20160311-0@2x.jpg
发表于 2016-3-11 12:03:11
回复 收藏
刀心,前来膜拜各位大神    

沙发。先去吃饭
 楼主| 发表于 2016-3-11 12:03:29
回复 收藏
刀心,前来膜拜各位大神    

我去  咋回事儿,3天了没人看啊。下载的人都干啥呢
 楼主| 发表于 2016-3-14 18:53:12
回复 收藏
alexhero,一个求变者,寻找这个世界的出口,站在高处心在尘埃!    

厉害  向您学习
发表于 2016-3-16 15:34:11
回复 收藏
快速回复 返回顶部 返回列表