torch.nn.Parameter(),nn.Embedding()

1.torch.nn.Parameter()函数

self.v = torch.nn.Parameter(torch.FloatTensor(hidden_size))

含义是将一个固定不可训练的tensor转换成可以训练的类型parameter,并将这个parameter绑定到这个module里面(net.parameter()中就有这个绑定的 parameter,所以在参数优化的时候可以进行优化),所以经过类型转换这个变量就变成了模型的一部分,成为了模型中根据训练可以改动的参数。
nn.Parameter()添加的参数会被添加到Parameters列表中,会被送入优化器中随训练一起学习更新 。以上摘自torcn.nn.parameter
访问其中元素时

print(net.parameters())

一个线性的实例:

(1)使用 self.test = torch.rand(1, 2)

import torch
class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel, self).__init__()
        self.test = torch.rand(1, 2)
        self.linear = torch.nn.Linear(1, 1)  # 构造linear对象,参数包括w,b (1,1)为输入,输出样本维度(特征数量)

    def forward(self, x):  # 重写,覆盖Module里的forward
        y_pred = self.linear(x)
        return y_pred


model = LinearModel()  # 实例化
print("模型",model)
print("参数",list(model.named_parameters()))
模型 LinearModel(
  (linear): Linear(in_features=1, out_features=1, bias=True)
)
参数 [('linear.weight', Parameter containing:
tensor([[-0.3734]], requires_grad=True)), ('linear.bias', Parameter containing:
tensor([0.9272], requires_grad=True))]

(2)使用self.test = torch.nn.Parameter(torch.rand(1, 2))#注意:Parameter大写P

import torch
class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel, self).__init__()
        self.test = torch.nn.Parameter(torch.rand(1, 2))#注意:Parameter大写P
        self.linear = torch.nn.Linear(1, 1)  # 构造linear对象,参数包括w,b (1,1)为输入,输出样本维度(特征数量)

    def forward(self, x):  # 重写,覆盖Module里的forward
        y_pred = self.linear(x)
        return y_pred


model = LinearModel()  # 实例化
print("模型",model)
print("参数",list(model.named_parameters()))
模型 LinearModel(
  (linear): Linear(in_features=1, out_features=1, bias=True)
)
参数 [('test', Parameter containing:
tensor([[0.3915, 0.7876]], requires_grad=True)), ('linear.weight', Parameter containing:
tensor([[-0.3052]], requires_grad=True)), ('linear.bias', Parameter containing:
tensor([-0.1999], requires_grad=True))]

2.nn.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)

其为一个简单的存储固定大小的词典的嵌入向量的查找表,意思就是说,给一个编号,嵌入层就能返回这个编号对应的嵌入向量,嵌入向量反映了各个编号代表的符号之间的语义关系。
输入为一个编号列表,输出为对应的符号嵌入向量列表。
第1个参数 num_embeddings 就是生成num_embeddings个嵌入向量。第2个参数 embedding_dim 就是嵌入向量的维度,即用embedding_dim值的维数来表示一个基本单位。
比如下面的代码embedding = nn.Embedding(6, 2),生成6个嵌入向量,每个嵌入向量的维度是2,
以上摘自详见

使⽤了嵌⼊层(embedding layer)来获得输⼊序列中每个词元的特征向量。嵌⼊层的权重是⼀个矩阵,其⾏数等于输⼊词表的⼤小(vocab_size),其列数等于特征向量的维度(embed_size)。对于任意输⼊词元的索引i,嵌⼊层获取权重矩阵的第i⾏(从0开始)以返回其特征向量。

embedding = torch.nn.Embedding(6, 2)
print(embedding.weight)
x=torch.ones(1,2).to(int)
print("x",x)
print("x.shape",x.shape)
y=embedding(x)
print("y",y)
print("y.shape",y.shape)#(,,embed_size)

输出:

Parameter containing:
tensor([[-0.5130, -1.2553],
        [-0.5915,  0.7818],
        [ 0.0382,  0.2250],
        [-0.9197, -0.3909],
        [-1.2444,  0.0630],
        [-1.8657, -0.6756]], requires_grad=True)
x tensor([[1, 1]])
x.shape torch.Size([1, 2])
y tensor([[[-0.5915,  0.7818],
         [-0.5915,  0.7818]]], grad_fn=<EmbeddingBackward>)
y.shape torch.Size([1, 2, 2])

实例:

import collections
import math
import torch
from torch import nn
from d2l import torch as d2l
#@save
class Seq2SeqEncoder(d2l.Encoder):
    """用于序列到序列学习的循环神经网络编码器"""
    def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
                 dropout=0, **kwargs):
        super(Seq2SeqEncoder, self).__init__(**kwargs)
        # 嵌入层
        self.embedding = nn.Embedding(vocab_size, embed_size)##获得每个词元的特征向量
        self.rnn = nn.GRU(embed_size, num_hiddens, num_layers,
                          dropout=dropout)
        #没有dense全连接的输出层,因为encoder不需要输出最终标号

    def forward(self, X, *args):
        # 输出'X'的形状:(batch_size,num_steps,embed_size)
        X = self.embedding(X)
        # 在循环神经网络模型中,第一个轴对应于时间步
        X = X.permute(1, 0, 2)#(num_step,batch_size,)
        # 如果未提及状态,则默认为0
        output, state = self.rnn(X)#拿到最后输出,output是每个时刻最上面的输出,state是最后时刻每一层的输出
        # output的形状:(num_steps,batch_size,num_hiddens)
        # state的形状:(num_layers,batch_size,num_hiddens)
        return output, state
encoder = Seq2SeqEncoder(vocab_size=10, embed_size=8, num_hiddens=16,
                         num_layers=2)
encoder.eval()#dropout不生效
X = torch.zeros((4, 7), dtype=torch.long)#(batch_size,num_step)
output, state = encoder(X)
output.shape#(num_steps,batch_size,num_hiddens)
class Seq2SeqDecoder(d2l.Decoder):
    """用于序列到序列学习的循环神经网络解码器"""
    def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
                 dropout=0, **kwargs):
        super(Seq2SeqDecoder, self).__init__(**kwargs)
        self.embedding = nn.Embedding(vocab_size, embed_size)#获得每个词元的特征向量
        self.rnn = nn.GRU(embed_size + num_hiddens, num_hiddens, num_layers,
                          dropout=dropout)
        self.dense = nn.Linear(num_hiddens, vocab_size)#输出vacab_size的分类

    def init_state(self, enc_outputs, *args):#encoder的state
        return enc_outputs[1]

    def forward(self, X, state):
        # 输出'X'的形状:(batch_size,num_steps,embed_size)
        X = self.embedding(X).permute(1, 0, 2)
        # 广播context,使其具有与X相同的num_steps
        '''上下文操作。这里state[-1]拿到的是“最右上角的”H(这个H融合和所有的信息)如果state是【2,4,16】的,
        那state[-1]就是【1,4,16】的。repeat重复时间步次。
        这样,可以用到每一个时间步最后的H信息,
        与新的输入X做concat操作(这也是为什么解码器的self.rnn是ebd_size + num_hiddens的原因)。
        如果state[-1]是【1,4,16】,时间步是7,那重复完之后就是【7,4,16】的?????
        (7个时间步,4是batch_size,16是state隐藏单元的个数)。'''
        context = state[-1].repeat(X.shape[0], 1, 1)#state[-1]最后时刻最后一层的输出,它包括了最后所有浓缩的信息
        #X_and_context(num_step,batch_size,ebd_size + num_hidden)
        X_and_context = torch.cat((X, context), 2)#DEcoder输入是ENcoder的state和最后context上下文拼在一起
        output, state = self.rnn(X_and_context, state)
        output = self.dense(output).permute(1, 0, 2)
        # output的形状:(batch_size,num_steps,vocab_size)
        # state的形状:(num_layers,batch_size,num_hiddens)
        return output, state
decoder = Seq2SeqDecoder(vocab_size=10, embed_size=8, num_hiddens=16,
                         num_layers=2)
decoder.eval()
state = decoder.init_state(encoder(X))
output, state = decoder(X, state)
output.shape, state.shape

猜你喜欢

转载自blog.csdn.net/weixin_44040169/article/details/126901581