在处理NLP任务时,第一步就会面临着如何将自然语言转化成数字/向量,常见的有下面几种方式
1.利用Pytorch和Tensorflow,自带的编码方式
2.使用one-hot编码
3.使用预训练模型,使词嵌入之间有更好的语义信息(ELMo,Bert)
本篇博客重点介绍第一种方式:Embedding layer,主要的步骤如下:
1.准备好所要使用的语料库
2.构建字典,使语料库中的每个词都对应一个索引
3.利用Embedding Layer对输入的自然语言做embedding,作为网络的第一层
4.训练模型,更新第3步输入的权重
值得注意的是:embedding layer只是对词进行权重初始化,所初始化的权重是符合正态分布。所以可以看出一个句子中的词与词之间是没有任何关系的。所以word2vec,Glove之类的方式是远远要比这种方式有效的多。
Pytorch 中Embedding Layer的用法
官方给出的embedding的参数如下:
torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False, _weight=None, device=None, dtype=None)
num_embeddings : 构建语料库字典的大小
embedding_dim : 每个词向要编码成向量的长度
padding_idx:输出遇到此下标时用0填充(非必要参数)
max_norm:对词嵌入进行归一化,使他们的范数小于max_norm(非必要参数)
norm_type: max_norm在计算范数时的范数类型,如:可以选择1范数,2范数
scale_grad_by_freq:将通过小批量中单词频率的倒数来缩放梯度。这里的词频是指输入的句子。
sparse:如果为True,则与权重矩阵相关的梯度转变为稀疏张量。这里的稀疏张量是指方向传播的时候只更新当前使用此的权重矩阵,加快更新速度。这里和word2vec的负采样有相似之处
下面用一个简单的例子来介绍:
假设我们的语料库如下(引用自狄更斯双城记):
那是最美好的时代,那是最糟糕的时代;那是智慧的年头,那是愚昧的年头;那是信仰的时期,那是怀疑的时期;那是光明的季节,那是黑暗的季节;那是希望的春天,那是失望的冬天;我们拥有一切,我们一无所有;我们全都在直奔天堂,我们全都在直奔相反的方向一一简而言之,那时跟现在非常相像,某些最喧嚣的权威坚持要用形容词的最高级来形容它。说它好,是最高级的;说它不好,也是最高级的这里是引用
想要做embedding的句子为:
失望之冬,希望之春
import torch.nn as nn
#corpus是语料库
corpus = "那是最美好的时代,那是最糟糕的时代;那是智慧的年头,那是愚昧的年头;那是信仰的时期,那是怀疑的时期;那是光明的季节,那是黑暗的季节;那是希望的春天,那是失望的冬天;我们拥有一切,我们一无所有;我们全都在直奔天堂,我们全都在直奔相反的方向一一简而言之,那时跟现在非常相像,某些最喧嚣的权威坚持要用形容词的最高级来形容它。说它好,是最高级的;说它不好,也是最高级的"
#建立语料库对应的字典
word_dict = {}
word_set = set()
for it in corpus:
word_set.add(it)
index = 0
for it in word_set:
word_dict[index] = it
index = index + 1
所建立好的语料字典大致如下:
{0: ‘词’,
1: ‘期’,
2: ‘头’,
3: ‘所’,
4: ‘言’,
5: ‘持’,
…
81: ‘疑’,
82: ‘方’}
在建立好字典之后,我们就可以做embedding了先设置embedding layer的参数:
1.字典的长度为: len(word_dict)
2.假设我们想要为每个字符编码的长度为:3。即一个词用长度为3的向量表示
3.其他设为默认
#这我们想要embedding的句子
input = "失望之冬,希望之春"
#用索引表示句子
raw_input = []
for it in input:
index_it = list(word_dict.keys())[list(word_dict.values()).index(it)]
raw_input.append(index_it)
#得到raw_input为:[58, 66, 22, 62, 80, 41, 66, 22, 72]
#设置embedding的参数
embedding = nn.Embedding(len(word_dict),3)
#打印最终embedding的结果
print(embedding(input_emb))
最终得到的结果是9x3的权重矩阵,这也是我们往后输入到神经网络的矩阵的维度:
tensor([[-0.5556, -0.5511, -1.4122],
[ 0.5721, -1.1856, 0.1831],
[-0.8368, 1.1271, -1.7927],
[-2.0651, -0.3584, 0.2892],
[ 0.3897, -0.4211, -0.7246],
[-0.5848, -0.1685, 0.8156],
[ 0.5721, -1.1856, 0.1831],
[-0.8368, 1.1271, -1.7927],
[-1.1437, -0.1087, -0.8976]])