PyTorch 中 Linear 和 Embedding 网络层

当我们使用 PyTorch 构建神经网络时,经常使用到一些内置的网络层。本篇文章主要介绍下列层的使用:

  1. 线性层(Linear)
  2. 词嵌入层(Embedding)
  3. 循环网络层(RNN、GRU、LSTM)

1. 线性层

torch.nn.Linear(in_features, out_features, bias=True, device=None)
  1. in_features 表示输入数据特征维度
  2. out_features 表示输出数据特征的维度
  3. bias 表示使用计算偏置
  4. device 表示指定计算设备

我们可以通过以下代码访问线性层的参数、偏置:

linear = nn.Linear(10, 20)
# 权重
print(linear.weight)
# 偏置
print(linear.bias)

PyTorch 中线性层的 weight 和 bias 使用范围 (-sqrt(1/in_features), sqrt(1/in_features))的均匀分布进行初始化。

线性层的计算公式如下:

import torch.nn as nn
import torch


def test():

    # 输入数据
    inputs = torch.randn(1, 10)

    # 线性层计算输出
    linear = nn.Linear(10, 20)
    outputs = linear(inputs)
    print(outputs)

    # 手动计算输出
    outputs = inputs @ linear.weight.data.T + linear.bias.data
    print(outputs)


if __name__ == '__main__':
    test()

程序输出结果:

tensor([[ 0.6065,  0.8099, -0.2903,  0.5085,  0.9268, -0.2801, -0.3360,  0.2642,
         -0.6695,  0.1063,  0.8341, -0.3041,  0.0055,  0.9461, -0.0116,  0.0872,
          0.3282, -0.7090, -0.9739, -0.0739]], grad_fn=<AddmmBackward>)
tensor([[ 0.6065,  0.8099, -0.2903,  0.5085,  0.9268, -0.2801, -0.3360,  0.2642,
         -0.6695,  0.1063,  0.8341, -0.3041,  0.0055,  0.9461, -0.0116,  0.0872,
          0.3282, -0.7090, -0.9739, -0.0739]])

我们发现输出结果是一样的。

2. 词嵌入层

torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, device=None)
  1. num_embeddings 表示词表中词的数量
  2. embedding_dim 表示词嵌入的维度
  3. padding_idx 表示填充词在词表中的序号,默认 None 表示不进行填充,稍后我们了解下该参数的作用

nn.Embedding 层的初始权重默认使用从均值为 0、标准差为 1 的标准正态分布中取值初始化,其并不是固定不变的,而是随着正向计算,反向传播会进行更新。

import torch
import torch.nn as nn


def test():

    # num_embeddings 表示词表共有 10 个单词
    # embedding_dim 表示每个词有 3 维度
    embedding = nn.Embedding(num_embeddings=10, embedding_dim=3, padding_idx=4)
    # 词嵌入矩阵
    print(embedding.weight.data)
    print('-' * 50)

    # 句子进行词嵌入
    sentence = torch.tensor([[1, 2, 3], [6, 7, 8]])
    sentence_embedding = embedding(sentence)
    print(sentence_embedding.data)
    print('-' * 50)

    sentence = torch.tensor([[1, 1, 4, 4], [6, 7, 8, 9]])
    sentence_embedding = embedding(sentence)
    print(sentence_embedding.data)


if __name__ == '__main__':
    test()

程序输出结果:

tensor([[ 2.7255,  1.1158,  0.9272],
        [-0.3430,  1.3805,  0.8425],
        [ 0.1564, -0.9834, -0.5991],
        [-0.9682,  0.0776, -2.0535],
        [ 0.0000,  0.0000,  0.0000],
        [-0.5484, -0.4215,  0.1984],
        [ 0.1445, -0.4071,  1.0063],
        [ 0.8116,  0.6240, -0.1881],
        [ 0.4918, -0.8921, -0.1006],
        [-0.2029,  1.5831,  0.5203]])
--------------------------------------------------
tensor([[[-0.3430,  1.3805,  0.8425],
         [ 0.1564, -0.9834, -0.5991],
         [-0.9682,  0.0776, -2.0535]],

        [[ 0.1445, -0.4071,  1.0063],
         [ 0.8116,  0.6240, -0.1881],
         [ 0.4918, -0.8921, -0.1006]]])
--------------------------------------------------
tensor([[[-0.3430,  1.3805,  0.8425],
         [-0.3430,  1.3805,  0.8425],
         [ 0.0000,  0.0000,  0.0000],
         [ 0.0000,  0.0000,  0.0000]],

        [[ 0.1445, -0.4071,  1.0063],
         [ 0.8116,  0.6240, -0.1881],
         [ 0.4918, -0.8921, -0.1006],
         [-0.2029,  1.5831,  0.5203]]])

我们发现,当 padding_idx 设置为 4 时,embedding.weight.data 第 4 下标位置就被设置为 0,那么当我们的 sentence 中句子长度不一,需要对较短的句子进行 padding 时,就可以用 4 来代替了。同理的,默认 padding_idx 的值为 0,所以在不修改其默认值的情况下,可以使用 0 来 padding 较短的 sentence。

未经允许不得转载:一亩三分地 » PyTorch 中 Linear 和 Embedding 网络层