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

  • A+
所属分类:python笔记  分词研究
本文信息本文由方法SEO顾问发表于2016-03-1112:53:11,共 3402 字,转载请注明:分享自用小工具:TF-IDF计算文档相似性的python实现_【方法SEO顾问】

首先感谢方法共享平台,哈哈。

先来说说实现思路
1、我从我的数据库中获取了一些文章的title
2、将title用jieba分词进行分词
3、使用一些第三方库计算出词频向量(其中计算方法不明)

4、根据每两篇文档的词频向量计算其余弦相似性,公式如下:

5、根据人肉观察和计算结果,设定一个阀值,作为相似性推荐的参数值

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

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

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

代码如下,我觉得可以扩展一下直接使用。

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


def cutWord():
    f = open('/Users/movespeed/Desktop/Python/title.json')  #文件路径自己修改
    """
        Open source file
    """
    jiebafile = open('/Users/movespeed/Desktop/Python/jiebafile.json', 'w+'
                     )  #文件路径自己修改
    """
        save cutword result into a json file
    """
    while 1:
        line = f.readline()
        if not line:
            break
        else:
            title = json.loads(line)['title']
            t_id = json.loads(line)['id']
            tf_idf = json.loads(line)['tf-idf']
            #seg_list =  jieba.cut(title, cut_all=True)#the jieba cut function
            title = Converter('zh-hans').convert(
                title.decode('utf-8')
            )  # Translate func for jieba can't cut cht.
            #print title
            seg_list = jieba.cut(title, cut_all=True)  #the jieba cut function

            seg_list = str(",".join(seg_list))
            seg_list = seg_list.split(',')
            #print seg_list
            result = []
            for seg in seg_list:
                seg = ','.join(seg.split(',')).decode('utf-8')
                if (seg != '' and seg != "\n" and seg != "\n\n" and
                        seg != "_" and seg != "," and seg != "|"):
                    result.append(seg)
            jsoninfo = json.dumps({"id": t_id,
                                   "title": title,
                                   "cut_word": result,
                                   "tf_idf": None})
            jiebafile.write(jsoninfo + '\n')

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


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


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

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

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

    tfidf__ = tfidf.toarray()
    return tfidf__


#Calculating cosine similarity
def CosValues(data1, data2):
    tfidf__ = Tf_Idf(vectorList)
    #print tfidf__ #输出全量文本词频向量稀疏矩阵。
    #print tfidf__[16] #某行文本的向量
    #print tfidf__[17] #某行文本的向量
    Numb = 0
    Agen = 0
    Bgen = 0
    for v, k in zip(tfidf__[data1], tfidf__[data2]):
        Numb += v * k
        Agen += v**2
        Bgen += k**2

    print '余弦值:',Numb / (math.sqrt(Agen) * math.sqrt(Bgen))


start = time.clock()

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

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

#cutWord() #调用切词程序,生成分词json
CosValues(17, 16)  #计算两段文本的相似性。两个参数是对应文本的行号。
end = time.clock()
print '耗时:',end - start  # Take xxx seconds
"""
    测试结果:
        最大值:1.0
        最小值:0.0
        150段文本的速度:0.0xx秒
        10万段文本的速度:40秒
"""

zip包下载。内有测试数据。改吧改吧就可以自测了。

tf-idf-api

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:5   其中:访客  0   博主  0

    • avatar 搜索量劳力士

      这么好的帖子居然没人顶?

      • avatar 深圳SEO http://www.smiseo.com/

        很少看到质量这么高的文章了
        深圳SEO
        http://www.smiseo.com/

        • avatar 苏客居装修网

          牛逼轰轰的

          • avatar 方法

            刀心大神出品,必属精品啊![嘻嘻]

            • avatar 刀心

              有什么问题可以找我交流。