文本是一种非常重要的非结构化的数据,如何表示文本数据一直是机器学习领域的一个重要研究方向。主要的方法有词袋模型、tf-idf、主题模型、词嵌入模型。
本文不会大篇幅的介绍,简单粗暴的给你灌输文本的理解方式。
one-hot
什么是one-hot编码?one-hot编码,又称独热编码。
语料库:
- John likes to watch movies. Mary likes too.
- John also likes to watch football games.
将语料库中所有的词拉成一个向量,给每个词一个下标,就得到对应的词典。
词典:
- {“John”: 1, “likes”: 2, “to”: 3, “watch”: 4, “movies”: 5, “also”: 6,
“football”: 7, “games”: 8, “Mary”: 9, “too”: 10}
one-hot的表示:
- John: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- likes: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
- too : [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
Bag of Words
有了上述词的表示,整个句子我们对每个词向量加和得到
- List item John likes to watch movies. Mary likes too
- John also likes to watch football games.
就分别可以表示成为:
- [1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
- [1, 1, 1, 1, 0, 1, 1, 1, 0, 0]
第一句是带词频统计的,第二句是不带词频统计的,即出现了,就表示为1,没出现就是0。带词频统计的数字表示词在句子中出现的次数。
词袋模型很难知道这个词是否重要。
TF-IDF
TF-IDF是Term Frequency - Inverse Document Frequency,可以用来权衡这个词对于这个文档的重要度,常用的TF-IDF来计算权重,公式为:
- T F − I D F ( t , d ) = T F ( t , d ) × I D F ( t ) TF-IDF(t,d)=TF(t,d) × IDF(t) TF−IDF(t,d)=TF(t,d)×IDF(t)
其中 T F ( t , d ) TF(t,d) TF(t,d)为单词t在文档d中出现的频率, I D F ( t ) IDF(t) IDF(t)是逆文档频率,用来衡量单词t对于表达语义所起的重要性,表示为:
- I D F ( t ) = l o g 文 章 总 数 包 含 单 词 t 的 文 章 总 数 + 1 IDF(t)=log\frac {文章总数} {包含单词t的文章总数+1} IDF(t)=log包含单词t的文章总数+1文章总数
直观的解释是,如果一个单词在非常多的文章中出现,那么它可能是一个比较通用的词汇,对于区分某篇文章的特殊语义的贡献交小,因此对权重做一定的惩罚。分母+1为了防止分母为0,做的平滑处理,
- I D F ( t ) = l o g 文 章 总 数 + 1 包 含 单 词 t 的 文 章 总 数 + 1 + 1 IDF(t)=log\frac {文章总数+1} {包含单词t的文章总数+1}+1 IDF(t)=log包含单词t的文章总数+1文章总数+1+1
在一些场景中也有上式的平滑处理,也是比较常见的。
但是TF-IDF丢失了语序的表示,只能表示出现与否,如:
- lilei likes hanmeimei
- hanmeimei likes lilei
用TF-IDF很难区分两句的语义。
N-gram
很简单就是可以结合几个词作为item,比如:
2-gram:
- {“lilei likes”:1, "likes hanmeimei ":2}
- {“hanmeimei likes”:1, "likes lilei ":2}
这样就可以保留了语序,但是这样词表会出现膨胀。同时参数的量级是很大的。这样的向量是非常长,非常稀疏的。
语言模型
语言模型的任务就是计算一句话出现的概率:
具体的计算就看你的假设,词语出现是否有关系。
NNLM(神经网络语言模型)
使用了最大似然,这里是对数似然。
- 目标函数: L ( θ ) = ∑ t l o g P ( w t ∣ w t − n + 1 , . . . w t − 1 ) L(θ)=\sum_tlogP(w_t|w_{t-n+1},...w_{t-1}) L(θ)=∑tlogP(wt∣wt−n+1,...wt−1)
上式要满足条件:
- ∑ w ∈ v o c a b u l a r y P ( w t ∣ w t − n + 1 , . . . w t − 1 ) \sum_{w\in vocabulary}P(w_t|w_{t-n+1},...w_{t-1}) ∑w∈vocabularyP(wt∣wt−n+1,...wt−1)
即最后一个词取值是整个词典,总的概率为1。
NNLM结构如图所示:
- 有个长度为4的滑动窗口,遍历语料库,根据这前三个词预测第四个词出现的概率。
- 输入w_{t-n+1}、w_{t-2}、w_{t-1}表示输入的这三个词,w_{t}就是要预测的词、模型的输入是one-hot的表示,假如有10w个词,每个词为10w的向量,w_{t-n+1}、w_{t-2}、w_{t-1}即3个长度为10w的向量,(只有一个位置为1,其他位置全为0)
- 输入进入到投影层,有个矩阵C,有300(我们要得到的稠密向量的维数)个10w维的列向量组成。 C ∈ R 300 × 10 w C\in R^{300×10w} C∈R300×10w是随机初始化的。C矩阵与w向量相乘得到300×1的的向量,相当于取出C中的一列,因为w只有一个位置为1,其他全为0,这样就把输入的三个w词向量取出来了。得到了三个稠密的300维的向量拼接起来得到900维的向量。
- 进入隐层,就是一个全连接(有激活函数)
- 最后一层softmax是有10w维的,就是我们的词表。判断预测的词是词表中的哪一个词。
最终C矩阵中每一列就是我们要求的词向量。需要做矩阵运算取出我们需要的词向量。
word2vec
word2vec的两种网络结构:CBOW(目标是根据上下文出现的词语预测当前词的生成概率)和Skip-gram(是根据当前词来预测上下文中各词的生成概率)
在神经网络语言模型的基础上做了一些简化:
这里没有做拼接,而是做了sum,直接去预测后面那个词:
这样还是存在一些问题就是,词表空间比较大,需要的计算量比较多,word2vec提供了两种解决方法:
-
哈夫曼编码:
根据这些词出现的词频,编码成一个哈夫曼树,只有0和1,原来有10w维,参数就要有300(全连接层节点个数)×10w维,这里把参数θ放到树的节点上,假设根据(我喜欢观看巴西——世界杯)预测(足球),足球的编码1001,做了四次二分类,最大化这四次二分类的连乘。 -
负例采样:
对所有的文档词进行采样,这里的采样并不是随机采样,因为与频次有关系,频次高的被采的概率大。
word2vec中的语义是不考虑上下文的。怎么解决?后面bert中做了进一步讲解。
https://blog.youkuaiyun.com/mr2zhang/article/details/91958053