赞
踩
对于一篇比较长的文章,想要不加人为干预的迅速了解文章的关键词,该怎么做到呢?这时候要送到经典算法IF-IDF,TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。
直观上理解,如果一个词很关键,那么这个词在文本中出现的次数就会比较多,此时我们就用 TF(词频) 来表示。而你又要问了,那么文章中出现最多的一定是一些类似 “的”,‘是’,‘在’等停用词 需要将这些词事先过滤掉在对文本进行处理。还有一个问题,我们要考虑词语的关键程度,如果文章中有些词出现的次数一样多,比如 “中国”,“蜜蜂”,“养殖” ,是否就能简单的认为这三个词语重要程度一样呢?答案是否定的,我们很容易看出 “中国” 是一个很常见的词语,在很多文献中都是经常出现的词语,就算给你这个词语,你并不知道这篇文章是干什么的。而 “蜜蜂”,“养殖” 却不常见,很能反应文章的内容,其俩关键性要大于 中国 ,所以还需要采取一种方法来解决。
所以,我们需要一个重要性调整系数,衡量一个词是不是常见词。如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性,正是我们所需要的关键词。
用统计语言来表示,就是在 词频的基础上,对每个词分配一个表示“重要性”的 权重 ,比如最常见的词 “是”,“的” 等停用词给与最小的权重,“中国” 给与较小的权重,而 “蜜蜂”,“养殖” 这类少见的词语给予较大的权重。我们把这个权重叫做 “逆文档频率(IDF)” ,它的大小与一个词的常见程度成 反比。
我们已经了解了什么是 频率(TF) 和 逆文档频率(IDF) 的概念。将两个值相乘,就得到了一个词的 TF-IDF值 ,值越大,说明词对文章的重要性越高。根绝词语的TF-IDF值排名来选择文章的关键词。
1
、
1、
1、 计算词频
词频(TF) = 该词在文章中出现的次数
考虑到文章有长短之分,这里对文章进行 “词频”标准化
词频(TF) = 该词在文章出现的次数/文章总词数
2
、
2、
2、 计算逆文档频率
这是,需要一个语料库(corpus),用来模拟语言的使用环境。计算公式为
逆文档频率(IDF) = log10(语料库的文档总数/包含该词的文档数+1)
分母加1是为了防止所有文档都不包含该词,避免分母为0
3
、
3、
3、 计算TF-IDF
TF-IDF = 词频(TF) X 逆文档频率(IDF)
从最终的结果来看,TF-IDF值与一个词在文档中出现的次数成 正比 ,与该词在整个语言中的出现次数成 反比 ,所以提取文章关键词就要计算TF-IDF值,按照大小顺序进行选择。
下面以 《中国的蜜蜂养殖》 为例子,为大家计算一下。假定文章长度为1000个词,“中国”,“蜜蜂”,“养殖” 各出现了15次,则这三个词的 “词频(TF)” 都为0.015,然后搜索Google发现,包含 “的” 的网页共有250亿张,包含 “中国” 的网页共有62.3亿张,包含 “蜜蜂” 的网页为0.484亿张,包含 “养殖” 的网页为0.973亿张,则他们的 逆文档频率(IDF) 和 IF-IDF值 如下:
包含该词的文档数(亿) | IDF | TF-IDF | |
---|---|---|---|
中国 | 62.3 | 0.603 | 0.009 |
蜜蜂 | 0.484 | 2.713 | 0.041 |
养殖 | 0.973 | 2.410 | 0.036 |
的 | 250 | 0.002 | 3e-5 |
从结果来看,“蜜蜂” 的TF-IDF值最高,**"养殖"其次,“的”**最低,近乎于 0。所以,如果只选择一个词,"蜜蜂"就是这篇文章的关键词。
TF-IDF算法的优点是简单快速,结果比较符合实际情况。缺点是,单纯以"词频"衡量一个词的重要性,不够全面,有时重要的词可能出现次数并不多。而且,这种算法无法体现词的位置信息,出现位置靠前的词与出现位置靠后的词,都被视为重要性相同,这是不正确的。(一种解决方法是,对全文的第一段和每一段的第一句话,给予较大的权重。)
1
、
g
e
n
s
i
m
库
来
计
算
T
F
−
I
D
F
值
1、gensim库来计算TF-IDF值
1、gensim库来计算TF−IDF值
首
先
构
建
语
料
库
为
首先构建语料库为
首先构建语料库为
corpus = [
'this is the first document',
'this is the second second document',
'and the third one',
'is this the first document'
]
开
始
处
理
开始处理
开始处理
1
)
对
文
本
进
行
分
词
1)对文本进行分词
1)对文本进行分词
seg_list = []
for i in range(len(corpus)):
seg_list.append(corpus[i].split(' '))
seg_list
结果为:
[['this', 'is', 'the', 'first', 'document'],
['this', 'is', 'the', 'second', 'second', 'document'],
['and', 'the', 'third', 'one'],
['is', 'this', 'the', 'first', 'document']]
2 ) 对 每 个 词 分 配 I d 以 及 计 算 词 频 2)对每个词分配Id以及计算词频 2)对每个词分配Id以及计算词频
from gensim import corpora
dictionary = corpora.Dictionary(seg_list) #生成字典,且对词语编号Id
for key,value in dictionary.items():
print(key,value)
结果为:
0 document
1 first
2 is
3 the
4 this
5 second
6 and
7 one
8 third
#词频统计
new_corpus = [dictionary.doc2bow(text) for text in seg_list]
print(new_corpus)
结果为:
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)],
[(0, 1), (2, 1), (3, 1), (4, 1), (5, 2)],
[(3, 1), (6, 1), (7, 1), (8, 1)],
[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)]]
#说明:括号中第一个数表示字典中的Id,第二个数表示词频(词语出现的个数),比如(0,1)表示第一个文本中document出现了1词,(5,2)表示第二个文本中second出现了2次。
3 ) 训 练 g e n s i m 模 型 并 且 保 存 它 以 便 后 面 的 使 用 3)训练gensim模型并且保存它以便后面的使用 3)训练gensim模型并且保存它以便后面的使用
from gensim import models tfidf = models.TfidfModel(new_corpus) #训练的模型 #载入模型得到单词的tfidf值 tfidf_vec = [] for i in range(len(corpus)): string = corpus[i] string_bow = dictionary.doc2bow(string.lower().split()) string_tfidf = tfidf[string_bow] tfidf_vec.append(string_tfidf) print(tfidf_vec) 结果: [[(0, 0.33699829595119235), (1, 0.8119707171924228), (2, 0.33699829595119235), (4, 0.33699829595119235)], [(0, 0.10212329019650272), (2, 0.10212329019650272), (4, 0.10212329019650272), (5, 0.9842319344536239)], [(6, 0.5773502691896258), (7, 0.5773502691896258), (8, 0.5773502691896258)], [(0, 0.33699829595119235),(1, 0.8119707171924228), (2, 0.33699829595119235), (4, 0.33699829595119235)]]
g
e
n
s
i
m
方
法
总
结
:
gensim方法总结:
gensim方法总结:
1、gensim训练出来的tf-idf值左边是词的id,右边是词的tfidf值
2、gensim有自动去除停用词的功能,比如the
3、gensim有自动去除单个字母,比如i
4、所以通过gensim并不能计算每个单词的tfidf值
2
、
s
k
l
e
a
r
n
库
提
取
文
本
t
f
i
d
f
特
征
2、sklearn库提取文本tfidf特征
2、sklearn库提取文本tfidf特征
代
码
代码
代码
from sklearn.feature_extraction.text import TfidfVectorizer tfidf_vec = TfidfVectorizer() tfidf_matrix = tfidf_vec.fit_transform(corpus) #得到语料库中不重复的词 print('不重复词:\n',tfidf_vec.get_feature_names()) #得到每个单词对应的id值 print('词语对应的id:\n',tfidf_vec.vocabulary_) #得到每个句子所对应的向量 #向量里数字的顺序是按照词语的id顺序来的 print(tfidf_matrix.toarray()) 结果为: 不重复词: ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this'] 词语对应的id: {'this': 8, 'is': 3, 'the': 6, 'first': 2, 'document': 1, 'second': 5, 'and': 0, 'third': 7, 'one': 4} [[0. 0.43877674 0.54197657 0.43877674 0. 0. 0.35872874 0. 0.43877674] [0. 0.27230147 0. 0.27230147 0. 0.85322574 0.22262429 0. 0.27230147] [0.55280532 0. 0. 0. 0.55280532 0. 0.28847675 0.55280532 0. ] [0. 0.43877674 0.54197657 0.43877674 0. 0. 0.35872874 0. 0.43877674]]
3
、
自
定
义
p
y
t
h
o
n
提
取
文
本
t
f
i
d
f
特
征
3、自定义python提取文本tfidf特征
3、自定义python提取文本tfidf特征
基
于
原
来
的
语
料
库
以
及
分
词
处
理
基于原来的语料库以及分词处理
基于原来的语料库以及分词处理
1
)
词
频
统
计
1)词频统计
1)词频统计
from collections import Counter
countlist = []
for i in range(len(seg_list)):
count = Counter(seg_list[i])
countlist.append(count)
print(countlist)
结果:
[Counter({'this': 1, 'is': 1, 'the': 1, 'first': 1, 'document': 1}),
Counter({'second': 2, 'this': 1, 'is': 1, 'the': 1, 'document': 1}),
Counter({'and': 1, 'the': 1, 'third': 1, 'one': 1}),
Counter({'is': 1, 'this': 1, 'the': 1, 'first': 1, 'document': 1})]
2 ) 定 义 p y t h o n 计 算 t f i d f 公 式 的 函 数 2)定义python计算tfidf公式的函数 2)定义python计算tfidf公式的函数
# word可以通过count得到,count可以通过countlist得到 # count[word]可以得到每个单词的词频, sum(count.values())得到整个句子的单词总数 def tf(word, count): return count[word] / sum(count.values()) # 统计的是含有该单词的句子数 def n_containing(word, count_list): return sum(1 for count in count_list if word in count) # len(count_list)是指句子的总数,n_containing(word, count_list)是指含有该单词的句子的总数,加1是为了防止分母为0 def idf(word, count_list): return math.log(len(count_list) / (1 + n_containing(word, count_list))) # 将tf和idf相乘 def tfidf(word, count, count_list): return tf(word, count) * idf(word, count_list)
3 ) 计 算 每 个 单 词 的 t f i d f 值 3)计算每个单词的tfidf值 3)计算每个单词的tfidf值
import math for i, count in enumerate(countlist): print("Top words in document {}".format(i + 1)) scores = {word: tfidf(word, count, countlist) for word in count} sorted_words = sorted(scores.items(), key=lambda x: x[1], reverse=True) for word, score in sorted_words[:]: print("\tWord: {}, TF-IDF: {}".format(word, round(score, 5))) 结果为: Top words in document 1 Word: first, TF-IDF: 0.05754 Word: this, TF-IDF: 0.0 Word: is, TF-IDF: 0.0 Word: document, TF-IDF: 0.0 Word: the, TF-IDF: -0.04463 Top words in document 2 Word: second, TF-IDF: 0.23105 Word: this, TF-IDF: 0.0 Word: is, TF-IDF: 0.0 Word: document, TF-IDF: 0.0 Word: the, TF-IDF: -0.03719 Top words in document 3 Word: and, TF-IDF: 0.17329 Word: third, TF-IDF: 0.17329 Word: one, TF-IDF: 0.17329 Word: the, TF-IDF: -0.05579 Top words in document 4 Word: first, TF-IDF: 0.05754 Word: is, TF-IDF: 0.0 Word: this, TF-IDF: 0.0 Word: document, TF-IDF: 0.0 Word: the, TF-IDF: -0.04463
tf-idf的主要作用就是找出某个词或某些词用于区别于其他文本,而 词袋模型 恰好又是找出文本中出现频率高的词语,那么我们试想:如果我先用词袋模型筛选出一些高热度词汇,再用tf-idf计算其权值,我们将得到词袋模型中的词汇的tf-idf值,值越高说明该词却分每条语句的效果越好。
import numpy as np from sklearn import preprocessing from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer vec=CountVectorizer(min_df=3,ngram_range=(1,1)) content=[ '<s[NULL]cript>alert(1)</s[NULL]cript>X</a>', '\'><video><source o?UTF-8?Q?n?error="alert(1)">', '\'><FRAMESET><FRAME RC=""+"javascript:alert(\'X\');"></FRAMESET>', '"></script>\'//<svg "%0Aonload=alert(1) //>', '"></script><img \'//"%0Aonerror=alert(1)// src>', 'id%3Den%22%3E%3Cscript%3Ealert%28%22AKINCILAR%22%29%3C/script%3E', '?a%5B%5D%3D%22%3E%3Cscript%3Ealert%28document.cookie%29%3C/script%3E', '><iframe src="data:data:javascript:,% 3 c script % 3 e confirm(1) % 3 c/script %3 e">', '?mess%3D%3Cscript%3Ealert%28document.cookie%29%3C/script%3E%26back%3Dsettings1', 'title%3D%3Cscript%3Ealert%28%22The%20Best%20XSSer%22%29%3C/script%3E', '<script charset>alert(1);</script charset>', '"><meta charset="x-mac-farsi">??script ??alert(1)//??/script ??', '</script><script>/*"/*\'/**/;alert(1)//</script>#', ] X=vec.fit_transform(content) trans=TfidfTransformer() tfidf=trans.fit_transform(X) print (vec.get_feature_names()) print (tfidf.toarray()) 输出结果: ['22', '29', '3c', '3cscript', '3d', '3e', '3ealert', 'alert', 'script'] [[ 0. 0. 0. 0. 0. 0. 0. 1. 0. ] [ 0. 0. 0. 0. 0. 0. 0. 1. 0. ] [ 0. 0. 0. 0. 0. 0. 0. 1. 0. ] [ 0. 0. 0. 0. 0. 0. 0. 0.75787695 0.65239752] [ 0. 0. 0. 0. 0. 0. 0. 0.75787695 0.65239752] [ 0.60865989 0.27418507 0.27418507 0.27418507 0. 0.54837013 0.27418507 0. 0.16767089] [ 0.33715382 0.30375763 0.30375763 0.30375763 0.33715382 0.60751526 0.30375763 0. 0.18575524] [ 0. 0. 0. 0. 0. 0. 0. 0. 1. ] [ 0. 0.38907452 0.38907452 0.38907452 0.43185075 0.38907452 0.38907452 0. 0.23792861] [ 0.39646122 0.35719043 0.35719043 0.35719043 0.39646122 0.35719043 0.35719043 0. 0.21843071] [ 0. 0. 0. 0. 0. 0. 0. 0.50226141 0.86471583] [ 0. 0. 0. 0. 0. 0. 0. 0.50226141 0.86471583] [ 0. 0. 0. 0. 0. 0. 0. 0.36109936 0.93252735]]
点
互
信
息
P
M
I
点互信息PMI
点互信息PMI
点互信息PMI(Pointwise Mutual Information)这个指标常常用来衡量两个事物之间的相关性(比如两个词)。公式如下:
如果x跟y不相关,则p(x,y)=p(x)p(y)。二者相关性越大,则p(x, y)就相比于p(x)p(y)越大。
举个自然语言处理中的例子来说,我们想衡量like这个词的极性(正向情感还是负向情感)。我们可以预先挑选一些正向情感的词,比如good。然后计算like跟good的PMI。
互
信
息
M
I
互信息MI
互信息MI
点互信息PMI其实就是从信息论里面的互信息这个概念里面衍生出来的。 互信息即:
其衡量的是两个随机变量之间的相关性,即一个随机变量中包含的关于另一个随机变量的信息量。
可以看出,互信息其实就是对X和Y的所有可能的取值情况的点互信息PMI的加权和。
利
用
互
信
息
进
行
筛
选
特
征
利用互信息进行筛选特征
利用互信息进行筛选特征
s
k
l
e
a
r
n
.
f
e
a
t
u
r
e
s
e
l
e
c
t
i
o
n
.
m
u
t
u
a
l
i
n
f
o
c
l
a
s
s
i
f
sklearn.feature_selection.mutual_info_classif
sklearn.featureselection.mutualinfoclassif
from sklearn import datasets
from sklearn.feature_selection import mutual_info_classif
iris = datasets.load_iris()
x = iris.data
label = iris.target
mutual_info = mutual_info_classif(x, label, discrete_features= False)
print(mutual_info)
结果为
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。