# encoding=utf-8
from __future__ import absolute_import
import os
import jieba
import jieba.posseg
from operator import itemgetter_get_module_path = lambda path: os.path.normpath(os.path.join(os.getcwd(),os.path.dirname(__file__), path))#调用jieba/init.py 中_get_abs_path 函数赋值给变量  _get_abs_path
_get_abs_path = jieba._get_abs_pathDEFAULT_IDF = _get_module_path("idf.txt") #默认的逆文档频率文件路径class KeywordExtractor(object):#初始化的一个停用词典STOP_WORDS = set(("the", "of", "is", "and", "to", "in", "that", "we", "for", "an", "are","by", "be", "as", "on", "with", "can", "if", "from", "which", "you", "it","this", "then", "at", "have", "all", "not", "one", "has", "or", "that"))#设置自定义停用词def set_stop_words(self, stop_words_path):abs_path = _get_abs_path(stop_words_path) #获取自定义停用词路径if not os.path.isfile(abs_path): raise Exception("jieba: file does not exist: " + abs_path)#文件存在,则读取文件内容,并添加到已有词典STOP_WORDS中content = open(abs_path, 'rb').read().decode('utf-8')for line in content.splitlines():self.stop_words.add(line)def extract_tags(self, *args, **kwargs):raise NotImplementedError#
class IDFLoader(object):def __init__(self, idf_path=None):self.path = "" self.idf_freq = {}self.median_idf = 0.0 #idf频率中位数if idf_path:#是否自定义逆文档频率文件self.set_new_path(idf_path)#自定义逆文档频率文件 并计算idf频率中位数def set_new_path(self, new_idf_path):if self.path != new_idf_path:self.path = new_idf_pathcontent = open(new_idf_path, 'rb').read().decode('utf-8') #读取文件self.idf_freq = {}  #初始化idf频率字典"""遍历idf文件每行数据,格式如下word      idf频率劳动防护  13.900677652生化学    13.900677652奥萨贝尔  13.900677652考察队员  13.900677652"""for line in content.splitlines():# 每行按空格切分为词,及其idf频率word, freq = line.strip().split(' ')#构建key,value字典,key为word, value为idf频率self.idf_freq[word] = float(freq)"""求逆词频中位数 整除法,sorted(self.idf_freq.values()),排序后是词频列表[13.900677652,13.900677653,.....]然后用idf词频字典长度除以2求中位数索引最后根据索引求词频列表中位数"""self.median_idf = sorted(self.idf_freq.values())[len(self.idf_freq) // 2]#返回idf词频字典与idf词频中位数def get_idf(self):return self.idf_freq, self.median_idfclass TFIDF(KeywordExtractor):def __init__(self, idf_path=None):#jieba.dt是 jieba/init.py 文件中    class Tokenizer(object)类的实例化   jieba分词器类self.tokenizer = jieba.dt #jieba/posseg/init.py文件中         dt = POSTokenizer(jieba.dt)类的实例化   新建自定义分词器类self.postokenizer = jieba.posseg.dt#停用词字典的浅拷贝,随原始字典改变而改变self.stop_words = self.STOP_WORDS.copy()#初始化IDFLoader类  自定义逆文档频率文件或选择默认逆文档频率文件  self.idf_loader = IDFLoader(idf_path or DEFAULT_IDF)#获取idf词频字典与idf词频中位数self.idf_freq, self.median_idf = self.idf_loader.get_idf()#用户调用函数 自定义逆文档频率文件def set_idf_path(self, idf_path):new_abs_path = _get_abs_path(idf_path)if not os.path.isfile(new_abs_path):raise Exception("jieba: file does not exist: " + new_abs_path)self.idf_loader.set_new_path(new_abs_path)self.idf_freq, self.median_idf = self.idf_loader.get_idf()"""使用tf-idf算法提取关键词函数sentence:文本topk: int类型         返回关键词数量(按idf频率最高返回吗???)withweight: bool类型    如果true返回词权重列表(word, weight);  false只返回词列表allowPOS:自定义词性列表,不在该词性列表中的词被过滤withFlag:定义了allowPOS词性列表后才有效,如果true返回词权重列表 word/权重  idf设置了allowpos 与不设置allowpos 权重不一样??有些词被过滤的原因吗eg:sentence = ‘此外,公司拟对全资子公司吉林欧亚置业有限公司增资4.3亿元,增资后,吉林欧亚置业注册资本由7000万元增加到5亿元。吉林欧亚置业主要经营范围为房地产开发及百货零售等业务。目前在建吉林欧亚城>市商业综合体项目。2013年,实现营业收入0万元,实现净利润-139.13万元。’a = ['ns', 'n', 'vn', 'v','nr']参数选择 allowPOS=a,withWeight=True,withFlag=True欧亚/ns 1.0397172936775758吉林/ns 0.9386301413806061置业/n 0.6960464319372728增资/v 0.47829481615333336实现/v 0.2834381985812121参数选择 withWeight=True欧亚 0.7458841454643479吉林 0.6733651014252174置业 0.49933765769413047万元 0.3466477318421739增资 0.3431245420230435参数选择 allowPOS=a,withWeight=True欧亚 1.0397172936775758吉林 0.9386301413806061置业 0.6960464319372728增资 0.47829481615333336实现 0.2834381985812121"""def extract_tags(self, sentence, topK=20, withWeight=False, allowPOS=(), withFlag=False):"""Extract keywords from sentence using TF-IDF algorithm.   使用tf-idf算法提取关键词Parameter:- topK: return how many top keywords. `None` for all possible words.   - withWeight: if True, return a list of (word, weight);if False, return a list of words.- allowPOS: the allowed POS list eg. ['ns', 'n', 'vn', 'v','nr'].if the POS of w is not in this list,it will be filtered.- withFlag: only work with allowPOS is not empty.if True, return a list of pair(word, weight) like posseg.cutif False, return a list of words"""#如果选择自定义词性列表 返回wordsif allowPOS:allowPOS = frozenset(allowPOS)  #frozenset  创建不可变词性集合words = self.postokenizer.cut(sentence) #使用自定义分词器 dt = POSTokenizer(jieba.dt)  jieba/posseg/init.py文件中 else:words = self.tokenizer.cut(sentence) #否则使用jieba默认分词器#初始化一个保存单词与词数的字典freq = {}#获取分词后的列表,遍历# 如果设置allowPOS  分词后返回值类似这样[(pair('欧亚','ns'),1.0333333),........]# pair格式  pair(flag:'ns','word','欧亚')# 没设置allowPOS  不会返回词性flagfor w in words:if allowPOS:#过滤词,只需要自定义指定词性的词,#如果该词词性不在自定义词性列表中,继续for循环,if w.flag not in allowPOS:continue#如果没有withFlag,只保留词w.wordelif not withFlag:w = w.word#如果设置allowPOSand and withFlag获取w.word  eg:pair(flag:'ns','word','欧亚')#否则只获取词#反正最终统计词数只需要词就行wc = w.word if allowPOS and withFlag else w#过滤一个字的词,以及停用词if len(wc.strip()) < 2 or wc.lower() in self.stop_words:continue#利用dict字典累计,统计词数  eg{'a': 1.0}freq[w] = freq.get(w, 0.0) + 1.0#计算总的词数total = sum(freq.values())#遍历获取字典的键for k in freq:#如果withFlag了 并且设置了词性列表allowPOS 只返回单词kw = k.word if allowPOS and withFlag else k#这里idf是已经算好的,在加载的逆文档频率文件中 eg:默认的idf.txt#计算权重算法:(freq[k] 词数) * (self.idf_freq.get(kw, self.median_idf) 词idf)  / total文章总词数 freq[k] *= self.idf_freq.get(kw, self.median_idf) / totalif withWeight:#按权重值 并从大到小排序 返回  eg: 公司/n 1.1678233145266665tags = sorted(freq.items(), key=itemgetter(1), reverse=True)else:#没设置withWeight 则不返回权重值  eg :公司 ntags = sorted(freq, key=freq.__getitem__, reverse=True)if topK:#返回权重最大的前几个词return tags[:topK]else:return tags

jieba源码学习------TF-IDF方法 计算词权重相关推荐

  1. caffe源码学习:softmaxWithLoss前向计算

    caffe源码学习:softmaxWithLoss 在caffe中softmaxwithLoss是由两部分组成,softmax+Loss组成,其实主要就是为了caffe框架的可扩展性. 表达式(1)是 ...

  2. tfidf处理代码_解霸源代码学习——用TF-IDF方法计算词权,jieba,源码,TFIDF,权重

    # encoding=utf-8 from __future__ import absolute_import import os import jieba import jieba.posseg f ...

  3. CAFFE源码学习之优化方法solver

    一.前言 solver就是来计算损失函数最小化的优化方法,在caffe中,提供了六种不同的优化方法: (1)SGD: (2)AdaGrad: (3)AdaDelta: (4)Adam: (5)RMSP ...

  4. ThinkPHP源码学习之I方法

    PHP新人一个,最近在做一个项目,用的是ThinkPHP,想往深处学习,特意学习ThinkPHP的源码并作笔记,以记录这些容易忘记的东西,废话不多说,开始. 官网说明: I方法是ThinkPHP众多单 ...

  5. Android源码学习之工厂方法模式应用

    主要内容: 工厂方法模式定义 工厂方法模式优势 工厂方法模式在Android源码中的应用 一.工厂方法模式定义 工厂方法模式定义: Define an interface for creating a ...

  6. 文本特征抽取的向量空间模型(VSM)和TF/IDF方法

    文本特征抽取 两组小说,一组是爱情的,另一组是科幻的.我们能否用支持向量机训练一个模型,用来识别小说类型呢? 这个并不容易.因为支持向量机这类机器学习算法只能接受数学里面的向量作为输入.如果用它来做文 ...

  7. RecyclerView源码学习笔记(一)构造函数和setLayoutManager方法

    前言 RecyclerView已经出来很久,现在几乎应该都会用RecyclerView代替Listview,虽然我觉得大多数人应该还是不太清楚这两者之前的区别的,或者说RecyclerView相对于L ...

  8. 基于Qt5.14.2和mingw的Qt源码学习(三) — 元对象系统简介及moc工具是如何保存类属性和方法的

    基于Qt5.14.2和mingw的Qt源码学习(三) - 元对象系统简介及moc工具是如何保存类属性和方法的 一.什么是元对象系统 1.元对象系统目的 2.实现元对象系统的关键 3.元对象系统的其他一 ...

  9. spring4.1.8初始化源码学习三部曲之三:AbstractApplicationContext.refresh方法

    本章是<spring4.1.8初始化源码学习三部曲>系列的终篇,重点是学习AbstractApplicationContext类的refresh()方法: 原文地址:https://blo ...

最新文章

  1. 在Windows 8.1上使用Fiddler重定向http请求进行前端调试
  2. Stimulsoft Reports.Net基础教程(十):创建图表报表②
  3. BF算法和KMP算法
  4. 美国教育---一切为了学生的成才
  5. 基于session认证
  6. struts2 国际化资源文件自定义的路径解决方法
  7. 深圳很适合创业,无论小白造梦,或是落魄重生
  8. React入门基础+练习 (一)
  9. 计算机电缆静电,ZR-DJFPVP计算机电缆
  10. Json转换为Model,Struct,Class对象 Swift
  11. 电子科大+矩阵理论+真题总结
  12. 前端布局篇之文字居中显示
  13. 五最好的应聘者可以问问题
  14. 暖暖环游世界显示服务器异常,暖暖环游世界客服常见问题汇总
  15. 如何基于Miniconda使用Pycharm调用Gurobi
  16. PLC++控制程序精编108例pdf
  17. 【MNIST数据转化】.idx3-ubyte 转png 格式
  18. Linux 套接字编程基础
  19. hualinux ros 1.1:RouterOS如何入门及推荐资料
  20. RadioButtonList1 默认选中

热门文章

  1. 微信小程序 转发 分享功能(二)
  2. BGP/MPLS 虚拟专用网络 Option C 1
  3. 加速取代Intel!苹果自研PC处理器更强大:12核、16核来了
  4. 12G+500G笔记本电脑最适合吃鸡
  5. Ubuntu20.04换源,安装基本脚本,自用
  6. 批量重命名 教你使用替换功能 将文件名称中特定符号进行替换
  7. Mac使用技巧|轻松使用Mac自带输入法输入不会读的字
  8. 电火花线切割加工的步骤及要求
  9. 将MOV转换为MP4的几种最佳方法
  10. 电脑蓝屏怎么办?一招教你修好