版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012369535/article/details/88018178
一、基本概念
词频(TF,Term Frequency):一篇文章中某个词的出现次数。TF=某个词在文章中出现的次数/文章的总词数,或者TF=某个词在文章中出现的次数/该文出现次数最多的词的次数。
反文档频率IDF:在词频的基础上,赋予每个词的权重,进一步体现该词的重要性。IDF=log([语料库的文档总数]/[包含该词的文档数+1])。
TF-IDF=词频(TF)* 反文档频率(IDF),可以看出TF-IDF与一个词在文档中出现的次数成正比,与包含该词的文档数成反比。某个词对文章的重要性越高,该值越大,于是排在前面的几个词,就是这篇文章的关键词。
TF-IDF可运用于计算两篇文章的相似度:
- 使用TF-IDF算法,找出两篇文章的关键词;
- 每篇文章各取出若干个关键词(比如20个),合并成一个集合(不重复),计算每篇文章对于这个集合中的词的词频;
- 生成两篇文章各自的词频向量(两个向量每个维的顺序要保持一致,可与集合顺序一致);
- 计算两个向量的余弦相似度,值越大就表示越相似。
二、IDF实践
实践中选取已进行中文分词后的508篇文章,其内容如下:
- convert.py:由于508篇文章需要频繁的读取每一篇,增加了磁盘IO操作,故先将其内容合并为一个文件中,合并代码如下。
import os
import sys
file_path_dir = sys.argv[1] %获取存放508篇文章的目录
def read_file_handler(f):
fd = open(f, 'r')
return fd
file_name = 0
for fd in os.listdir(file_path_dir):
file_path = file_path_dir + '/' + fd %获取每篇文章的路径
content_list = []
file_fd = read_file_handler(file_path)
for line in file_fd:
content_list.append(line.strip()) %将每篇文章里的所有行内容去首位空格和换行符后添加进List集合
print '\t'.join([str(file_name), ' '.join(content_list)])
file_name += 1
然后执行以下命令,将所有文章合并到idf_input.data文件中,该文件的每一行为每一篇文章的内容,共508行
[root@master tfidf_python]# python convert.py input_tfidf_dir > idf_input.data
- map.py:对所有文章的单词作map处理,每篇文章的单词需作去重处理,这样再对每个单词后添置1,表示包含该单词的文章数。
import sys
for line in sys.stdin:
ss = line.strip().split('\t')
if len(ss) != 2:
continue
file_name, file_content = ss
word_list = file_content.strip().split(' ')
word_set = set(word_list) %去重
for word in word_set:
print '\t'.join([word, '1'])
map的输出结果部分如下:
- reduce.py:对map输出的结果,合并相同的单词key的value值,统计包含该词的文档总数,计算idf值。
import sys
import math
current_word = None
sum = 0
docs_cnt = 508
for line in sys.stdin:
ss = line.strip().split('\t')
if len(ss) != 2:
continue
word, val = ss
if current_word == None:
current_word = word
if current_word != word:
idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
print '\t'.join([current_word, str(idf)])
current_word = word
sum = 0
sum += int(val)
idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
print '\t'.join([current_word, str(idf)]) %打印最后一个单词的idf值
通过以下命令测试mapreduce:加入了人工排序,模拟MapReduce的shuffle里的排序
[root@master tfidf_python]# cat idf_input.data | python map.py | sort -k1 | python red.py > red.tmp
- 结果: