语言表示模型有很多种方式,常见的语言表示方式可以粗略的分成非神经网络的方式、基于神经网路的方式。
也可以分为一下四种方式:
1.基于one-hot、tf-idf、textrank等的bag-of-words;
2.主题模型:LSA(SVD)、pLSA、LDA;
3.基于词向量的固定表征:word2vec、fastText、glove;
4.基于词向量的动态表征:elmo、GPT、bert、XLnet、RoBERTa、T5、ERNIE-Baidu、ELECTRA;
Bag of Words(BOW),就是将文本/Query看作是一系列词的集合。由于词很多,所以咱们就用袋子把它们装起来,简称词袋。根据词语在文本中的统计信息创建文本表示模型,最常见的有one-hot表示、词频表示、tfidf表示。
方法步骤:根据文本库创建词典,再对单个文本中进行表示,如果词语出现在文本中则标注为1否则该位置标注为0
texts=["John likes to watch movies. Mary likes too.","John also likes to watch football games."]
from sklearn.feature_extraction.text import CountVectorizer
# bow_vectorizer = CountVectorizer(max_df=0.9, min_df=1, max_features=10, stop_words='english')# bag-of-words feature matrix
bow_vectorizer = CountVectorizer(max_features=4000)
bow = bow_vectorizer.fit_transform(texts)
print(bow_vectorizer.get_feature_names())
print(bow.toarray())
#TFIDF 文本表示形式
from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidfVectorizer(lowercase=False, max_features=4000)
vec_matrix=vec.fit_transform(texts)
print(vec.get_feature_names())
print(vec_matrix.toarray())
文档一:汤姆追杰瑞
文档二:汤姆杰瑞
文档三:杰瑞追汤姆 词袋:“汤姆追”,“追杰瑞”,“汤姆杰瑞”,“杰瑞追”,“追汤姆”。
主要用于发现主题,解决词向量相近关系的表示;
将共现矩阵行(列)作为词向量
例如:语料库如下:
• I like deep learning.
• I like NLP.
• I enjoy flying. 则共现矩阵表示如下:(使用对称的窗函数(左右window length都为1) )
例如:“I like”出现在第1,2句话中,一共出现2次,所以=2。 对称的窗口指的是,“like I”也是2次。共现窗口中的两个词语不考虑前后顺序,所以矩阵是对称矩阵。
将共现矩阵行(列)作为词向量表示后,可以知道like,enjoy都是在I附近且统计数目大约相等,他们意思相近。
缺点:面临稀疏性问题、向量维数随着词典大小线性增长
解决:SVD、PCA降维,但是计算量大
主题模型用于从文本库中发现有代表性的主题(得到每个主题上面词的分布特性),并能够计算出每篇文章的主题分布。
隐狄利克雷模型(LDA)是利用文档中单词的共现关系来对单词按主题聚类,可以理解为“文档-单词”矩阵进行分解,得到“文档-主题”和“主题-单词”两个概率分布。
输出:文档-主题概率分布矩阵和主题-词概率分布矩阵
训练方法:利用文档中单词的贡献关系来对单词按主题聚类,也可以理解为对“文档-单词”进行矩阵分解(有点像ALS,即将NM矩阵分解维 NK 和 K*M两个矩阵,K为主题个数)
用处:可以找到词与主题,主题与文档之间的关系
Latent Semantic Analysis(LSA)假设以一定的概率选择了一个主题,然后以一定的概率选择当前主题的词。
LSI是基于奇异值分解(SVD)的方法来得到文本的主题的。 通过一次SVD,就可以得到文档和主题的相关度,词和词义的相关度以及词义和主题的相关度。
LSA**举例**: 假设我们有下面这个有10个词三个文本的词频TF对应矩阵如下:
这里我们没有使用预处理,也没有使用TF-IDF,在实际应用中最好使用预处理后的TF-IDF值矩阵作为输入。我们假定对应的主题数为2,则通过SVD降维后得到的三矩阵为:(m:词语的个数,n文本个数,k主题个数)
A m n = U m k ∗ E k k ∗ V k n A_{mn}=U_{mk}* E_{kk} *V_{kn} Amn=Umk∗Ekk∗Vkn
U i j U_{ij} Uij:第i个词和第j个主题的相关度
E i j E_{ij} Eij:第i个主题和第j个主题的相关度
V i j V_{ij} Vij :第i个文本和第j个主题的相关度
# 主题模型 https://blog.csdn.net/selinda001/article/details/80446766
doc1 = "Sugar is bad to consume. My sister likes to have sugar, but not my father."
doc2 = "My father spends a lot of time driving my sister around to dance practice."
doc3 = "Doctors suggest that driving may cause increased stress and blood pressure."
doc4 = "Sometimes I feel pressure to perform well at school, but my father never seems to drive my sister to do better."
doc5 = "Health experts say that Sugar is not good for your lifestyle."
# 整合文档数据
doc_complete = [doc1, doc2, doc3, doc4, doc5]
from nltk.stem.wordnet import WordNetLemmatizer
import string
stop = ["\n","\r","is","to","the","of","a","an","my","i","at","for","not","that","but"]
exclude = set(string.punctuation)
lemma = WordNetLemmatizer()
def clean(doc):
stop_free = " ".join([i for i in doc.lower().split() if i not in stop])
punc_free = ''.join(ch for ch in stop_free if ch not in exclude)
normalized = " ".join(lemma.lemmatize(word) for word in punc_free.split())
return normalized
doc_clean = [clean(doc).split() for doc in doc_complete]
print(doc_clean)
import numpy as np
import gensim
from gensim import corpora
# 创建语料的词语词典,每个单独的词语都会被赋予一个索引
dictionary = corpora.Dictionary(doc_clean)
print(len(dictionary),dictionary)
# 使用上面的词典,将转换文档列表(语料)变成 DT 矩阵
doc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]
print(doc_term_matrix)
# 使用 gensim 来创建 LDA 模型对象
Lda = gensim.models.ldamodel.LdaModel
# 在 DT 矩阵上运行和训练 LDA 模型
ldamodel = Lda(doc_term_matrix, num_topics=3, id2word = dictionary, passes=50)
print(ldamodel)
# 输出结果
print(ldamodel.print_topics(num_topics=3, num_words=3))
#文本主题表示
for doc in ldamodel[doc_term_matrix]:
print(doc)
BOW优点:
1、解决了分类器不好处理离散数据的问题
2、 在一定程度上也起到了扩充特征的作用
BOW缺点:
1、它是一个词袋模型,不考虑词与词之间的顺序(文本中词的顺序信息也是很重要的);
2、它假设词与词相互独立(实际上大多数情况下,词与词是相互影响的);
3、它得到的特征是离散稀疏的
主题模型优点:
1、可以找到词与主题,主题与文档之间的关系
主题模型缺点:
1、无法挖掘的词与词之间的相似度
2、计算量比较大(奇异值分解SVD)
为了解决词语向量的稀疏性问题,以及挖掘词语之间的语义关系,研究者提出了用** 词嵌入**的概念。
词嵌入是一类将词向量化的模型的统称,核心思想是将每个词映射成低维空间(通常K=50~300维)上的一个稠密向量(Dense Vector)。
神经网络将每个词映射成低维空间(通常K=50~300维)上的一个稠密向量(Dense Vector)。
利用向量之间的距离可以计算词语之间的语义关系
king和queen之间的关系相比与man与woman的关系大体应该相同的,那么他们通过矩阵运算,维持住这种关系
Paris 和France之间的关系相比与Berlin与German的关系大体应该相同的,那么他们通过矩阵运算,维持住这种关系
import gensim
from gensim.models import word2vec
word2vec_path = 'D:\py3.6code\data_nlp\word_vec\\200dim\word2vec.model'
model=gensim.models.Word2Vec.load(word2vec_path)
print(model.vector_size)#词向量维度
sim_words = model.most_similar(positive=['女人'])
for word,similarity in sim_words:
print(word,similarity) # 输出’女人‘相近的词语和概率
print(model['女孩'])
神经网络语言模型(2003,A Neural Probabilistic Language Model)其用前n-1个词预测第n个词的概率,并用神经网络搭建模型。
应用场景:已知前文数个词语,通过概率计算预测下一个词。
思路:输入词语文本第i个词语的上下文词语(窗口大小k)oneHot编码,与矩阵C(vocabSizehiddenSize)相乘得到(oneHot编码与C矩阵形成只有编码为1的位置得到维度为)hiddenSize维度的向量;得到的khiddenSize维度矩阵,拼接起来得到(khiddenSize,)向量,在经过全连接层softmax得到下一个词语的概率,(共有vocabSize个概率,且概率之和=1)。
输入:语料中词w以及它的上下文{w,Context(w)w,Context(w)};
输出:预测语料中基于前文的前提下每个词的概p(w∣Context(w))p(w∣Context(w))(即类条件概率);
目标:最大化似然函数。
NNLM具有三层网络结构,分别为输入(投影)层、隐含层和输出层,如下图所示。
上述得到的C_vocabSize*hiddenSize 即可以将每个词语表示成一个稠密向量(Dense Vector)表示,我们称之为词嵌入表示方式。
word2vec和神经网络语言模型不同,直接来学习这个词向量,使用的基本假设是分布式假设,如果两个词的上下文时相似的,那么他们语义也是相似的。
Word2Vec是谷歌2013年提出的目前最常用的词嵌入模型之一,Word2Vec实际上是一种浅层的神经网络模型,它有两种网络结构,分别是CBOW(Continues Bag of Words)和Skip-gram。
CBOW的目标是根据上下文出现的词语来预测当前词的生成概率;而Skip-gram是根据当前词来预测上下文中各词的生成概率。CBOW和Skip-gram都可以表示成输入层(Input)、映射层(Projection)和输出层(Output)组成的神经网络。
在神经网络语言模型的基础上做了一些简化: 这里没有做拼接,而是做了sum,直接去预测后面那个词。
word2vec 两点优化:
1、hierarchical-softmax哈夫曼树将平铺型softmax压缩成层级softmax【优点】
(1)softmax计算量为VocabSize,现在变成了log2VocabSize,
(2)使用霍夫曼树是高频的词靠近树根,这样高频词需要更少的时间会被找到,这符合我们的贪心优化思想。
2、负采样 【优点】
(1)negative sampling 每次让一个训练样本仅仅更新一小部分的权重参数,从而降低梯度下降过程中的计算量。
(2)对频繁词进行二次抽样和应用负抽样不仅减少了训练过程的计算负担,而且还提高了其结果词向量的质量。
fasttext的模型与CBOW类似,实际上,fasttext的确是由CBOW演变而来的。CBOW预测上下文的中间词,fasttext预测文本标签。与word2vec算法的衍生物相同,稠密词向量也是在训练神经网络的过程中得到的。
fasttext中采用层级softmax做分类,这与CBOW相同。fasttext算法中还考虑了词的顺序问题,即采用N-gram,与之前介绍离散表示时的做法相同。如:今天天气非常不错,Bi-gram的表示就是:今天、天天、天气、气非、非常、常不、不错。
Glove模型 Cbow/Skip-Gram 是一个local context window的方法,比如使用NS来训练,缺乏了整体的词和词的关系,负样本采用sample的方式会缺失词的关系信息。 另外,直接训练Skip-Gram类型的算法,很容易使得高曝光词汇得到过多的权重。
Global Vector融合了矩阵分解Latent Semantic Analysis (LSA)的全局统计信息和local context window优势。融入全局的先验统计信息,可以加快模型的训练速度,又可以控制词的相对权重。
我们可以通过word2vec或者 glove这种模型在大量的未标注的语料上学习,我们可以学习到比较好的向量表示,可以学习到词语之间的一些关系。比如男性和女性的关系距离,时态的关系,学到这种关系之后我们就可以把它作为特征用于后续的任务,从而提高模型的泛化能力。 但是同时存在一些问题比如:
He deposited his money in this bank .
His soldiers were arrayed along the river bank .
【bank 一词多义问题】word embeding 有个问题就是我们的词通常有很多语义的,比如bank是银行还是河岸,具体的意思要取决与上下文,如果我们强行用一个向量来表示语义的话,只能把这两种语义都编码在这个向量里,但实际一个句子中,一个词只有一个语义,那么这种编码是有问题的。
静态词向量优点
1、解决特征表示稀疏问题
2、可以挖掘词语之间的语义关系
静态词向量缺点:
1、无法解决一词多义的问题
2、无法挖掘上下文语义信息
Word2vec算法通过使用一组固定维度的向量来表示单词,但是往往一个词语在不同的语境中会有不同的意思。 eg:“长”这个字,在“长度”这个词中表示度量,在“长高”这个词中表示增加。那么为什么我们不通过“长”周围是“度”或者是“高”来判断它的读音或者它的语义呢?这个问题就派生出语境中的词嵌入模型。
要解决这一问题,就引入了【contextual word embedding】。
contextual word embedding:无监督的上下文的表示,这种无监督的学习是考虑上下文的,比如ELMo、OpenAI GPT、BERT都是上下文相关的表示方法。
ACL2017发表的《Semi-supervised sequence tagging with bidirectional language models》 EMLo改变Word2vec类的将单词固定为指定长度的向量处理方式,它是在为每个单词分配词向量之前先查看整个句子,然后使用bi-LSTM来训练它对应的词向量。
ELMO虽然用了双向的LSTM模型解决了单向流问题,但是仍然会由顺序依赖问题。
可以通过RNN/LSTM/GRU来解决上下文的语义问题,RNN与普通深度学习不同的是,RNN是一种序列的模型,会有一定的记忆单元,能够记住之前的历史信息,从而可以建模这种上下文相关的一些语义。RNN中的记忆单元可以记住当前词之前的信息。
RNN序列可能会存在梯度消失或梯度爆炸的问题,因此提出LSTM模型。
RNN的三个问题:
1、顺序依赖,t依赖t-1时刻(串行的,很难并行的计算,持续的依赖的关系,通常很慢,无法并行)
The animal didn’t cross the street because it was too tired.
The animal didn’t cross the street because it was too narrow.
2、单向信息流(如仅根据上文或下文的信息不能确定文中it的指代)
3、需要一些比较多的监督数据,对于数据获取成本很高的任务,就比较困难,在实际情况中很难学到复杂的上下文关系
为了解决以上问题研究者们提出了用Transformer模型代替LSTM模型。
2017年6月google团队在《Attention is all your need》论文中提出的Transformer解码器作为语言模型。Transformer模型主要是利用自注意力(self-attention)机制的模型。https://www.cnblogs.com/robert-dlut/p/9824346.html
这篇论文主要亮点在于
(1)不同于以往主流机器翻译使用基于RNN的seq2seq模型框架,该论文用attention机制代替了RNN搭建了整个模型框架。
(2)提出了多头注意力(Multi-headed attention)机制方法,在编码器和解码器中大量的使用了多头自注意力机制(Multi-headed self-attention)。
(3)在WMT2014语料中的英德和英法任务上取得了先进结果,并且训练速度比主流模型更快。
参考bert.docx文件,插入对比表格。
[1] https://blog.csdn.net/jiaowoshouzi/article/details/89073944
[2] https://www.cnblogs.com/gczr/p/11785930.html
[3] https://blog.csdn.net/MarsYWK/article/details/86648812
[4] https://zhuanlan.zhihu.com/p/48612853
[5] https://blog.csdn.net/sparkexpert/article/details/79890972
[6] https://www.cnblogs.com/robert-dlut/p/9824346.html
[7] https://www.cnblogs.com/robert-dlut/p/8638283.html
[8] https://zhuanlan.zhihu.com/p/106106079
[9] https://www.cnblogs.com/robert-dlut/p/9824346.html
[10] https://www.cnblogs.com/robert-dlut/p/8638283.html
[11] https://zhuanlan.zhihu.com/p/106106079
[12] https://zhuanlan.zhihu.com/p/106129657
[13] https://blog.csdn.net/haidixipan/article/details/84299039
[14] https://zhuanlan.zhihu.com/p/56382372
[15] https://zhuanlan.zhihu.com/p/56382372
[16] https://blog.csdn.net/data_scientist/article/details/79063138
跳转下一篇Transformer:link.