ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

深度学习38:RNN前置知识:基础知识,词向量和词嵌入

深度学习38:RNN前置知识:基础知识,词向量和词嵌入

目录标题

      • 一、自然语言处理概述
        • 1、基于同义词词典的方法
        • 2、基于计数的方法
        • 3、基于推理的方法
      • 二、词嵌入层
        • 什么是词嵌入
        • API使用(这里词嵌入矩阵随机生成,没经过训练)

一、自然语言处理概述

我们平日使用的语言,如汉语或英语,称为自然语言。自然语言处理(Natural Language Processing,NLP)的目标就是让计算机理解人类语言,进而完成对我们有帮助的事情。
说到计算机可以理解的语言,我们可能会想到编程语言或者标记语言等。这些语言的语法定义可以唯一性地解释代码含义,计算机也能根据确定的规则分析代码。编程语言是一种机械的、缺乏活力的语言。换句话说,它是一种“硬语言”。而汉语或英语等自然语言是“软语言”,其含义和形式会灵活变化,并且会不断出现新的词语或新的含义。要让计算机去理解自然语言,使用常规方法是无法办到的。下面是几个解决方法

1、基于同义词词典的方法

具有相同(同义词)或类似(近义词)含义的单词,可以归到同一个类别中;而根据单词“整体-部分”或者“上位-下位”关系,可以构建出层级的树状图。
这样,就可以构成一个庞大的“单词网络”,用它就可以教会计算机单词之间的关系,从而计算出单词的“相似度”。
主要缺点:

  • 需要人工逐个定义单词之间的相关性,非常费时费力;
  • 新词不断出现,语言不断变化,词典维护成本极高;
  • 在表现力上也有限制。
2、基于计数的方法

大量的文本数据,构成了 语料库(corpus)。
我们的目的,就是从语料库中,自动且高效地提取出语言的“本质”。最简单的做法,就是统计“词频”

  • 分词:对词进行统计,首先需要对文本内容进行切分,找出一个个基本单元
  • 词关联ID:给单词标上一个 ID,构建单词和ID的关联字典(称为“词表”)
  • 词向量化:用一个固定长度的向量来表示单词,也称为词的“分布式表示”

对每一个词,可以统计它周围出现了什么单词、出现了多少次(称为“上下文”);把这些词频统计出来,就构成了一个向量;这个向量就可以表示当前的词了,称为“词向量”(word vector)。这样,所有词对应的向量,汇总起来就是一个矩阵,被称为 共现矩阵(co-occurrence matrix)。

主要缺点

对所有词进行向量化表示的计算复杂度极高。

3、基于推理的方法

除了基于计数的方法,还可以使用推理的方法把词用向量表示出来。
我们希望在已知上下文的前提下,“推测”当前位置的词是什么。
利用神经网络,接收上下文信息作为输入,通过模型计算,输出各个单词可能得出现概率;从而就可以根据上下文,预测该出现的单词了。

二、词嵌入层

什么是词嵌入

自然语言是由文字构成的,而语言的含义是由单词构成的。即单词是含义的最小单位。因此为了让计算机理解自然语言,首先要让它理解单词含义。
词向量是用于表示单词意义的向量,也可以看作词的特征向量。将词映射到向量的技术称为词嵌入(Word Embedding)。


还有一种使用向量表示单词意义的方式是独热向量,独热向量很容易构建,但它们通常不是一个好的选择。一个主要原因是独热向量不能准确表达不同词之间的相似度。比如使用余弦相似度x T y ∣ ∣ x ∣ ∣ ∣ ∣ y ∣ ∣ \frac{x^Ty}{||x|| ||y||}∣∣x∣∣∣∣y∣∣xTy​来表示两个词之间的相似程度,由于任意两个不同词的独热向量之间的余弦相似度为 0,所以独热向量不能编码词之间的相似性。另一个原因是随着词汇量的增大,独热向量表示的向量大小也会增大,在词汇量较大的情况下会消耗大量的存储资源与计算资源。

将词转换为词向量时:

首先需要对文本进行分词,再根据需要进行清洗和标准化。

构建词表(Vocabulary),每个词对应一个索引。

使用词嵌入矩阵将词索引转换为词向量。

API使用(这里词嵌入矩阵随机生成,没经过训练)

可使用torch.nn.Embedding来初始化词嵌入矩阵:

torch.nn.Embedding(num_embeddings,embedding_dim)# num_embeddings:词的数量# embedding_dim:词向量的维度

例:
先安装jieba库用于分词:pip install jieba。

#%%importtorchimporttorch.nnasnnimportjieba# 设置随机种子torch.manual_seed(42)text="自然语言是由文字构成的,而语言的含义是由单词构成的。即单词是含义的最小单位。因此为了让计算机理解自然语言,首先要让它理解单词含义。"# 自定义停用词和标点符号stopwords={"的","是","而","由",",","。","、"}# 分词,过滤停用词和标点,去重,构建词表words=[wordforwordinjieba.lcut(text)ifwordnotinstopwords]vocab=list(set(words))# 词表print(f'去重后的列表f{vocab}')# 去重后的列表f['首先', '语言', '单词', '文字', '即', '因此', '为了', '最小', '计算机', '让', '要', '它', '单位', '理解', '自然语言', '含义', '构成']# 构建词到索引的映射word2idx=dict()foridx,wordinenumerate(vocab):word2idx[word]=idxprint(f'word2idx,根据单词找到下标:{word2idx}')# 初始化嵌入层embed=nn.Embedding(num_embeddings=len(word2idx),embedding_dim=5)# 打印词向量foridx,wordinenumerate(vocab):word_vec=embed(torch.tensor(idx))# 通过索引获取词向量print(f"{idx:>2}:{word:8}\t{word_vec.detach().numpy()}")#打印输出如下word2idx,根据单词找到下标:{'首先':0,'语言':1,'单词':2,'文字':3,'即':4,'因此':5,'为了':6,'最小':7,'计算机':8,'让':9,'要':10,'它':11,'单位':12,'理解':13,'自然语言':14,'含义':15,'构成':16}0:首先[1.92691531.48728410.9007172-2.1055210.6784184]1:语言[-1.2345449-0.04306748-1.604667-0.75213531.648723]2:单词[-0.39247864-1.4036071-0.7278813-0.5594302-0.7688389]3:文字[0.76244541.6423169-0.15959747-0.497397540.43958926]4:即[-0.758131151.07831760.800800561.68062061.2791244]5:因此[1.29642280.61046651.3347378-0.231624320.04175949]6:为了[-0.25157530.8598585-1.3846737-0.87123615-0.22336592]7:最小[1.71736150.31888032-0.424518970.30572093-0.7745925]8:计算机[-1.55757250.9956361-0.87978584-0.60114205-1.2741512]9:让[2.122785-1.2346531-0.48791388-0.913823-0.65813726]10:要[0.078023870.52580875-0.487991721.191369-0.81400764]11:它[-0.7359928-1.40324780.03600367-0.063477270.6756149]12:单位[-0.097806891.844594-1.18453741.38354931.4451338]13:理解[0.856412532.21807580.52316550.346646670.5246226]14:自然语言[1.14120160.05164360.72810954-0.7106419-0.6020683]15:含义[0.96044880.40481427-0.827768861.3347030.48353928]16:构成[-0.197561681.26831141.22426280.098117211.7422527]

这段代码是 Python 的 **f-string(格式化字符串)**语法。>和:后面跟的数字是用来控制输出格式的。

具体拆解如下:

1.{idx:>2}中的>2

  • >:表示右对齐(Right align)。
  • 2:表示该字段的最小宽度为 2 个字符。
  • 效果:如果idx是1,输出就是" 1"(前面补一个空格);如果是12,输出就是"12"。这样可以 让输出的序号整齐排列。

2.{word:8}中的8

  • 默认行为:对于字符串,默认是左对齐。
  • 8:表示该字段的最小宽度为 8 个字符。
  • 效果:如果word是"cat",输出就是"cat "(后面补 5 个空格);如果单词超过 8 个字符,则原样输出,不会截断。这同样是为了让后面的向量数据对齐,看起来更美观。
返回列表