= dropout_mask(torch.randn(3,4), [4,3], 0.25)
t 4,3])
test_eq(t.shape, [assert ((t == 4/3) + (t==0)).all()
AWD-LSTM
AWD LSTM 来自 Smerity 等人
基础 NLP 模块
在 PyTorch 或 fastai 的 layers
之上,语言模型使用一些 NLP 特有的自定义层。
dropout_mask
dropout_mask (x:torch.Tensor, sz:list, p:float)
返回与 x
类型相同、大小为 sz
的 dropout mask,其中元素以概率 p
被取消。
类型 | 详情 | |
---|---|---|
x | Tensor | 源 Tensor,输出将与 x 类型相同 |
sz | list | dropout mask 的大小,以 int 列表表示 |
p | float | Dropout 概率 |
返回值 | Tensor | 乘法 dropout mask |
RNNDropout
RNNDropout (p:float=0.5)
在 seq_len 维度上具有一致性的 dropout,概率为 p
。
= RNNDropout(0.3)
dp = torch.randn(4,3,7)
tst_inp = dp(tst_inp)
tst_out for i in range(4):
for j in range(7):
if tst_out[i,0,j] == 0: assert (tst_out[i,:,j] == 0).all()
else: test_close(tst_out[i,:,j], tst_inp[i,:,j]/(1-0.3))
它还支持在图像序列上进行 dropout,其中时间维度是第一个轴,例如 10 张 3 通道、32x32 的图像。
= dp(torch.rand(4,10,3,32,32)) _
WeightDropout
WeightDropout (module:nn.Module, weight_p:float, layer_names:str|MutableSequence='weight_hh_l0')
一个模块,用于包裹另一层,训练期间该层的一些权重将被替换为 0。
类型 | 默认值 | 详情 | |
---|---|---|---|
module | Module | 包裹的模块 | |
weight_p | float | Weight dropout 概率 | |
layer_names | str | collections.abc.MutableSequence | weight_hh_l0 | 应用 dropout 的参数名称 |
= nn.LSTM(5,7)
module = WeightDropout(module, 0.4)
dp_module = dp_module.module.weight_hh_l0
wgts = torch.randn(10,20,5)
tst_inp = torch.zeros(1,20,7), torch.zeros(1,20,7)
h
dp_module.reset()= dp_module(tst_inp,h)
x,h = x.sum()
loss
loss.backward()= getattr(dp_module.module, 'weight_hh_l0')
new_wgts getattr(dp_module, 'weight_hh_l0_raw'))
test_eq(wgts, assert 0.2 <= (new_wgts==0).sum().float()/new_wgts.numel() <= 0.6
assert dp_module.weight_hh_l0_raw.requires_grad
assert dp_module.weight_hh_l0_raw.grad is not None
assert ((dp_module.weight_hh_l0_raw.grad == 0.) & (new_wgts == 0.)).any()
EmbeddingDropout
EmbeddingDropout (emb:nn.Embedding, embed_p:float)
对嵌入层 emb
应用 dropout,概率为 embed_p
。
类型 | 详情 | |
---|---|---|
emb | Embedding | 包裹的嵌入层 |
embed_p | float | 嵌入层 dropout 概率 |
= nn.Embedding(10, 7, padding_idx=1)
enc = EmbeddingDropout(enc, 0.5)
enc_dp = torch.randint(0,10,(8,))
tst_inp = enc_dp(tst_inp)
tst_out for i in range(8):
assert (tst_out[i]==0).all() or torch.allclose(tst_out[i], 2*enc.weight[tst_inp[i]])
AWD_LSTM
AWD_LSTM (vocab_sz:int, emb_sz:int, n_hid:int, n_layers:int, pad_token:int=1, hidden_p:float=0.2, input_p:float=0.6, embed_p:float=0.1, weight_p:float=0.5, bidir:bool=False)
受 https://arxiv.org/abs/1708.02182 启发的 AWD-LSTM
类型 | 默认值 | 详情 | |
---|---|---|---|
vocab_sz | int | 词汇表大小 | |
emb_sz | int | 嵌入向量大小 | |
n_hid | int | 隐藏状态中的特征数量 | |
n_layers | int | LSTM 层数量 | |
pad_token | int | 1 | Padding 标记 ID |
hidden_p | float | 0.2 | 层间隐藏状态的 dropout 概率 |
input_p | float | 0.6 | LSTM 堆栈输入的 dropout 概率 |
embed_p | float | 0.1 | 嵌入层 dropout 概率 |
weight_p | float | 0.5 | LSTM 层的隐藏层间权重 dropout 概率 |
bidir | bool | False | 如果设置为 True ,则使用双向 LSTM 层 |
这是 AWD-LSTM 模型的核心,使用来自 vocab_sz
和 emb_sz
的嵌入层,以及可能堆叠的 n_layers
个 bidir
LSTM 层。第一个 LSTM 层从 emb_sz
到 n_hid
,最后一个从 n_hid
到 emb_sz
,所有中间层都从 n_hid
到 n_hid
。pad_token
被传递给 PyTorch 嵌入层。dropout 的应用方式如下:
- 嵌入层被包裹在概率为
embed_p
的EmbeddingDropout
中; - 嵌入层的结果经过概率为
input_p
的RNNDropout
; - 每个 LSTM 应用概率为
weight_p
的WeightDropout
; - 在两个内部 LSTM 层之间,应用概率为
hidden_p
的RNNDropout
。
该模块返回两个列表:每个内部 LSTM 层的原始输出(未应用 hidden_p
的 dropout)和应用了 dropout 的输出列表。由于最后一个输出未应用 dropout,因此这两个列表的最后一个元素相同,该元素应馈送给解码器(在语言模型的情况下)。
= AWD_LSTM(100, 20, 10, 2, hidden_p=0.2, embed_p=0.02, input_p=0.1, weight_p=0.2)
tst = torch.randint(0, 100, (10,5))
x = tst(x)
r 10)
test_eq(tst.bs, len(tst.hidden), 2)
test_eq(for h_ in tst.hidden[0]], [[1,10,10], [1,10,10]])
test_eq([h_.shape for h_ in tst.hidden[1]], [[1,10,20], [1,10,20]])
test_eq([h_.shape
10,5,20])
test_eq(r.shape, [-1], tst.hidden[-1][0][0]) #hidden state is the last timestep in raw outputs
test_eq(r[:,
eval()
tst.
tst.reset();
tst(x); tst(x)
awd_lstm_lm_split
awd_lstm_lm_split (model)
将 RNN model
分组以应用差异学习率。
awd_lstm_clas_split
awd_lstm_clas_split (model)
将 RNN model
分组以应用差异学习率。