详解深度学习之Embedding

更新时间:2023-07-26 11:34:53 阅读: 评论:0

详解深度学习之Embedding背斜
深⼊理解深度学习之 Embedding
1. 从 one-hot 编码引⼊ Embedding
三亮三比三评在正式介绍 Embedding 之前,我们必须先理解它提出的背景,也就是说研究者提出 Embedding 是为了解决什么问题。
⾸先我们有⼀个 one-hot 编码的概念。我们知道神经⽹络是不能处理字符数据的,所以在⽂本预处理中对⼀句话进⾏数值编码,⽐如对于⼀句话“我 从 哪 ⾥ 来 要 到 何 处 去”,我们可能会很直观的对每个字进⾏ 从 0 到 N(N 表⽰所有不同字符的个数) 这样的索引编码,于是就有:
[我 从 哪 ⾥ 来 要 到 何 处 去] → [0 1 2 3 4 5 6 7 8 9]
有⼈会提出质疑,原本没有数值⼤⼩的字符经过这种形式的编码之后,好像存在某种⼤⼩关系和顺序关系,即:2 > 1,但实际字符 “哪”与 “从” 却并没有数值含义。所以就有⼈提出了没有数值含义的 one-hot 编码,也被称为独热编码,对上⾯的那句话进⾏独热编码后如下:
这样处理之后好像解决了上⾯的问题,并且 one-hot 编码具有计算⽅便,表达能⼒强的优点。但是缺点
也随之⽽来,⼀篇硕⼠论⽂不同的字可能会达到 1 万,⽽每篇⽂章的总字数也会有 5 万,难道我们在编码⼀篇⽂章的时候要建⽴⼀个 5W x 1W 的矩阵,我们⽴刻能想到这种编码⽅式所带来存储量的问题。所以归纳之后,独热编码 one-hot encoding 存在的问题包括如下:1. ⼤量为 0 的稀疏矩阵;2. 硬编码,特征没有语义信息;
3. 特征维度较⾼,且每个特征都彼此独⽴,训练所需要的数据量⾼,容易导致维度灾难;
所以就引⼊了我们要介绍的 Embedding,我们再来考虑⼀个场景来说明 Embedding 是如何解决上述问题的,假如我们现在需要对 girl、woman、boy 和 man 四个单词进⾏编码,如果采⽤ one-hot 编码形式,就可以得到如下的矩阵:
但是我们从语义上理解这个四个单词的含义就会发现,具有年龄和性别上的差异,假如我们设定性别为男时,记作1,性别为⼥时,记作0;年龄⼤于20时,记作1,⼩于20岁时记作0,于是既可以得到下表:
gender
age girl
⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡1000000000
01000000000010000000000100000000001000000000010000000000100000000001000000000010
0000000001⎦
⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤⎣⎢⎢⎡1000
01000010
0001⎦
⎥⎥⎤
woman 0
1boy 10man
1
1
gender
age 我们很⾃然的挖掘到 2 个语义特征,所以将上⾯的四个单词编码如下:
从上⾯的例⼦中可以看到,特征维度由 4 变成了 2,⽽且好像具备了语义信息,这就是 Embedding 做的事,从数据中⾃动学习到输⼊空间的信息表⽰的映射 ,由于上述计算中没有涉及到  ,所以 Embedding 的训练过程是⽆监督的。
注意:这⾥的例⼦是对输⼊张量使⽤ Embedding 做降维,但是实际上还可以使⽤ Embedding 来做升维处理,。
2. PyTorch 实现 Embedding
如果我们仅仅从词向量的⾓度理解,Embedding 所做的⼯作就是把⼀个维数为所有词数量的⾼维空间嵌⼊到⼀个维数低得多的连续向量空间中,每个词或词组被映射为实数域上的向量。
在 PyTorch 中,针对词向量有⼀个专门的层 nn.Embedding  ,⽤来实现词与词向量的映射。nn.Embedding  相当于⼀个词表,形状为
(num_embedings, embedding_dim) ,其中 num_embedding 表⽰词表的长度,embedding_dim 表⽰词向量的维度,如果输⼊张量中不同
词的个数超过词表的长度,就会报数组越界异常。
num_embedding(int):size of the dictionary of embeddings embedding_dim(int):the size of each embedding vector
如果 Embedding 层的输⼊形状为 NxM(N为batch_size,M是序列的长度),则输出的形状是 N x M x embedding_dim.注意:输⼊必须是 LongTensor 类型,可以通过 tensor.long() ⽅法转成 LongTensor。
import  numpy as  np import  torch
import  torch .nn as  nn
import  torch .nn .functional as  F
儿童剪纸
word_to_idx = {'girl': 0, 'boy': 1, 'woman': 2, 'man': 3}  # 每个单词⽤⼀个数字表⽰embeds = nn .Embedding (8, 2) # 单词的个数8,2位embedding 的维度inputs = torch .LongTensor ([[word_to_idx [key ] for  key in  word_to_idx .keys ()]])inputs = torch .autograd .Variable (inputs )# 获取Variable 对应的embedding ,并打印出来outputs = embeds (inputs )print (outputs )print (embeds .weight )
⎣⎢⎢⎡00110101⎦
⎥⎥⎤f label
tensor([[[-0.9663, -0.6391],
[-2.2001,  0.7629],
[0.1813, -1.1935],
[-0.3214, -0.9004]]], grad_fn=<EmbeddingBackward>)
Parameter containing:
tensor([[-0.9663, -0.6391],
[-2.2001,  0.7629],
[0.1813, -1.1935],
[-0.3214, -0.9004],
[-1.7540,  0.0908],
[1.1053, -0.8680],
[0.2549,  0.2402],
[0.9486, -0.7895]], requires_grad=True)
注:Embedding的权重也是可以训练的,既可以采⽤随机初始化,也可以采⽤预训练好的词向量初始化。
3. 使⽤ Embedding 训练的 RNN
需求:实现⼀个2层的RNN,加⼀个Embedding 嵌⼊层,将字符序列 “hello” 转化为 “ohlol”
中原会战class Module):
def__init__(lf, input_size, embedding_size, hidden_size, num_layers, num_class):
super(Model, lf).__init__()
# 嵌⼊层
# RNN层
< = RNN(input_size=embedding_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True)
# 全连接层
lf.fc = Linear(hidden_size, num_class)
def forward(lf, x):
为什么叫骆驼祥子
# 初始化隐藏层h0
hidden = s(num_layers, x.size(0), hidden_size)
x = lf.embed(x)# (batch, qLen, embeddingSize)
x, _ = lf.rnn(x, hidden)
x = lf.fc(x)
return x.view(-1, num_class)
# 构造数据集
idx2char =['e','h','l','o']
x_data =[[1,0,2,2,3]]# (batch, q_len)
y_data =[3,1,2,3,2]# (batch * q_len)
inputs = torch.LongTensor(x_data)
labels = torch.LongTensor(y_data)
# 初始化参数
num_class =4
input_size =4# 词典长度
hidden_size =8
embedding_size =8
num_layers =2
batch_size =1
q_len =5
net = Model(input_size, embedding_size, hidden_size, num_layers, num_class)
criterion = CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)
"""
秋天景色的词语这⾥就不⽤再对字符进⾏one-hot编码了,直接做索引编码即可
"""
for epoch in range(15):
<_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, idx = outputs.max(dim=1)
idx = idx.data.numpy()
print('Predicted: ',''.join([idx2char[x]for x in idx]), end='')
print(', Epoch [%d/15] loss = %.3f'%(epoch +1, loss.item()))
模型的训练过程如下:
Predicted:  hllll, Epoch [1/15] loss =1.268美白针有副作用吗
Predicted:  ollll, Epoch [2/15] loss =1.066
Predicted:  ollll, Epoch [3/15] loss =0.878
Predicted:  ohlll, Epoch [4/15] loss =0.679
Predicted:  ohlol, Epoch [5/15] loss =0.500
Predicted:  ohlol, Epoch [6/15] loss =0.369
Predicted:  ohlol, Epoch [7/15] loss =0.237
纷沓而至Predicted:  ohlol, Epoch [8/15] loss =0.154
Predicted:  ohlol, Epoch [9/15] loss =0.103
Predicted:  ohlol, Epoch [10/15] loss =0.069
Predicted:  ohlol, Epoch [11/15] loss =0.048
Predicted:  ohlol, Epoch [12/15] loss =0.035
Predicted:  ohlol, Epoch [13/15] loss =0.025
Predicted:  ohlol, Epoch [14/15] loss =0.019
Predicted:  ohlol, Epoch [15/15] loss =0.014
最后我认为 Embedding ⼀开始可能只有感性的理解,但是随着应⽤和实践不断的积累,就会对它有新的认识。

本文发布于:2023-07-26 11:34:53,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1097282.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:编码   没有   训练
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图