栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

模型的第一层!torch.nn.Embedding和torch.nn.Linear的区别详解

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

模型的第一层!torch.nn.Embedding和torch.nn.Linear的区别详解

文章目录
      • 1.概述
      • 2.Embedding
        • 2.1 全连接层
        • 2.2 Embedding层
      • 结尾

1.概述

torch.nn.Embedding是用来将一个数字变成一个指定维度的向量的,比如数字1变成一个128维的向量,数字2变成另外一个128维的向量。不过,这128维的向量并不是永恒不变的,这些128维的向量是模型真正的输入(也就是模型的第1层)(数字1和2并不是,可以算作模型第0层),然后这128维的向量会参与模型训练并且得到更新,从而数字1会有一个更好的128维向量的表示。

显然,这非常像全连接层,所以很多人说,Embedding层是全连接层的特例。

2.Embedding
import numpy as np
import torch.nn as nn
import torch

比如我们有2个字,

vocab={"我":0,"你":1}

我们要把这两个字变成向量,有两种做法:

2.1 全连接层
vocab={"我":0,"你":1}
vocab_vec=torch.eye(2)#构造one-hot向量,所以需要用两个2维的向量表示这两个字。
print(vocab_vec)

tensor(
[[1., 0.],
[0., 1.]]
)

但是众所周知one-hot向量没有任何的语义信息,而且在这个one-hot中,空间庞大。我们需要一个低维稠密的向量来代替one-hot向量。很简单,一个线性层即可。

fc=nn.Linear(2,2)#原来表示一个字的向量维度是2,为了简单,我们全连接后还是2.
fc(vocab_vec)


上面才是我们想要的这两个字的表示,然后将上述输入到模型的后续层中,进行训练,这样,由于线性层fc的参数会不断变化,所以上面这个数值fc(vocab_vec)当然也会随之而变化喽。

2.2 Embedding层

使用这个会更简单,更方便一些。我们不需要构造one-hot向量,我们开头说过了,Embedding层将一个数字直接转化为你想要的维度的向量,这是好事!比如你内存不够的时候,就不用像上面这种做法那样需要多存储一个one-hot的矩阵。

vocab={"我":0,"你":1}
embedding=torch.nn.Embedding(vocab_size,emb_size)#原来表示一个字的向量维度是2,为了简单,我们全连接后还是2.

然后,我们想要得到我们那两个字(“我”,“你”)的向量,只需要将"我"和"你"的编号输入即可,而不需要那个one-hot向量,比如"我"的编号是0,"你"的编号是1:

me=torch.tensor([0],dtype=torch.int64)
you=torch.tensor([1],dtype=torch.int64)

然后将上述作为参数,传入embedding层。

print(embedding(me))
print(embedding(you))

tensor([[0.6188, 1.5322]], grad_fn=)
tensor([[-0.8198, -0.9139]], grad_fn=)

就得到了上述两个字的向量。当然了,我们也可以合并起来得到:

meyou=torch.tensor([0,1],dtype=torch.int64)
print(embedding(meyou))


同样,上述得到的向量输入到模型的后续中,训练后,Embedding层的参数会随之改变,从而我们得到了更好的字向量。

结尾

可以看到,Embedding和Linear几乎是一样的,区别就在于:输入不同,一个是输入数字,后者是输入one-hot向量。习惯上,我们在模型的第一层使用的是Embedding,而不是Linear。模型的后续不会再使用Embedding,而是使用Linear。

补充:上述我们在做定义的时候,里面的参数是初始化的。

fc=nn.Linear(2,2)
embedding=torch.nn.Embedding(vocab_size,emb_size)

有的时候,我们可能觉得其初始化得不好,想要按照我们的来指定,怎么办?1.使用nn.Parameter直接进行赋值。

myemb=nn.Parameter(torch.rand(2,2))#(0,1)均匀分布的参数
print(fc.weight)#原来的
fc.weight=myemb#修改
print(embedding.weight)#原来的
embedding.weight=myemb#修改


我们再查看修改后的:

当然了,还有很多很多的其他做法,2.使用.data:

embedding.weight.data.uniform_(-1,1)#又改成(-1,1)的均匀分布。
embedding.weight#查看一下


而且以上两种方法都适用于Embedding和Linear。不过,还有一个方法适用于Embedding。3.nn.Embedding.from_pretrained

a=torch.tensor([[1,2],[2,2]],dtype=torch.float32)
embedding=nn.Embedding.from_pretrained(a)
embedding.weight

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/329917.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号