dropout层、线性层、layernorm

dropout层:防止过拟合

nn.dropout 每次将 p 元素设置为 0,剩下的元素乘以 1/(1-p)

eval()模式不进行dropout

使用方法如下:

In [1]: import torch

In [2]: p = 0.5

In [3]: module = torch.nn.Dropout(p)

In [4]: module.training
Out[4]: True

In [5]: inp = torch.ones(3,5)

In [6]: print(inp)
tensor([[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]])

In [7]: module(inp)
Out[7]:
tensor([[0., 0., 0., 2., 0.],
        [2., 2., 0., 0., 2.],
        [2., 0., 2., 2., 2.]])

In [10]: 1/(1-p)
Out[10]: 2.0

In [11]: module.eval()
Out[11]: Dropout(p=0.5, inplace=False)

In [12]: module.training
Out[12]: False

In [13]: module(inp)
Out[13]:
tensor([[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]])

Linear层

In [1]: import torch

In [2]: module = torch.nn.Linear(10,20)

In [3]: module
Out[3]: Linear(in_features=10, out_features=20, bias=True)

In [4]: n_samples = 40

In [5]: inp_2d = torch.rand(n_samples,10)

In [6]: module(inp_2d).shape
Out[6]: torch.Size([40, 20])

In [7]: inp_3d = torch.rand(n_samples,33,10)

In [8]: module(inp_3d).shape
Out[8]: torch.Size([40, 33, 20])

In [10]: input_7d = torch.rand(n_samples,2,3,4,5,6,10)

In [12]: module(input_7d).shape
Out[12]: torch.Size([40, 2, 3, 4, 5, 6, 20])

LayerNorm属性

可学习参数为0

In [1]: import torch

In [2]: inp = torch.tensor([[0,4.],[-1,7],[3,5]])

In [3]: n_samples,n_features = inp.shape

In [4]: print(n_samples)
3

In [5]: module = torch.nn.LayerNorm(n_features, elementwise_affine=False)

In [6]: sum(p.numel() for p in module.parameters() if p.requires_grad)
Out[6]: 0

In [7]: inp.mean(-1),inp.std(-1,unbiased=False)
Out[7]: (tensor([2., 3., 4.]), tensor([2., 4., 1.]))

In [8]: module(inp).mean(-1),module(inp).std(-1,unbiased=False)
Out[8]:
(tensor([ 0.0000e+00, -2.9802e-08,  1.1921e-07]),
 tensor([1.0000, 1.0000, 1.0000]))

可学习参数为4

In [9]: module = torch.nn.LayerNorm(n_features, elementwise_affine=True)

In [10]: sum(p.numel() for p in module.parameters() if p.requires_grad)
Out[10]: 4

In [11]: (module.bias,module.weight)
Out[11]:
(Parameter containing:
 tensor([0., 0.], requires_grad=True),
 Parameter containing:
 tensor([1., 1.], requires_grad=True))

In [12]: module(inp).mean(-1),module(inp).std(-1,unbiased=False)
Out[12]:
(tensor([ 0.0000e+00, -2.9802e-08,  1.1921e-07], grad_fn=<MeanBackward1>),
 tensor([1.0000, 1.0000, 1.0000], grad_fn=<StdBackward1>))

In [13]: module.bias.data += 1

In [14]: module.weight.data *= 4

In [15]: module(inp).mean(-1),module(inp).std(-1,unbiased=False)
Out[15]:
(tensor([1.0000, 1.0000, 1.0000], grad_fn=<MeanBackward1>),
 tensor([4.0000, 4.0000, 4.0000], grad_fn=<StdBackward1>))

只更新n_features,样本间独立,与n_samples无关

In [16]: module(torch.rand(n_samples,2,3,4,5,6,n_features)).shape
Out[16]: torch.Size([3, 2, 3, 4, 5, 6, 2])

In [17]: module(torch.rand(n_samples,2,3,4,5,6,n_features)).mean(-1)
Out[17]:
tensor([[[[[[1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000]],

            [[1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000],
            [1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000]]]]]],
       grad_fn=<MeanBackward1>)

In [18]: module(torch.rand(n_samples,2,3,4,5,6,n_features)).std(-1,unbiased=False)
Out[18]:
tensor([[[[[[3.9998, 3.9962, 3.9993, 3.9966, 3.9657, 3.9954],
            [3.9998, 3.9997, 3.9996, 3.9981, 3.9981, 3.9983],
            [3.9799, 3.9996, 3.9657, 3.9998, 3.9998, 3.9986],
            [3.9990, 3.9950, 3.9885, 3.9996, 3.9582, 3.9996],
            [3.9987, 3.9989, 3.9900, 3.9992, 3.9992, 3.9994]],

           [[3.9996, 3.9996, 3.9972, 3.9931, 3.9998, 3.5468],
            [3.9998, 3.9808, 3.9974, 3.9985, 3.9992, 3.9986],
            [1.1207, 3.9993, 3.9998, 3.6870, 3.9997, 3.9981],
            [3.9998, 3.9998, 3.9986, 3.9676, 3.9999, 3.9998],
            [3.9993, 3.9999, 3.9998, 3.9852, 3.9993, 3.9891]]]]]],
       grad_fn=<StdBackward1>)

### Transformer Layer 结构与实现细节 #### 次结构概述 Transformer 架构由多个相同的堆叠而成,每一都包含了两个子:一个多头自注意力机制(Multi-Head Attention)子和一个全连接前馈网络(Feedforward Network)。这些子之间还加入了残差连接(Residual Connection),并应用了归一化(Normalization)来稳定训练过程[^1]。 #### 子详解 ##### 自注意力机制 (Self-Attention) 自注意力允许模型关注输入序列的不同位置,从而捕捉到更丰富的上下文信息。在多头版本中,查询、键和值被线性映射成不同表示空间下的向量集合,再分别计算各自的关注度分布,最后汇总得到加权求和的结果作为输出。 ```python import torch.nn as nn class MultiHeadedAttention(nn.Module): def __init__(self, h, d_model, dropout=0.1): super().__init__() assert d_model % h == 0 self.d_k = d_model // h self.h = h self.linears = clones(nn.Linear(d_model, d_model), 4) self.attn = None self.dropout = nn.Dropout(p=dropout) def forward(self, query, key, value, mask=None): ... ``` ##### 前馈神经网络 (Feedforward Network) 每个位置的数据都会经过两线性的转换操作,并且中间夹杂着ReLU激活函数。值得注意的是,在整个transformer架构里,这个部分对于所有的token都是共享参数的。 ```python class PositionwiseFeedForward(nn.Module): "Implements FFN equation." def __init__(self, d_model, d_ff, dropout=0.1): super(PositionwiseFeedForward, self).__init__() self.w_1 = nn.Linear(d_model, d_ff) self.w_2 = nn.Linear(d_ff, d_model) self.dropout = nn.Dropout(dropout) def forward(self, x): return self.w_2(self.dropout(F.relu(self.w_1(x)))) ``` ##### 残差连接与规范化处理 为了缓解深网络带来的梯度消失问题以及加速收敛速度,在每一个子之后添加了一个跳跃链接加上批量标准化的操作。这不仅有助于保持信息流动顺畅,而且能够提高泛化能力。 ```python from typing import TypeVar, Callable TensorType = TypeVar('torch.Tensor') def residual_connection(sublayer: Callable[[TensorType], TensorType], input_tensor: TensorType, norm_layer: nn.LayerNorm) -> TensorType: """Apply a sub-layer with residual connection.""" output = sublayer(input_tensor) normalized_output = norm_layer(output + input_tensor) return normalized_output ``` #### 实现注意事项 当实际构建Transformer时,除了上述核心组件外还需要考虑其他因素比如位置编码(position encoding),它用来给定固定长度的位置嵌入;masking技术用于屏蔽掉不必要的padding token或者未来时间步的信息等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非零因子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值