NLP到Word2Vec实现-第二课

文章目录

  • 词向量到word2vec与相关应用
  • 一、NLP常见任务
    • 1.自动摘要
    • 2.指代消解
    • 3.机器翻译
    • 4.词性标注
    • 5.分词
    • 6.主题识别
    • 7.文本分类
  • 二、NLP处理方法
    • 1.传统:基于规则
    • 2.现代:基于统计机器学习
      • (1)HMM、CRF、SVM、LDA、CNN
      • (2)”规则“隐含在模型参数里
    • 3.词编码需要保证词的相似性
    • 4.向量空间分布的相似性
    • 5.向量空间子结构
    • 6.在计算机中表示词
      • (1)离散表示
        • ①One-hot表示
        • ②Bag of Words
          • 1)TF-IDF (Term Frequency - Inverse Document Frequency):信息检索
          • 2)Binary weighting
        • ③Bi-gram 和N-gram
    • 7.语言模型
      • (1)离散表示的问题
      • (2)分布式表示(Distributed representation)
      • (3)共现矩阵 (Cocurrence matrix)
        • ①定义
        • ②存在的问题
        • ③解决:SVD降维/PCA降维
  • 三、NNLM (Neural Network Language model)
    • 1.定义
    • 2.结构
    • 3.复杂度
    • 4.word2vec: CBOW(连续词袋)
      • (2)CBOW:层次Softmax
      • (3)CBOW:负例采样
    • 5.Word2Vec: Skip-Gram模型
    • 6.Word2Vec: 存在的问题
  • 三、总结
  • 四、工具gensim
    • 1 基本概念
      • (1)语料(Corpus)
      • (2)向量(Vector)
      • (3)稀疏向量(SparseVector)
      • (4)模型(Model)
    • 2 步骤:
      • (1)训练语料的预处理
      • (2)主题向量的变换
      • (3)文档相似度的计算
      • (4)补充

词向量到word2vec与相关应用

一、NLP常见任务

1.自动摘要

2.指代消解

3.机器翻译

4.词性标注

5.分词

6.主题识别

7.文本分类

二、NLP处理方法

1.传统:基于规则

2.现代:基于统计机器学习

(1)HMM、CRF、SVM、LDA、CNN

(2)”规则“隐含在模型参数里

3.词编码需要保证词的相似性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-osN44u87-1642402706254)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117104705603.png)]

4.向量空间分布的相似性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u4ZDVjyy-1642402706255)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117104734785.png)]

左:英语 右:西班牙语

5.向量空间子结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqZiZnnK-1642402706256)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117104815419.png)]

6.在计算机中表示词

(1)离散表示

①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]

❖ 词典包含10个单词,每个单词有唯一索引

❖ 在词典中的顺序和在句子中的顺序没有关联

②Bag of Words

文档的向量表示可以直接将各词的词向量表示加和

John likes to watch movies. Mary likes too.

John also likes to watch football games.

Ø 词权重 :词在文档中的顺序没有被考虑

1)TF-IDF (Term Frequency - Inverse Document Frequency):信息检索

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pOa12GMK-1642402706256)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117105203149.png)]

[0.693, 1.386, 0.693, 0.693, 1.099, 0, 0, 0, 0.693, 0.693]

2)Binary weighting

短文本相似性,Bernoulli Naive Bayes

[1, 1, 1, 1, 1, 0, 0, 0, 1, 1]

③Bi-gram 和N-gram

优点:考虑了词的顺序

缺点:词表的膨胀

为2-gram建索引:

"John likes” : 1,

"likes to” : 2,

"to watch”: 3,

"watch movies” : 4,

"Mary likes” : 5,

"likes too” : 6,

"John also”: 7,

"also likes” : 8,

“watch football”: 9,

“football games”: 10,

John likes to watch movies. Mary likes too.

[1, 1, 1, 1, 1, 1, 0, 0, 0, 0]

John also likes to watch football games.

[0, 1, 1, 0, 0, 0, 1, 1, 1, 1]

7.语言模型

一句话 (词组合) 出现的概率 ——基于贝叶斯公式

工业上一般不用连乘的方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XStvxkWd-1642402706257)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117105540700.png)]

(1)离散表示的问题

Ø 无法衡量词向量之间的关系——各种度量(与或非、距离) 都不合适

酒店 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

宾馆 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]

旅舍 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]

Ø 词表维度随着语料库增长膨胀

Ø n-gram词序列随语料库膨胀更快

Ø 数据稀疏问题

(2)分布式表示(Distributed representation)

分布式:自己承担很难,就把东西分担出去,再把信息汇总起来

前面是一个模板的话

需要一个短语的方式

大大缩减了存储空间

用一个词附近的其他词来表示该词

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpqDTslS-1642402706257)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117105831414.png)]

(3)共现矩阵 (Cocurrence matrix)

每个词可以用周边次representation,我不知道你的生活习惯,就找你的朋友收入、习惯,大概就知道你是什么样的人。找朋友的方式就是你肯定会经常和他们一起。

问题:到底要找几个朋友

①定义

Word - Document 的共现矩阵主要用于发现主题(topic),用于主题模型,如LSA (Latent Semantic Analysis)

局域窗中的Word - Word 共现矩阵可以挖掘语法和语义信息

• I like deep learning.

• I like NLP.

• I enjoy flflying.

window length设为1(一般设为5~10)

使用对称的窗函数(左右window length都为1)”对于like而言,I隔了一个位置,就是朋友

I like 共同出现了2次,

②存在的问题

Ø将共现矩阵行(列)作为词向量

​ • 向量维数随着词典大小线性增长

​ • 存储整个词典的空间消耗非常大

​ • 一些模型如文本分类模型会面临稀疏性问题构造低维稠密向量作为词的分布式表示 (25~1000维)!

​ • 模型会欠稳定

③解决:SVD降维/PCA降维

用SVD对贡献矩阵向量做降维。构建共现矩阵,然后做SVD的分解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6UHIgFx-1642402706258)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117112545413.png)]

问题:

Ø 计算量随语料库和词典增长膨胀太快,对X(n,n)维的矩阵,计算量O(n^3)。 而对大型的语料库,n400k,语料库大小160B token

Ø 难以为词典中新加入的词分配词向量

Ø 与其他深度学习模型框架差异大

三、NNLM (Neural Network Language model)

1.定义

固定滑动窗口的大小

滑动窗口会遍历整个语料库求和

看完整个语料库之后,再去做推断

语言模型:会构造一个目标函数,loss Function:评估差距有多大,objective Function

Ø 直接从语言模型出发,将模型最优化过程转化为求词向量表示的过程

​ 目标函数(最大似然)

Ø 使用了非对称的前向窗函数,窗长度为n-1

Ø 滑动窗口遍历整个语料库求和,计算量正比于语料库大小

Ø 概率P满足归一化条件,这样不同位置t处的概率才能相加,即

2.结构

有一个语料库,eg:4-gram,用前面三个词去预测第四个词,用w1,w2,w3预测w4,所以前面三个词在下面w1,w2,w3,用若干次

projection layer:(在one-hot中做dense 将对应w1的词取出来)

​ 输入是一个one-hot的表示,从词海里面找了10w个短语,就编码一个10w个行向量

​ w1,w2,w3就是10w个,中间有一个是1

在最底层和上一层有矩阵C:一共有10w个词,想要编码为300维,c就是(30010w),one-hot的矩阵是(10w,1)两个向量相乘之后,维度就变为了(300,1)*

相当于从10w中挑出来真正想要的词向量:我爱北京,三个词向量作拼接

最后要得到的结果是:我爱北京,这三个词都确定了,不能确定下一个词是不是天安门,就要把这10w个词的概率拿出来,看天安门的概率向量是多少

• (N-1)个前向词:one-hot表示

• 采用线性映射将one-hot表示投影到稠密D维表示

• 输出层:Softmax

• 各层权重最优化:BP+SGD

C矩阵是投影矩阵,也是稠密词向量表示

3.复杂度

每个训练样本的计算复杂度:N * D + N * D * H + H * V

一个简单模型在大数据量上的表现比复杂模型在少数据量上的表现会好

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3JbOejQI-1642402706259)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117110335222.png)]

4.word2vec: CBOW(连续词袋)

eg:corpus=[ 我喜欢 学习 机器学习 ]

想要通过“我喜欢”“机器学习”去预测中间的“学习”

我喜欢机器学习就是词向量

projection layer:就是把词向量拼接在一起了

word2vector就做了一个简化,去掉了projection layer,将几个词向量加起来求和,直接去预测后面那个词

输入层就是用的稠密向量

最大化的情况下,去预测概率

10w个词中的概率向量,就取

无隐层

使用双向上下文窗口

上下文词序无关 (BoW)

输入层直接使用低维稠密表示

投影层简化为求和(平均)

(2)CBOW:层次Softmax

10w维太大了,需要处理一下:可以用层次softmax,10w个太长了,要编码成低维度,并且所有的词都还在

————哈夫曼编码

一句话,(我 喜欢 观看 巴西 足球 世界杯)

​ 根据词出现的词频,展开得到6 个节点,长度为6的概率向量

​ 但是平铺太麻烦了,就有个哈夫曼树

根据我 喜欢 观看 巴西 足球 世界杯出现的频次,编码成一棵树

这棵树到每个节点做决策都只有两个,左右分支 0和1

每个权重都在点和边连接的上面

将θ做简化,我们需要有300*10w的权重,计算量太大了。编码成树之后,就把θ放到了树上

每个做决策的树上都有一个权重,因为是0和1,所以就是二分类,之前是v,现在是logv量级

如果我喜欢观看巴西,后面是足球,哈夫曼编码就是1,0,0,1

其实每个节点是分类,

• 使用Huffman Tree 来编码输出层的词典

• 只需要计算路径上所有非叶子节点词向量的贡献即可

• 计算量降为树的深度 V => log_2(V)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uu4wL8cE-1642402706260)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117110557376.png)]

左走的是sigmoid的,右走的是1-sigmoid的

Ø Sigmoid函数

Ø n(w,j):Huffman数内部第j层的节点

Ø ch(n(w,j)):n节点的child节点

Ø [[n(w,j+1)=ch(n(w,j)]] 是选择函数,表明只选择从根节点到目标叶节点路径上的内部节点

(3)CBOW:负例采样

P(w|context(w)): 一个正样本,V-1个负样本,对负样本做采样

取出一部分的负样本就好了,然后用平铺的方式展开

凭什么从10w-1到499个负样本

将这个线段划成108 等分,对应的词频是不一样的,频次不一样,采样的权重是不一样的,根据权重判断要分多长的线段,作为它所处的线段

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfkfSwx3-1642402706261)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117143141882.png)]

负样本就是:取出499个负样本与1个正样本一起构建一个哈夫曼树

我喜欢学习机器学习,要从我 喜欢 机器学习,预测学习。那么

​ 正样本:学习

最后是10w个里面找学习就太多太多了,方法就是:哈夫曼树,和负例采样

5.Word2Vec: Skip-Gram模型

Ø 无隐层

Ø 投影层也可省略

Ø 每个词向量作为log-linear模型的输入

目标函数:

Ø 概率密度由Softmax给出

6.Word2Vec: 存在的问题

Ø 对每个local context window单独训练,看不到全局信息

​ 没有利用包含在global co-currence矩阵中的统计信息

Ø 对多义词无法很好的表示和处理,因为使用了唯一的词向量

三、总结

❖ 离散表示

• One-hot representation, Bag Of Words Unigram语言模型

• N-gram词向量表示和语言模型

• Co-currence矩阵的行(列)向量作为词向量

❖ 分布式连续表示

• Co-currence矩阵的SVD降维的低维词向量表示

• Word2Vec: Continuous Bag of Words Model

• Word2Vec: Skip-Gram Model

四、工具gensim

1 基本概念

(1)语料(Corpus)

一组原始文本的集合,用于无监督地训练文本主题的隐层结构。语料中不需要人工标注的附加信息。在Gensim中,Corpus通常是一个可迭代的对象(比如列表)。每一次迭代返回一个可用于表达文本对象的稀疏向量。

(2)向量(Vector)

由一组文本特征构成的列表。是一段文本在Gensim中的内部表达。

(3)稀疏向量(SparseVector)

通常,我们可以略去向量中多余的0元素。此时,向量中的每一个元素是一个(key, value)的元组

(4)模型(Model)

是一个抽象的术语。定义了两个向量空间的变换(即从文本的一种向量表达变换为另一种向量表达)。

2 步骤:

(1)训练语料的预处理

由于Gensim使用python语言开发的,为了减少安装中的繁琐,直接使用anaconda工具进行集中安装,
输入:pip install gensim,这里不再赘述。

训练语料的预处理指的是将文档中原始的字符文本转换成Gensim模型所能理解的稀疏向量的过程。

通常,我们要处理的原生语料是一堆文档的集合,每一篇文档又是一些原生字符的集合。在交给Gensim的模型训练之前,我们需要将这些原生字符解析成Gensim能处理的稀疏向量的格式。由于语言和应用的多样性,我们需要先对原始的文本进行分词、去除停用词等操作,得到每一篇文档的特征列表。例如,在词袋模型中,文档的特征就是其包含的word:

texts = [['human', 'interface', 'computer'],
 ['survey', 'user', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'system'],
 ['system', 'human', 'system', 'eps'],
 ['user', 'response', 'time'],
 ['trees'],
 ['graph', 'trees'],
 ['graph', 'minors', 'trees'],
 ['graph', 'minors', 'survey']]
# 其中,corpus的每一个元素对应一篇文档。

接下来,我们可以调用Gensim提供的API建立语料特征(此处即是word)的索引字典,并将文本特征的原始表达转化成词袋模型对应的稀疏向量的表达。依然以词袋模型为例:

from gensim import corpora
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus[0]) # [(0, 1), (1, 1), (2, 1)]

到这里,训练语料的预处理工作就完成了。我们得到了语料中每一篇文档对应的稀疏向量(这里是bow向量);

向量的每一个元素代表了一个word在这篇文档中出现的次数

值得注意的是,虽然词袋模型是很多主题模型的基本假设,这里介绍的doc2bow函数并不是将文本转化成稀疏向量的唯一途径。

最后,出于内存优化的考虑,Gensim支持文档的流式处理。我们需要做的,只是将上面的列表封装成一个Python迭代器;每一次迭代都返回一个稀疏向量即可。

class MyCorpus(object):
  def iter(self):
    for line in open('mycorpus.txt'):
 # assume there's one document per line, tokens separated by whitespace
				yield dictionary.doc2bow(line.lower().split())

(2)主题向量的变换

对文本向量的变换是Gensim的核心。通过挖掘语料中隐藏的语义结构特征,我们最终可以变换出一个简洁高效的文本向量。

在Gensim中,每一个向量变换的操作都对应着一个主题模型,例如上一小节提到的对应着词袋模型的doc2bow变换。每一个模型又都是一个标准的Python对象。下面以TF-IDF模型为例,介绍Gensim模型的一般使用方法。

首先是模型对象的初始化。通常,Gensim模型都接受一段训练语料(注意在Gensim中,语料对应着一个稀疏向量的迭代器)作为初始化的参数。显然,越复杂的模型需要配置的参数越多。

from gensim import models
tfidf = models.TfidfModel(corpus)

其中,corpus是一个返回bow向量的迭代器。这两行代码将完成对corpus中出现的每一个特征的IDF值的统计工作。

接下来,我们可以调用这个模型将任意一段语料(依然是bow向量的迭代器)转化成TFIDF向量(的迭代器)。需要注意的是,这里的bow向量必须与训练语料的bow向量共享同一个特征字典(即共享同一个向量空间)。

doc_bow = [(0, 1), (1, 1)]
print tfidf[doc_bow] # [(0, 0.70710678), (1, 0.70710678)]

注意,同样是出于内存的考虑,model[corpus]方法返回的是一个迭代器。如果要多次访问model[corpus]的返回结果,可以先将结果向量序列化到磁盘上。

我们也可以将训练好的模型持久化到磁盘上,以便下一次使用:

tfidf.save("./model.tfidf")
tfidf = models.TfidfModel.load("./model.tfidf")
Gensim内置了多种主题模型的向量变换,包括LDA,LSI,RP,HDP等。这些模型通常以bow向量或tfidf向量的语料为输入,生成相应的主题向量。所有的模型都支持流式计算。关于Gensim模型更多的介绍,可以参考这里:API Reference(https://radimrehurek.com/gensim/apiref.html)

(3)文档相似度的计算

在得到每一篇文档对应的主题向量后,我们就可以计算文档之间的相似度,进而完成如文本聚类、信息检索之类的任务。在Gensim中,也提供了这一类任务的API接口。

以信息检索为例。对于一篇待检索的query,我们的目标是从文本集合中检索出主题相似度最高的文档。

首先,我们需要将待检索的query和文本放在同一个向量空间里进行表达(以LSI向量空间为例):

# 构造LSI模型并将待检索的query和文本转化为LSI主题向量
# 转换之前的corpus和query均是BOW向量
lsi_model = models.LsiModel(corpus, id2word=dictionary,num_topics=2)
documents = lsi_model[corpus]
query_vec = lsi_model[query]

接下来,我们用待检索的文档向量初始化一个相似度计算的对象:

index = similarities.MatrixSimilarity(documents)

我们也可以通过save()和load()方法持久化这个相似度矩阵:

index.save('/tmp/test.index')
index = similarities.MatrixSimilarity.load('/tmp/test.index')

注意,如果待检索的目标文档过多,使用similarities.MatrixSimilarity类往往会带来内存不够用的问题。此时,可以改用similarities.Similarity类。二者的接口基本保持一致。

最后,我们借助index对象计算任意一段query和所有文档的(余弦)相似度:

sims = index[query_vec]
# 返回一个元组类型的迭代器:(idx, sim)

(4)补充

TF-IDF
TF-IDF(注意:这里不是减号)是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。

  1. 一个词预测主题能力越强,权重就越大,反之,权重就越小。我们在网页中看到“原子能”这个词,或多或少地能了解网页的主题。我们看到“应用”一次,对主题基本上还是一无所知。因此,“原子能“的权重就应该比应用大。
  2. 应删除词的权重应该是零。

LDA文档主题生成模型
LDA是一种文档主题生成模型,包含词、主题和文档三层结构。

所谓生成模型,就是说,我们认为一篇文章的每个词都是通过“以一定概率选择了某个主题,并从这个主题中以一定概率选择某个词语”这样一个过程得到。文档到主题服从多项式分布,主题到词服从多项式分布。

LDA是一种非监督机器学习技术,可以用来识别大规模文档集或语料库中潜藏的主题信息。它采用了词袋的方法,这种方法将每一篇文档视为一个词频向量,从而将文本信息转化为了易于建模的数字信息。

你可能感兴趣的:(自然语言处理,自然语言处理,word2vec,机器学习)