数据处理过程中很多情况需要对某个信息进行打分,判断这个信息字段的重要行,这里拿文章的单词进行距离,获取TFIDF值。
TFIDF打分:某个词对文章重要性
1、TF:一个词在文章中出现的次数
2、IDF:反文档频率
词频(TF ):某个词在文章中出现的次数:
词频(TF )=某个词在文章中出现的次数/文章的总词数
词频(TF )=某个词在文章中出现的次数/该文出现次数最多的词的出现次数
反文档频率(IDF )= log ( 语料库的文档总数/包含该词的文档数+1)
TF-IDF = 词频(TF )* 反文档频率(IDF)
TF-IDF与一个词在文档中的出现次数成正比,与包含该词的文档数成反比。
IDF值的计算:
run.sh
1
2 INPUT_FILE_PATH="/test/work02/idf_input.data"
3 OUTPUT_PATH="/test/work02/tfidf_output"
4
5 hadoop fs -rmr $OUTPUT_PATH
6
7 hadoop jar /usr/local/src/hadoop-2.6.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0.jar \
8 -input $INPUT_FILE_PATH \
9 -output $OUTPUT_PATH \
10 -mapper "python map.py" \
11 -reducer "python red.py" \
12 -file ./map.py \
13 -file ./red.py
map.py
1 import sys
2
3 for line in sys.stdin:
4 ss = line.strip().split('\t')
5 if len(ss) != 2:
6 continue
7 file_name, file_content = ss
8 word_list = file_content.strip().split(' ')
9 word_set = set(word_list)
10 for word in word_set:
11 print '\t'.join([word,'1'])
这个map的作用就是读取文件内容,过滤脏数据,将文章内容存放到set集合中,并对文章中的单词进行计数。
注意:
1、我的数据源是将多篇文件提前进行了中文分词分割,然后将多个文章文件进行合并,合并后每行使用数字标识,‘\t’进行分割,每一行对应一篇文档;
2、第5是对脏数据进行过滤;
8、我的文章分词是使用的空格,这里是将文件拆分成单个的单词存放列表中
9、将列表转换成set集合,这个转换是为了去重,因为一篇文章中某个单词可能包含多个,但是我只需要记一次,所以需要去重。
red.py
1 import sys
2 import math
3
4 current_word = None
5 sum = 0
6 docs_cnt = 508
7 for line in sys.stdin:
8 ss = line.strip().split('\t')
9 if len(ss) !=2:
10 continue
11 word, val = ss
12 if current_word == None:
13 current_word = word
14 if current_word != word:
15 idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
16 print '\t'.join([current_word, str(idf)])
17 current_word = word
18 sum = 0
19
20 sum += int(val)
21 idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
22 print '\t'.join([current_word, str(idf)])
计算TFIDF值
1 import sys
2
3 input_file_article = sys.argv[1]
4 input_idf = sys.argv[2]
5 input_con = sys.argv[3]
6 input_work = sys.argv[4]
7 def read():
8 file_work = {}
9 idf = {}
10 sum = 0
11 idf_work = open(input_idf, 'r')
12 for line in idf_work:
13 ss = line.strip().split('\t')
14 if len(ss) != 2:
15 continue
16 word, con = ss
17 idf[word] = float(con)
18 file_article = open(input_file_article, 'r')
19 for line in file_article:
20 ss = line.strip().split('\t')
21 if len(ss) != 2:
22 continue
23 con, words = ss
24 if input_con != con:
25 continue
26 for word in words.strip().split(' '):
27 if word not in file_work:
28 file_work[word] = 1
29 else:
30 file_work[word] += 1
31 sum += 1
32
33 if (input_work not in idf) or (input_work not in file_work):
34 print input_work
35 print 'not found work'
36 sys.exit(-1)
37 tf = file_work[input_work]
38 print tf
39 print idf[input_work]
40 tfidf = tf * idf[input_work]
41 print '\t'.join([input_con, input_work, str(tfidf)])
42 sys.exit(-1)
43
44
45 if __name__ == "__main__":
46 read()
这里使用一个简单的py程序计算结果,需要注意的一下几个地方:
1、我是将上面生成的idf值从hdfs上面拉到了本地
2、直接套取前面写的公式。