目录
1.2 TF-IDF(term frequency–inverse document frequency)
5.NNLM(Neural Network Language model)
1. Bag-of-words
1.1 类似于one-hot的词袋模型
Bag of words模型最初被用在文本分类中,将文档表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序和语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。简单说就是将每篇文档都看成一个袋子(因为里面装的都是词汇,所以称为词袋,Bag of words即因此而来),然后根据袋子里装的词汇对其进行分类。如果文档中猪、马、牛、羊、山谷、土地、拖拉机这样的词汇多些,而银行、大厦、汽车、公园这样的词汇少些,我们就倾向于判断它是一篇描绘乡村的文档,而不是描述城镇的。
基于文本的BoW模型的一个简单例子,首先给出两个简单的文本文档如下:
文档1: John likes to watch movies. Mary likes too.
文档2: John also likes to watch football games.
基于上述两个文档中出现的单词,构建如下一个词典 (dictionary):
Vocabulary= {"John": 1, "likes": 2,"to": 3, "watch": 4, "movies": 5,"also": 6, "football": 7, "games": 8,"Mary": 9, "too": 10}
上面的词典中包含10个单词, 每个单词有唯一的索引, 那么每个文本我们可以使用一个10维的向量来表示。(用整数数字0~n(n为正整数)表示某个单词在文档中出现的次数):
文档1: [1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
文档2: [1, 1,1, 1, 0, 1, 1, 1, 0, 0]
从上述的表示中,可以很清楚地看出来,在文档表示过程中并没有考虑关键词的顺序,而是仅仅将文档看成是一些关键词出现的概率的集合(这是Bag-of-words模型的缺点之一),每个关键词之间是相互独立的,这样每个文档可以表示成关键词出现频率的统计集合,类似于直方图的统计表示。
优点:简单,直观
缺点:所有的词一视同仁,没有考虑词的重要度,没有考虑词的上下文,没有考虑词与词之间的关系。
1.2 TF-IDF(term frequency–inverse document frequency)
TF-IDF依旧属于词袋模型,相比与1.1节的,这种方式考虑了词对于一篇文章的重要度。
TF(Term Frequency,词频)
TF(Term Frequency,词频)表示一个给定词语t在一篇给定文档d中出现的频率。TF越高,则词语t对文档d来说越重要,TF越低,则词语t对文档d来说越不重要。那是否可以以TF作为文本相似度评价标准呢?答案是不行的,举个例子,常用的中文词语如“我”,“了”,“是”等,在给定的一篇中文文档中出现的频率是很高的,但这些中文词几乎在每篇文档中都具有非常高的词频,如果以TF作为文本相似度评价标准,那么几乎每篇文档都能被命中。
对于在某一文档 里的词语 来说, 的词频可表示为:
其中 ni,j 是词语 ti 在文档 dj 中的出现次数,分母则是在文件 dj 中所有词语的出现次数之和。
注意,这里除了文档总词数作为分母,只是做了一个标准化,因为有的文章长,有的文章短,出现100次的不一定算多,出现3次的不一定就少。有时候也用其他作为分母进行标准化。
IDF(Inverse Document Frequency,逆向文件频率)
IDF(Inverse Document Frequency,逆向文件频率)的主要思想是:如果包含词语t的文档越少,则IDF越大,说明词语t在整个文档集层面上具有很好的类别区分能力。IDF说明了什么问题呢?还是举个例子,常用的中文词语如“我”,“了”,“是”等在每篇文档中几乎具有非常高的词频,那么对于整个文档集而言,这些词都是不重要的。对于整个文档集而言,评价词语重要性的标准就是IDF。
某一特定词语的IDF,可以由总文件数除以包含该词语的文件数,再将得到的商取对数得到:
其中 |D| 是语料库中所有文档总数,分母是包含词语 ti 的所有文档数。
有时分母为0,需要平滑,
以1.1的例子,来计算两个文档中tf-idf(未平滑)。
import math
d1 = [1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
d2 = [1, 1,1, 1, 0, 1, 1, 1, 0, 0]
assert len(d1) == len(d2)
contain_document_num=[0] * len(d1)
for i in range(len(d1)):
if(0 != d1[i]):
contain_document_num[i] += 1
if(0 != d2[i]):
contain_document_num[i] += 1
tf_1 = [i/float(sum(d1)) for i