• TF-IDF算法(2)—python实现


      参加完数模之后休息了几天,今天继续看TF-IDF算法。上篇中对TF-IDF算法已经做了详细的介绍,在此不再赘述。今天主要是通过python,结合sklearn库实现该算法,并通过k-means算法实现简单的文档聚类。

    一 结巴分词                                                                                     

    1.简述

      中文分词是中文文本处理的一个基础性工作,长久以来,在Python编程领域,一直缺少高准确率、高效率的分词组建,结巴分词正是为了满足这一需求而提出。

    2.安装

    (1)全自动安装

    在安装了easy—stall的情况之下可以全自动安装:easy_install jieba

    (2)半自动安装

      •下载地址:https://pypi.python.org/pypi/jieba/

      •在cmd下找到具体的目录python setup.py安装

    3.功能

    (1)全模式:将句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义问题;

      jieba.cut方法接收两个参数:第一个参数为需要分词的字符串,第二个cut_all参数用来控制是否采用全模式进行分词。

    >>> #coding:utf-8
    >>> import jieba
    >>> seg_list = jieba.cut("我爱西邮西邮爱我",cut_all = True)
    >>> print "Full Mode:","/".join(seg_list)

      Full Mode: 我/爱/西/邮/西/邮/爱/我

    (2)精确模式:将句子最精确分开,适合文本分析: 

    >>> seg_list = jieba.cut("喜欢玩游戏,可以把编程当成玩游戏,还挺好玩的,哈哈哈哈")
    >>> print "Default Mode:", "/ ".join(seg_list)

       Default Mode: 喜欢/ 玩游戏/ ,/ 可以/ 把/ 编程/ 当成/ 玩游戏/ ,/ 还/ 挺好玩/ 的/ ,/ 哈哈哈哈

      除此之外,默认表示的也是精确模式: 

    >>> seg_list = jieba.cut("喜欢玩游戏,可以把编程当成玩游戏,还挺好玩的,哈哈哈哈")
    >>> print ",".join(seg_list)

     (3)搜索引擎模式:在精确模式的基础上,对长词再次切分 ,提高召回率。

      jieba.cut_for_search方法只接收需要分词的字符串,这种方法分词分的比较细: 

    >>> seg_list = jieba.cut_for_search("西邮就是西安邮电大学的简称")
    >>> print ",".join(seg_list)

    结果:西邮,就是,西安,邮电,电大,大学,邮电大学,的,简称

      当然结巴分词还有很多功能,比如添加字典啊什么的,在此不再详细说明。

    二  scikit-learn                                                         

      scikit-learn含有完善的文档和丰富的机器学习算法,已经实现了所有基本的机器学习算法,并且其本身就带有一些标准的数据集。比如用来分类的iris数据集、digits数据集;用来回归的boston house price 数据集。

      更多内容见http://dataunion.org/20071.html。

    三 python实现TF-IDF算法                                                                                             

      之前用的是python3.4,但由于不可抗的原因,又投入了2.7的怀抱,在这里编写一段代码,简单的实现TF-IDF算法。大致的实现过程是读入一个测试文档,计算出文档中出现的词的tfidf值,并保存在另一个文档中。

    # -*- coding: cp936 -*-
    import jieba
    import jieba.posseg as pseg
    import os
    import sys
    from sklearn import feature_extraction
    from sklearn.feature_extraction.text import TfidfTransformer
    from sklearn.feature_extraction.text import CountVectorizer
    import sys
    reload(sys)
    sys.setdefaultencoding( "utf-8" )
    sys.path.append("C:UsersAdministratorDesktop9.17")
    from numpy import *
    
    fr = open('exercise.txt')
    fr_list = fr.read()
    dataList = fr_list.split('
    ')
    data = []
    for oneline in dataList:
        data.append(" ".join(jieba.cut(oneline))) 
    
    #将得到的词语转换为词频矩阵
    freWord = CountVectorizer()
    
    #统计每个词语的tf-idf权值
    transformer = TfidfTransformer()
    #计算出tf-idf(第一个fit_transform),并将其转换为tf-idf矩阵(第二个fit_transformer)
    tfidf = transformer.fit_transform(freWord.fit_transform(data))
    
    #获取词袋模型中的所有词语
    word = freWord.get_feature_names()
    
    #得到权重
    weight = tfidf.toarray()
    tfidfDict = {}
    for i in range(len(weight)):
        for j in range(len(word)):
            getWord = word[j]
            getValue = weight[i][j]
            if getValue != 0:
                if tfidfDict.has_key(getWord):
                    tfidfDict[getword] += string.atof(getValue)
                else:
                    tfidfDict.update({getWord:getValue})
    sorted_tfidf = sorted(tfidfDict.iteritems(),
                          key = lambda d:d[1],reverse = True)
    fw = open('result.txt','w')
    for i in sorted_tfidf:
        fw.write(i[0] + '	' + str(i[1]) +'
    ')

    至此,对算法已经有了一个简单的实现,接下来需要做的是将其应用到文档聚类中加以运用。 

    四 实现简单的文本聚类                                                                

      要聚类,聚什么是重点!结合上述分析,我们可以将一篇文章中的关键词和对应的tf-idf值一一对应起来,显然想到的是dict,那么聚类是聚的当然不止一篇文章,那么我们就可以分别将每篇文章的关键词和对应的tf-idf值对应起来,最后整合起来进行聚类,当然还是得用到dict。

      结合上述tf-idf的实现,可以将得到的结果分别存在同一个目录下的.txt中,导入目录读取并整合,直接上代码: 

    # -*- coding: cp936 -*-
    #-*- coding:utf-8 -*-
    from PIL import Image,ImageDraw
    import os, codecs, random
    from math import sqrt
    
    #将得到的结果按照字典存放
    rows_norms = {}
    def readfile(dirname):
        rows = {}
        for f in os.listdir(dirname):#目录
            fr = codecs.open(dirname + f,'r',encoding = 'utf-8')
            tw_dict = {}
            norm = 0
            for line in fr:
                items = line.split('	')
                token = items[0].strip()
                if len(token)<2:
                    continue
                w = float(items[1].strip())
                norm = w**2
                tw_dict[token] = w
            rows[str(f[:-4])] = tw_dict
            rows_norms[str(f[:-4])] = sqrt(float(norm))
        #print len(rows)
        return rows

       至此,相当于得到了数据,接下来就是k-means算法的实现了,之前的文章中都有详细说明,在此不再赘述,所不同的是在此采用了余弦距离计算相似度:

    #得到余弦距离,其中v1就是row,v2是聚类中心点
    def cosine(v1,norm_v1,v2,norm_v2):
        if norm_v1 == 0 or norm_v2 == 0:
            return 1.0
        dividend = 0
        for k,v in v1.items():
            for k in v2:
                dividend += v*v2[k]
        return 1.0-dividend/(norm_v1*norm_v2)

    主程序段如下:

    #算法的实现
    def kcluster(rows,distance=cosine,k=3):
        ranges=rows_range(rows)
        #初始化聚类中心
        clusters=[]
        for i in range(k):
            clusters.append(random_vec(ranges))
    
        clusteres_norm=[]
        for i in range(k):
            clusteres_norm.append(norm(clusters[i]))
        lastmatches=None
        #开始迭代
        for t in range(300):
            print '第%d次迭代' % t
            bestmatches=[[] for i in range(k)]
            for j in rows.keys():
                row=rows[j]
                row_norm=rows_norms[j]
                bestmatch=0
                min_dis=10000000
                for i in range(k):
                    d=distance(row, row_norm, clusters[i],clusteres_norm[i])
                    if d<min_dis:
                        bestmatch=i
                        min_dis=d
                bestmatches[bestmatch].append(j)
            if bestmatches==lastmatches: 
                break
            lastmatches=bestmatches
            for i in range(k):
                clusters[i]=center(bestmatches[i], rows)
        print bestmatches
        return bestmatches
    
    #test
    if __name__ == '__main__':
        corpus_dir='D:/python2.7/exercise/clusting/data/'
        rows=readfile(corpus_dir)
        print 'create vectorspace'
        n=3
        clust=kcluster(rows,k=n)

      简单测试,结果还是挺理想的,但还是可以结合之前对k-means算法的优化,实现更好的聚类。

  • 相关阅读:
    MySQL++:(转)mybatis 常用 jdbcType数据类型
    CF1556F Sports Betting (状压枚举子集DP)
    ICPC Greater New York Region 2020 F
    post方式实现导出/下载文件
    自定义一个v-if
    在vue项目中引用element-ui时 让el-input 获取焦点的方法
    element-select当下拉框数据过多使用懒加载
    vue强制刷新组件更新数据的方式
    .net core efcore dbfirst(sqlserver,mysql,oracle,postgresql)
    camunda安装配置mysql以及整合springboot
  • 原文地址:https://www.cnblogs.com/ybjourney/p/4824903.html
Copyright © 2020-2023  润新知