大家好,欢迎来到IT知识分享网。
文章目录
1. TF-IDF概念
TF-IDF是NLP中常用的方法,也比较经典,基本思想是:如果一个词在文档中出现了很多次,但是这个词在其它文档中出现的次数很少,则这个词对这篇文档很重要。在一定程度上这个词可以表达这篇文档的关键信息,所以在网页搜索、关键词提取中常用到TF-IDF。
TF-IDF就是 t f − i d f ( t , d ) = t f ( t , d ) × i d f ( t ) tf-idf(t,d)=tf(t,d) \times idf(t) tf−idf(t,d)=tf(t,d)×idf(t),公式中t代表词term,d代表文档document。其实就是TF与IDF相乘。
TF是词频term frequency ,idf是逆文档频率inverse document-frequency。频率与频数不同,这里的词频是指词的频数,也就是一个词在文档中出现的个数,比如“的”在一个文档中出现了128次数,则 t f ( t , d ) = 128 tf(t,d)=128 tf(t,d)=128,这个比较好理解。
2. sklearn中的TF-IDF
2.1 sklearn中TF-IDF的公式及计算过程
在sklearn中 TfidfTransformer 和 TfidfVectorizer 设置参数 smooth_idf=False时,IDF的计算公式,如下: i d f ( t ) = l o g n d f ( t ) + 1 idf(t)=log\frac{n}{df(t)}+1 idf(t)=logdf(t)n+1
把分子中的1拿到了外边。如果smooth_idf=True时分子和分母同时加了1,做平滑处理。如下:
i d f ( t ) = l o g 1 + n 1 + d f ( t ) + 1 idf(t) = log\frac{1+n}{1+df(t)}+1 idf(t)=log1+df(t)1+n+1
然后再 l 2 l_2 l2正则化:
v n o r m = v v 1 2 + v 2 2 + . . . + v n 2 v_{norm}=\frac{v}{\sqrt{v_1^2+v_2^2+…+v_n^2}} vnorm=v12+v22+...+vn2v
这个向量其实是每个词的权重(weight),一开始是用于信息检索(information retrieval),后来发现这个词向量在文本分类与文本聚类中也很有效果。或许会问,为什么要做正则化?有没有发现正则化后,两个向量的点乘就是这两个向量的余弦相似度了。
举个例子:
>>> from sklearn.feature_extraction.text import TfidfTransformer >>> transformer = TfidfTransformer(smooth_idf=False) >>> transformer # 未做smooth处理 TfidfTransformer(smooth_idf=False) # 有6个文档,每个文档有三个特征词,一行是一个文档。 >>> counts = [[3, 0, 1], ... [2, 0, 0], ... [3, 0, 0], ... [4, 0, 0], ... [3, 2, 0], ... [3, 0, 2]] ... # 使用sklearn的 >>> tfidf = transformer.fit_transform(counts) >>> tfidf <6x3 sparse matrix of type '<... 'numpy.float64'>' with 9 stored elements in Compressed Sparse ... format> >>> tfidf.toarray() array([[0., 0. , 0.], [1. , 0. , 0. ], [1. , 0. , 0. ], [1. , 0. , 0. ], [0., 0., 0. ], # 做smooth处理的 >>> transformer = TfidfTransformer() >>> transformer.fit_transform(counts).toarray() array([[0., 0. , 0.], [1. , 0. , 0. ], [1. , 0. , 0. ], [1. , 0. , 0. ], [0., 0., 0. ], [0., 0. , 0.]])
TfidfVectorizer:
>>> from sklearn.feature_extraction.text import TfidfVectorizer >>> vectorizer = TfidfVectorizer() # 直接把语料转换为if-idf的向量 >>> vectorizer.fit_transform(corpus) <4x9 sparse matrix of type '<... 'numpy.float64'>' with 19 stored elements in Compressed Sparse ... format>
这个例子中6篇文档3个特征的tf-idf的计算过程:
一共有6个文档,n=6,特征词有三个,对于term1在所有的文档中都出现过,所以, d f ( t ) t e r m 1 = 6 df(t)_{term1}=6 df(t)term1=6,
对于doc1的第一个term的tf = 3,所以 t f − i d f t e r m 1 = t f ∗ i d f ( t ) t e r m 1 = 3 × ( l o g 6 6 + 1 ) = 3 tf-idf_{term1}= tf * idf(t)_{term1} = 3 \times (log\frac{6}{6}+1)=3 tf−idfterm1=tf∗idf(t)term1=3×(log66+1)=3
对于doc2的第二个term的tf = 0,所以 t f − i d f t e r m 1 = t f ∗ i d f ( t ) t e r m 1 = 0 × ( l o g 6 1 + 1 ) = 0 tf-idf_{term1}= tf * idf(t)_{term1} = 0 \times (log\frac{6}{1}+1)=0 tf−idfterm1=tf∗idf(t)term1=0×(log16+1)=0
对于doc1的第三个term的tf = 1,所以 t f − i d f t e r m 1 = t f ∗ i d f ( t ) t e r m 1 = 1 × ( l o g 6 2 + 1 ) = 2.0986 tf-idf_{term1}= tf * idf(t)_{term1} = 1 \times (log\frac{6}{2}+1)=2.0986 tf−idfterm1=tf∗idf(t)term1=1×(log26+1)=2.0986
2.2 使用LightGBM进行文本分类
2.3 小结
- 文本需要切词,构建所有文本的词典;
- 把词典的词作为样本的特征,特征值是每个词在文档中出现的次数;
- 根据次数及tf-idf公式计算每个词的tf-idf值,然后l2正则化;经过tf-idf处理后的向量也可以作为文本的向量;
- 样本的tf-id向量中权重比较大的词就可以作为样本的关键词;
- 可以通过限制
max_df和min_df来限制样本的tf-idf向量的维度; - 所有样本的tf-idf matrix是一个稀疏矩阵,对于传统的机器学习算法不友好,训练时间比较长;所以后来word embedding就是把稀疏矩阵降维的;
- 这种文本向量化的模型其实基于词袋模型(Bag of Word model)的。
3. jieba使用tf-idf提取关键词
3.1 一行代码提取关键词
from jieba import analyse sentence = "人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的“容器”。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。人工智能是一门极富挑战性的科学,从事这项工作的人必须懂得计算机知识,心理学和哲学。人工智能是包括十分广泛的科学,它由不同的领域组成,如机器学习,计算机视觉等等,总的说来,人工智能研究的一个主要目标是使机器能够胜任一些通常需要人类智能才能完成的复杂工作。但不同的时代、不同的人对这种“复杂工作”的理解是不同的。2017年12月,人工智能入选“2017年度中国媒体十大流行语“。" keywords = analyse.extract_tags(sentence, topK=10, withWeight=False, allowPOS=(), withFlag=False) print(keywords) # ['人工智能', '智能', '2017', '机器', '不同', '人类', '科学', '模拟', '一门', '技术']
- sentence:需要提取关键词的字符串
- topK:返回权重前top K个单词
- withWeight:返回结果是否需要带tf-idf值
- allowPOS:关键词的词性
- withFlag:返回结果是否要带词性
使用起来确实简单,直接输入一段话就可以提取其中的关键词了。但是有一个问题是,idf的计算是需要看出现这个词的文档的个数,及总的文档数量的,jieba难道不需要么?
3.2 具体实现
- 第一步:对sentence分词,分词使用的HMM算法,当然,也是内置的转移矩阵、发射矩阵及初始概率。分词这个有时间可以写一下。
- 第二步:统计sentence中每个单词的个数。具体实现是用一个dict放的,当然也根据参数allowPOS、stop_words,单词的长度(大于2)进行了过滤。
- 第三步:计算tf-idf。idf是通过内置的idf.txt得到的,类初始化的时候会加载idf.txt文件为一个diict,即
self.idf_freq。如果单词不在self.freq中时,返回的是平均的idf值self.median_idf。然后用第二步的tf值与得到idf相乘。至于为什么要除以一个total,我觉得是为了把tf-idf值变的小一些,比较容易比较大小,毕竟所有的tf-idf都除以一个正数对大小的比较没有影响。
3.3 小结
- jieba的tf-idf值的计算,不需要输入多篇文档,只需要输入需要提取关键词的文档即可
- 关键词可以有词性的限制
- jieba是通过内置的idf来计算单词的tf-idf值的
- 缺点:对于专业性比较强的文档,可能会有问题。毕竟jieba使用的训练样本是不清楚的。
4 总结
- tf-idf的计算公式及优化
- tf-idf的一个应用是基于词袋模型为文本提取特征向量,然后用于文本分类或聚类。优点是比较好理解 ,缺点是matrix太稀疏,向量与向量之间的相似性不太靠谱。试想一下两个文档,里面所用的词不同,但是意思差不多,直观上两个向量应该是相似的。但是其实两个向量相乘的结果为零向量。词不相同,向量正交。
- tf-idf的另一个应用是提取关键词,jieba的实现中是利用已经训练好的idf来作的,对于比较专业的领域可能会有偏差。如果有小伙伴儿知道jieba是用什么语料训练的,欢迎留言。
参考:
- https://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction
- https://lightgbm.readthedocs.io/en/latest/index.html
- https://github.com/fxsjy/jieba
声明:原创文章,转载请注明出处。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119717.html