1.前言
参考了:
1、https://zhuanlan.zhihu.com/p/32965521
2、https://blog.csdn.net/feilong_csdn/article/details/88655927
2.结论
1、fastText不需要预训练好的词向量,fastText会自己训练词向量。fastText用作文本分类也会产生单词的embedding,也就是说embedding是fastText文本分类的产物。
2、字符级别的n-gram
word2vec把语料中的单词作为最小的单位,他会为每个单词生成一个词向量,但是这就忽略了单词内部的特征,比如“apple”和“apples”等。为了克服这个问题,fastTest使用了字符级别的n-gram来表示一个单词,比如“apple”,设n=3(一般为3~6),则它的trigram有:
"<ap", "app","ppl","ple", "le>"
其中<>分别表示单词的开始和结束。
这样会带来两点好处:
1、对低频词生成的词向量效果会更好。根据上面的字符级别的n-gram来说,即使这个单词出现的次数很少,但是组成单词的字符和其他单词有共享的部分,因此这一点可以优化生成的单词向量。
2、对于训练词库之外的单词,仍然可以构建它们的词向量。我们可以叠加它们的字符级n-gram向量。
3、n-gram可以让模型学习到局部单词顺序的部分信息, 如果不考虑n-gram则便是取每个单词,这样无法考虑到词序所包含的信息,即也可理解为上下文信息,因此通过n-gram的方式关联相邻的几个词,这样会让模型在训练的时候保持词序信息。
4、n-gram可以是字符级别的,也可以是单词级别的。
3、fastText两个重要的优化:Hierarchical Softmax、N-gram
3.模型结构
![](https://img.haomeiwen.com/i659952/d083df873ef148cb.png)
上图是fasttext的模型结构图,x1到xn是n-gram的特征。和CBOW一样,也是有输入层、隐藏层、输出层组成。
输入层是多个单词的向量化形式。
输出层(分层softmax)是一个特定的target,也就是分类的类别。
隐藏层也是对多个词向量的叠加平均。
不同的是,CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档;CBOW的输入单词被onehot编码过,fastText的输入特征是被embedding过;CBOW的输出是目标词汇,fastText的输出是文档对应的类标。
值得注意的是,fastText在输入时,将单词的字符级别的n-gram向量作为额外的特征;在输出时,fastText采用了分层Softmax,大大降低了模型训练时间。
看到前面描述“输入是多个单词及其n-gram特征”还有“将单词级别的n-gram向量作为额外的特征”,那么强调了半天只是额外特征,那么完整的特征构造到底什么样的呢?送入模型的输入到底是什么样的呢?这里我要先打个问号,毕竟王越也不知道。我后来又查了很多资料,发现没有一个说清楚的,而且网上和我有同样困惑的人,还挺多的,但是时间原因,就先放这里吧。
fasttext是用单词的embedding叠加获得文档向量,然后在计算文档与文档之间向量的距离,再进行分类。
4.具体做法
1、添加输入层(embedding层)
Embedding层的输入是一批文档,每个文档由一个词汇索引序列构成。例如:[10, 30, 80, 1000] 可能表示“我 昨天 来到 达观数据”这个短文本,其中“我”、“昨天”、“来到”、“达观数据”在词汇表中的索引分别是10、30、80、1000;Embedding层将每个单词映射成EMBEDDING_DIM维的向量。
于是:input_shape=(BATCH_SIZE, MAX_WORDS), output_shape=(BATCH_SIZE,MAX_WORDS, EMBEDDING_DIM);
EMBEDDING_DIM是embedding层的输出,每个单词被分布式表示的向量维度。可以自己决定,比如设置为100,那么每个单词就会被表示为100维的实值向量。
MAX_WORDS是一个文档的最大词的个数。因为每个文档的长度不一样,所以这个数应该设置的稍微大些,超过的部分会被截断。不足的部分会用“未知词”补齐,比如在词表中设置“未知词”的索引是0.
VOCAB_SIZE表示词汇表大小。
2、添加隐含层(投影层)。投影层对一个文档中所有单词的向量进行叠加平均。
这层的input_shape是Embedding层的output_shape,这层的output_shape=( BATCH_SIZE, EMBEDDING_DIM);
3、添加输出层(softmax层)。真实的fastText这层是Hierarchical Softmax。这层指定了CLASS_NUM(类别的个数),对于一篇文档,输出层会产生CLASS_NUM个概率值,分别表示此文档属于当前类的可能性,哪个概率最大,算法就认为当前文档属于哪个类别。
这层的output_shape=(BATCH_SIZE, CLASS_NUM)
4、 指定损失函数、优化器类型、评价指标,编译模型。损失函数我们设置为categorical_crossentropy(交叉熵),它就是我们上面所说的softmax回归的损失函数;优化器我们设置为SGD,表示随机梯度下降优化器;评价指标选择accuracy,表示精度。
5.用训练数据feed模型时,你需要:
1、将文档分好类,构建词汇表。词汇表中每个词用一个整数(索引)来代替,并预留“未知词”索引,假设为0。
2、对类别进行one-hot化。比如有1.2.3三个类别,则应分别表示为[1,0,0],[0,1,0],[0,0,1]。
3、 对一批文本,将每个文本转化为词索引序列,每个类标转化为onehot向量。就像之前的例子,“我 昨天 来到 达观数据”可能被转化为[10, 30,80, 1000];它属于类别1,它的类标就是[1, 0, 0]。由于我们设置了MAX_WORDS=500,这个短文本向量后面就需要补496个0,即[10, 30, 80, 1000, 0, 0, 0, …, 0]。因此,batch_xs的 维度为( BATCH_SIZE,MAX_WORDS),batch_ys的维度为(BATCH_SIZE, CLASS_NUM)。(注意,这里的例子只是简单的词序,是简化版的,没有考虑字符级别的n-gram)
网友评论