Spaces:
Build error
Build error
| # Copyright (c) Microsoft Corporation. | |
| # Licensed under the MIT License. | |
| import math | |
| import torch | |
| from torch import nn | |
| from torch.nn import Parameter | |
| import torch.onnx.operators | |
| from collections import defaultdict | |
| import torch.nn.functional as F | |
| def make_positions(tensor, padding_idx): | |
| """Replace non-padding symbols with their position numbers. | |
| Position numbers begin at padding_idx+1. Padding symbols are ignored. | |
| """ | |
| # The series of casts and type-conversions here are carefully | |
| # balanced to both work with ONNX export and XLA. In particular XLA | |
| # prefers ints, cumsum defaults to output longs, and ONNX doesn't know | |
| # how to handle the dtype kwarg in cumsum. | |
| mask = tensor.ne(padding_idx).int() | |
| return ( | |
| torch.cumsum(mask, dim=1).type_as(mask) * mask | |
| ).long() + padding_idx | |
| def softmax(x, dim): | |
| return F.softmax(x, dim=dim, dtype=torch.float32) | |
| class SelfAttention(nn.Module): | |
| def __init__(self, hid_dim, n_heads, dropout=0.1, gaussian_bias=False, gaussian_tao=None, | |
| gaus_init_l=3000): | |
| super().__init__() | |
| self.hid_dim = hid_dim | |
| self.n_heads = n_heads | |
| assert hid_dim % n_heads == 0 | |
| self.w_q = Linear(hid_dim, hid_dim) | |
| self.w_k = Linear(hid_dim, hid_dim) | |
| self.w_v = Linear(hid_dim, hid_dim) | |
| self.gaussian_bias = gaussian_bias | |
| if gaussian_bias: | |
| self.tao = nn.Parameter(torch.FloatTensor(n_heads)) | |
| nn.init.constant_(self.tao, gaussian_tao) # sigma = tao^2 | |
| # pre construct a gaussian matrix without dividing sigma^2 | |
| self.bias_matrix = torch.Tensor([[-abs(i - j) ** 2 / 2. | |
| for i in range(gaus_init_l)] for j in range(gaus_init_l)]) | |
| self.fc = Linear(hid_dim, hid_dim) | |
| self.dropout = nn.Dropout(dropout) | |
| self.sqrt_d = (hid_dim // n_heads) ** -0.5 | |
| def forward(self, query, key, value, mask=None, require_w=False): | |
| # Q,K,V计算与变形: input is L B C | |
| for m in [query, key, value]: | |
| m.transpose_(0, 1) # convert to B L C | |
| bsz, length, emb_dim = query.shape | |
| Q = self.w_q(query) # B, L, hid_emb | |
| K = self.w_k(key) | |
| V = self.w_v(value) | |
| # -1 means the dim should be inferred | |
| # B, L, n, C//n,把embedding分成n份, n为num_head | |
| Q = Q.view(bsz, -1, self.n_heads, self.hid_dim // self.n_heads) | |
| Q = Q.permute(0, 2, 1, 3) # B, n, L, C//n | |
| K = K.view(bsz, -1, self.n_heads, self.hid_dim // self.n_heads).permute(0, 2, 1, 3) | |
| V = V.view(bsz, -1, self.n_heads, self.hid_dim // self.n_heads).permute(0, 2, 1, 3) | |
| QK = torch.matmul(Q, K.transpose(2, 3)) * self.sqrt_d # Transpose last two dim, out = B, n, L, L | |
| if self.gaussian_bias: | |
| # gaussian distribution: L*L | |
| L = QK.size(-1) | |
| # get matrix of -(i-j)^2 / 2: i, j \in [0, L-1] | |
| if L <= self.bias_matrix.size(0): | |
| gaussian_mask = self.bias_matrix[:L, :L].repeat(self.n_heads, 1, 1).to(QK.device) # n. L. L. | |
| else: # 样本太长, 预构建的数值矩阵不够大 | |
| gaussian_mask = torch.tensor([[-abs(i - j) ** 2 / 2. | |
| for i in range(L)] for j in range(L)] | |
| ).repeat(self.n_heads, 1, 1).to(QK.device) | |
| print("Tensor is too long, size:", L) | |
| # divide gaussian matrix by tao^4 (multiply by tao^(-4)) | |
| # tao: nn.Parameters, size [n_head] | |
| gaussian_mask = torch.mul(gaussian_mask, torch.pow(self.tao, -4)[:, None, None]) # out shape n,L,L | |
| QK += gaussian_mask.repeat(bsz, 1, 1, 1).to(QK.device) # expand mask n,L,L to B, n, L, L | |
| if mask is not None: | |
| ''' | |
| attn weight size: b*n_h, L, L | |
| mask size: b, L -> b, 1, 1, L + | |
| attn_weight(b,n_head,L,L).masked_fill(mask) | |
| ''' | |
| QK = QK.masked_fill(mask[:, None, None, :], float('-inf')) | |
| # 然后对Q,K相乘的结果 计算softmax 计算weight | |
| attn_weight = torch.softmax(QK, dim=-1) | |
| attention = self.dropout(attn_weight) | |
| # 第三步,attention结果与V相乘 | |
| x = torch.matmul(attention, V) # B, n, L, C//n | |
| # 最后将多头排列好,就是multi-head attention的结果了 | |
| x = x.permute(0, 2, 1, 3).contiguous() # B, L, n, C//n | |
| x = x.view(bsz, -1, self.n_heads * (self.hid_dim // self.n_heads)) # B, L, C | |
| x = self.fc(x) | |
| x.transpose_(0, 1) # return L B C | |
| # return to operations.py: EncGausSALayer.forward() | |
| return (x, attn_weight[:1, :1, ...]) if require_w else (x, None) # remember to add bracket | |
| class EncGausSALayer(nn.Module): | |
| def __init__(self, hid_dim, num_heads, dropout, attention_dropout=0.1, relu_dropout=0.1, gaus_bias=False, | |
| gaus_tao=10): | |
| super().__init__() | |
| self.dropout = dropout | |
| self.layer_norm1 = LayerNorm(hid_dim) | |
| # hid_dim, n_heads, dropout=0.1, gaussian_bias=False, gaussian_tao=None | |
| self.self_attn_gaus_bias = SelfAttention(hid_dim, num_heads, attention_dropout, gaus_bias, gaus_tao) | |
| self.layer_norm2 = LayerNorm(hid_dim) | |
| self.ffn = TransformerFFNLayer(hid_dim, 4 * hid_dim, kernel_size=9, dropout=relu_dropout) | |
| def forward(self, x, encoder_padding_mask=None, require_w=False, **kwargs): | |
| layer_norm_training = kwargs.get('layer_norm_training', None) | |
| # print("EncGausSA, kwargs", str(kwargs)) | |
| # require_w = kwargs.get('require_w', False) | |
| # print("EncGausSA, require_w", require_w) | |
| if layer_norm_training is not None: | |
| self.layer_norm1.training = layer_norm_training | |
| self.layer_norm2.training = layer_norm_training | |
| residual = x | |
| x = self.layer_norm1(x) | |
| # x = self.self_attn_gaus_bias(query=x, key=x, value=x, mask=encoder_padding_mask) | |
| x, attn_w = self.self_attn_gaus_bias(query=x, key=x, value=x, mask=encoder_padding_mask, require_w=require_w) | |
| # print("self_attn return:", type(x)) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| residual = x | |
| x = self.layer_norm2(x) | |
| x = self.ffn(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| return (x, attn_w) if require_w else x | |
| class CyclicalPositionEmb(nn.Module): | |
| def __init__(self, K, emb_size): | |
| super(CyclicalPositionEmb, self).__init__() | |
| self.fc = Linear(K, emb_size) | |
| def forward(self, x): | |
| ''' | |
| :param x: B * T * 1 | |
| :return: x | |
| ''' | |
| pass # todo | |
| INCREMENTAL_STATE_INSTANCE_ID = defaultdict(lambda: 0) | |
| def _get_full_incremental_state_key(module_instance, key): | |
| module_name = module_instance.__class__.__name__ | |
| # assign a unique ID to each module instance, so that incremental state is | |
| # not shared across module instances | |
| if not hasattr(module_instance, '_instance_id'): | |
| INCREMENTAL_STATE_INSTANCE_ID[module_name] += 1 | |
| module_instance._instance_id = INCREMENTAL_STATE_INSTANCE_ID[module_name] | |
| return '{}.{}.{}'.format(module_name, module_instance._instance_id, key) | |
| def get_incremental_state(module, incremental_state, key): | |
| """Helper for getting incremental state for an nn.Module.""" | |
| full_key = _get_full_incremental_state_key(module, key) | |
| if incremental_state is None or full_key not in incremental_state: | |
| return None | |
| return incremental_state[full_key] | |
| def set_incremental_state(module, incremental_state, key, value): | |
| """Helper for setting incremental state for an nn.Module.""" | |
| if incremental_state is not None: | |
| full_key = _get_full_incremental_state_key(module, key) | |
| incremental_state[full_key] = value | |
| def LayerNorm(normalized_shape, eps=1e-5, elementwise_affine=True, export=False): | |
| return torch.nn.LayerNorm(normalized_shape, eps, elementwise_affine) | |
| def Linear(in_features, out_features, bias=True): | |
| m = nn.Linear(in_features, out_features, bias) | |
| nn.init.xavier_uniform_(m.weight) | |
| if bias: | |
| nn.init.constant_(m.bias, 0.) | |
| return m | |
| class SinusoidalPositionalEmbedding(nn.Module): | |
| """This module produces sinusoidal positional embeddings of any length. | |
| Padding symbols are ignored. | |
| """ | |
| def __init__(self, embedding_dim, padding_idx, init_size=1024): | |
| super().__init__() | |
| self.embedding_dim = embedding_dim | |
| self.padding_idx = padding_idx | |
| self.weights = SinusoidalPositionalEmbedding.get_embedding( | |
| init_size, | |
| embedding_dim, | |
| padding_idx, | |
| ) | |
| self.register_buffer('_float_tensor', torch.FloatTensor(1)) | |
| def get_embedding(num_embeddings, embedding_dim, padding_idx=None): | |
| """Build sinusoidal embeddings. | |
| This matches the implementation in tensor2tensor, but differs slightly | |
| from the description in Section 3.5 of "Attention Is All You Need". | |
| """ | |
| half_dim = embedding_dim // 2 | |
| emb = math.log(10000) / (half_dim - 1) | |
| emb = torch.exp(torch.arange(half_dim, dtype=torch.float) * -emb) | |
| emb = torch.arange(num_embeddings, dtype=torch.float).unsqueeze(1) * emb.unsqueeze(0) | |
| emb = torch.cat([torch.sin(emb), torch.cos(emb)], dim=1).view(num_embeddings, -1) | |
| if embedding_dim % 2 == 1: | |
| # zero pad | |
| emb = torch.cat([emb, torch.zeros(num_embeddings, 1)], dim=1) | |
| if padding_idx is not None: | |
| emb[padding_idx, :] = 0 | |
| return emb | |
| def forward(self, input, incremental_state=None, timestep=None, **kwargs): | |
| """Input is expected to be of size [bsz x seqlen].""" | |
| bsz, seq_len = input.shape[:2] | |
| max_pos = self.padding_idx + 1 + seq_len | |
| if self.weights is None or max_pos > self.weights.size(0): | |
| # recompute/expand embeddings if needed | |
| self.weights = SinusoidalPositionalEmbedding.get_embedding( | |
| max_pos, | |
| self.embedding_dim, | |
| self.padding_idx, | |
| ) | |
| self.weights = self.weights.to(self._float_tensor) | |
| if incremental_state is not None: | |
| # positions is the same for every token when decoding a single step | |
| pos = timestep.view(-1)[0] + 1 if timestep is not None else seq_len | |
| return self.weights[self.padding_idx + pos, :].expand(bsz, 1, -1) | |
| positions = make_positions(input, self.padding_idx) | |
| return self.weights.index_select(0, positions.view(-1)).view(bsz, seq_len, -1).detach() | |
| def max_positions(self): | |
| """Maximum number of supported positions.""" | |
| return int(1e5) # an arbitrary large number | |
| class ConvTBC(nn.Module): | |
| def __init__(self, in_channels, out_channels, kernel_size, padding=0): | |
| super(ConvTBC, self).__init__() | |
| self.in_channels = in_channels | |
| self.out_channels = out_channels | |
| self.kernel_size = kernel_size | |
| self.padding = padding | |
| self.weight = torch.nn.Parameter(torch.Tensor( | |
| self.kernel_size, in_channels, out_channels)) | |
| self.bias = torch.nn.Parameter(torch.Tensor(out_channels)) | |
| def forward(self, input): | |
| return torch.conv_tbc(input.contiguous(), self.weight, self.bias, self.padding) | |
| class EncConvLayer(nn.Module): | |
| def __init__(self, c, kernel_size, dropout): | |
| super().__init__() | |
| self.layer_norm = LayerNorm(c) | |
| conv = ConvTBC(c, c, kernel_size, padding=kernel_size // 2) | |
| std = math.sqrt((4 * (1.0 - dropout)) / (kernel_size * c)) | |
| nn.init.normal_(conv.weight, mean=0, std=std) | |
| nn.init.constant_(conv.bias, 0) | |
| self.conv = nn.utils.weight_norm(conv, dim=2) | |
| self.dropout = dropout | |
| def forward(self, x, encoder_padding_mask=None, **kwargs): | |
| layer_norm_training = kwargs.get('layer_norm_training', None) | |
| if layer_norm_training is not None: | |
| self.layer_norm.training = layer_norm_training | |
| residual = x | |
| if encoder_padding_mask is not None: | |
| x = x.masked_fill(encoder_padding_mask.t().unsqueeze(-1), 0) | |
| x = self.layer_norm(x) | |
| x = self.conv(x) | |
| x = F.relu(x) | |
| x = F.dropout(x, self.dropout, self.training) | |
| x = x + residual | |
| return x | |
| class MultiheadAttention(nn.Module): | |
| def __init__(self, embed_dim, num_heads, kdim=None, vdim=None, dropout=0., bias=True, | |
| add_bias_kv=False, add_zero_attn=False, self_attention=False, | |
| encoder_decoder_attention=False): | |
| super().__init__() | |
| self.embed_dim = embed_dim | |
| self.kdim = kdim if kdim is not None else embed_dim | |
| self.vdim = vdim if vdim is not None else embed_dim | |
| self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim | |
| self.num_heads = num_heads | |
| self.dropout = dropout | |
| self.head_dim = embed_dim // num_heads | |
| assert self.head_dim * num_heads == self.embed_dim, "embed_dim must be divisible by num_heads" | |
| self.scaling = self.head_dim ** -0.5 | |
| self.self_attention = self_attention | |
| self.encoder_decoder_attention = encoder_decoder_attention | |
| assert not self.self_attention or self.qkv_same_dim, 'Self-attention requires query, key and ' \ | |
| 'value to be of the same size' | |
| if self.qkv_same_dim: | |
| self.in_proj_weight = Parameter(torch.Tensor(3 * embed_dim, embed_dim)) | |
| else: | |
| self.k_proj_weight = Parameter(torch.Tensor(embed_dim, self.kdim)) | |
| self.v_proj_weight = Parameter(torch.Tensor(embed_dim, self.vdim)) | |
| self.q_proj_weight = Parameter(torch.Tensor(embed_dim, embed_dim)) | |
| if bias: | |
| self.in_proj_bias = Parameter(torch.Tensor(3 * embed_dim)) | |
| else: | |
| self.register_parameter('in_proj_bias', None) | |
| self.out_proj = nn.Linear(embed_dim, embed_dim, bias=bias) | |
| if add_bias_kv: | |
| self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim)) | |
| self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim)) | |
| else: | |
| self.bias_k = self.bias_v = None | |
| self.add_zero_attn = add_zero_attn | |
| self.reset_parameters() | |
| self.enable_torch_version = False | |
| if hasattr(F, "multi_head_attention_forward"): | |
| self.enable_torch_version = True | |
| else: | |
| self.enable_torch_version = False | |
| def reset_parameters(self): | |
| if self.qkv_same_dim: | |
| nn.init.xavier_uniform_(self.in_proj_weight) | |
| else: | |
| nn.init.xavier_uniform_(self.k_proj_weight) | |
| nn.init.xavier_uniform_(self.v_proj_weight) | |
| nn.init.xavier_uniform_(self.q_proj_weight) | |
| nn.init.xavier_uniform_(self.out_proj.weight) | |
| if self.in_proj_bias is not None: | |
| nn.init.constant_(self.in_proj_bias, 0.) | |
| nn.init.constant_(self.out_proj.bias, 0.) | |
| if self.bias_k is not None: | |
| nn.init.xavier_normal_(self.bias_k) | |
| if self.bias_v is not None: | |
| nn.init.xavier_normal_(self.bias_v) | |
| def forward( | |
| self, | |
| query, key, value, | |
| key_padding_mask=None, | |
| incremental_state=None, | |
| need_weights=True, | |
| static_kv=False, | |
| attn_mask=None, | |
| before_softmax=False, | |
| need_head_weights=False, | |
| enc_dec_attn_constraint_mask=None | |
| ): | |
| """Input shape: Time x Batch x Channel | |
| Args: | |
| key_padding_mask (ByteTensor, optional): mask to exclude | |
| keys that are pads, of shape `(batch, src_len)`, where | |
| padding elements are indicated by 1s. | |
| need_weights (bool, optional): return the attention weights, | |
| averaged over heads (default: False). | |
| attn_mask (ByteTensor, optional): typically used to | |
| implement causal attention, where the mask prevents the | |
| attention from looking forward in time (default: None). | |
| before_softmax (bool, optional): return the raw attention | |
| weights and values before the attention softmax. | |
| need_head_weights (bool, optional): return the attention | |
| weights for each head. Implies *need_weights*. Default: | |
| return the average attention weights over all heads. | |
| """ | |
| if need_head_weights: | |
| need_weights = True | |
| tgt_len, bsz, embed_dim = query.size() | |
| assert embed_dim == self.embed_dim | |
| assert list(query.size()) == [tgt_len, bsz, embed_dim] | |
| if self.enable_torch_version and incremental_state is None and not static_kv: | |
| if self.qkv_same_dim: | |
| return F.multi_head_attention_forward(query, key, value, | |
| self.embed_dim, self.num_heads, | |
| self.in_proj_weight, | |
| self.in_proj_bias, self.bias_k, self.bias_v, | |
| self.add_zero_attn, self.dropout, | |
| self.out_proj.weight, self.out_proj.bias, | |
| self.training, key_padding_mask, need_weights, | |
| attn_mask) | |
| else: | |
| return F.multi_head_attention_forward(query, key, value, | |
| self.embed_dim, self.num_heads, | |
| torch.empty([0]), | |
| self.in_proj_bias, self.bias_k, self.bias_v, | |
| self.add_zero_attn, self.dropout, | |
| self.out_proj.weight, self.out_proj.bias, | |
| self.training, key_padding_mask, need_weights, | |
| attn_mask, use_separate_proj_weight=True, | |
| q_proj_weight=self.q_proj_weight, | |
| k_proj_weight=self.k_proj_weight, | |
| v_proj_weight=self.v_proj_weight) | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_key' in saved_state: | |
| # previous time steps are cached - no need to recompute | |
| # key and value if they are static | |
| if static_kv: | |
| assert self.encoder_decoder_attention and not self.self_attention | |
| key = value = None | |
| else: | |
| saved_state = None | |
| if self.self_attention: | |
| # self-attention | |
| q, k, v = self.in_proj_qkv(query) | |
| elif self.encoder_decoder_attention: | |
| # encoder-decoder attention | |
| q = self.in_proj_q(query) | |
| if key is None: | |
| assert value is None | |
| k = v = None | |
| else: | |
| k = self.in_proj_k(key) | |
| v = self.in_proj_v(key) | |
| else: | |
| q = self.in_proj_q(query) | |
| k = self.in_proj_k(key) | |
| v = self.in_proj_v(value) | |
| q *= self.scaling | |
| if self.bias_k is not None: | |
| assert self.bias_v is not None | |
| k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)]) | |
| v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)]) | |
| if attn_mask is not None: | |
| attn_mask = torch.cat([attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1) | |
| if key_padding_mask is not None: | |
| key_padding_mask = torch.cat( | |
| [key_padding_mask, key_padding_mask.new_zeros(key_padding_mask.size(0), 1)], dim=1) | |
| q = q.contiguous().view(tgt_len, bsz * self.num_heads, self.head_dim).transpose(0, 1) | |
| if k is not None: | |
| k = k.contiguous().view(-1, bsz * self.num_heads, self.head_dim).transpose(0, 1) | |
| if v is not None: | |
| v = v.contiguous().view(-1, bsz * self.num_heads, self.head_dim).transpose(0, 1) | |
| if saved_state is not None: | |
| # saved states are stored with shape (bsz, num_heads, seq_len, head_dim) | |
| if 'prev_key' in saved_state: | |
| prev_key = saved_state['prev_key'].view(bsz * self.num_heads, -1, self.head_dim) | |
| if static_kv: | |
| k = prev_key | |
| else: | |
| k = torch.cat((prev_key, k), dim=1) | |
| if 'prev_value' in saved_state: | |
| prev_value = saved_state['prev_value'].view(bsz * self.num_heads, -1, self.head_dim) | |
| if static_kv: | |
| v = prev_value | |
| else: | |
| v = torch.cat((prev_value, v), dim=1) | |
| if 'prev_key_padding_mask' in saved_state and saved_state['prev_key_padding_mask'] is not None: | |
| prev_key_padding_mask = saved_state['prev_key_padding_mask'] | |
| if static_kv: | |
| key_padding_mask = prev_key_padding_mask | |
| else: | |
| key_padding_mask = torch.cat((prev_key_padding_mask, key_padding_mask), dim=1) | |
| saved_state['prev_key'] = k.view(bsz, self.num_heads, -1, self.head_dim) | |
| saved_state['prev_value'] = v.view(bsz, self.num_heads, -1, self.head_dim) | |
| saved_state['prev_key_padding_mask'] = key_padding_mask | |
| self._set_input_buffer(incremental_state, saved_state) | |
| src_len = k.size(1) | |
| # This is part of a workaround to get around fork/join parallelism | |
| # not supporting Optional types. | |
| if key_padding_mask is not None and key_padding_mask.shape == torch.Size([]): | |
| key_padding_mask = None | |
| if key_padding_mask is not None: | |
| assert key_padding_mask.size(0) == bsz | |
| assert key_padding_mask.size(1) == src_len | |
| if self.add_zero_attn: | |
| src_len += 1 | |
| k = torch.cat([k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1) | |
| v = torch.cat([v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1) | |
| if attn_mask is not None: | |
| attn_mask = torch.cat([attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1) | |
| if key_padding_mask is not None: | |
| key_padding_mask = torch.cat( | |
| [key_padding_mask, torch.zeros(key_padding_mask.size(0), 1).type_as(key_padding_mask)], dim=1) | |
| attn_weights = torch.bmm(q, k.transpose(1, 2)) | |
| attn_weights = self.apply_sparse_mask(attn_weights, tgt_len, src_len, bsz) | |
| assert list(attn_weights.size()) == [bsz * self.num_heads, tgt_len, src_len] | |
| if attn_mask is not None: | |
| attn_mask = attn_mask.unsqueeze(0) | |
| attn_weights += attn_mask | |
| if enc_dec_attn_constraint_mask is not None: # bs x head x L_kv | |
| attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) | |
| attn_weights = attn_weights.masked_fill( | |
| enc_dec_attn_constraint_mask.unsqueeze(2).bool(), | |
| float('-inf'), | |
| ) | |
| attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len) | |
| if key_padding_mask is not None: | |
| # don't attend to padding symbols | |
| attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) | |
| attn_weights = attn_weights.masked_fill( | |
| key_padding_mask.unsqueeze(1).unsqueeze(2), | |
| float('-inf'), | |
| ) | |
| attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len) | |
| attn_logits = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) | |
| if before_softmax: | |
| return attn_weights, v | |
| attn_weights_float = softmax(attn_weights, dim=-1) | |
| attn_weights = attn_weights_float.type_as(attn_weights) | |
| attn_probs = F.dropout(attn_weights_float.type_as(attn_weights), p=self.dropout, training=self.training) | |
| attn = torch.bmm(attn_probs, v) | |
| assert list(attn.size()) == [bsz * self.num_heads, tgt_len, self.head_dim] | |
| attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) | |
| attn = self.out_proj(attn) | |
| if need_weights: | |
| attn_weights = attn_weights_float.view(bsz, self.num_heads, tgt_len, src_len).transpose(1, 0) | |
| if not need_head_weights: | |
| # average attention weights over heads | |
| attn_weights = attn_weights.mean(dim=0) | |
| else: | |
| attn_weights = None | |
| return attn, (attn_weights, attn_logits) | |
| def in_proj_qkv(self, query): | |
| return self._in_proj(query).chunk(3, dim=-1) | |
| def in_proj_q(self, query): | |
| if self.qkv_same_dim: | |
| return self._in_proj(query, end=self.embed_dim) | |
| else: | |
| bias = self.in_proj_bias | |
| if bias is not None: | |
| bias = bias[:self.embed_dim] | |
| return F.linear(query, self.q_proj_weight, bias) | |
| def in_proj_k(self, key): | |
| if self.qkv_same_dim: | |
| return self._in_proj(key, start=self.embed_dim, end=2 * self.embed_dim) | |
| else: | |
| weight = self.k_proj_weight | |
| bias = self.in_proj_bias | |
| if bias is not None: | |
| bias = bias[self.embed_dim:2 * self.embed_dim] | |
| return F.linear(key, weight, bias) | |
| def in_proj_v(self, value): | |
| if self.qkv_same_dim: | |
| return self._in_proj(value, start=2 * self.embed_dim) | |
| else: | |
| weight = self.v_proj_weight | |
| bias = self.in_proj_bias | |
| if bias is not None: | |
| bias = bias[2 * self.embed_dim:] | |
| return F.linear(value, weight, bias) | |
| def _in_proj(self, input, start=0, end=None): | |
| weight = self.in_proj_weight | |
| bias = self.in_proj_bias | |
| weight = weight[start:end, :] | |
| if bias is not None: | |
| bias = bias[start:end] | |
| return F.linear(input, weight, bias) | |
| def _get_input_buffer(self, incremental_state): | |
| return get_incremental_state( | |
| self, | |
| incremental_state, | |
| 'attn_state', | |
| ) or {} | |
| def _set_input_buffer(self, incremental_state, buffer): | |
| set_incremental_state( | |
| self, | |
| incremental_state, | |
| 'attn_state', | |
| buffer, | |
| ) | |
| def apply_sparse_mask(self, attn_weights, tgt_len, src_len, bsz): | |
| return attn_weights | |
| def clear_buffer(self, incremental_state=None): | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_key' in saved_state: | |
| del saved_state['prev_key'] | |
| if 'prev_value' in saved_state: | |
| del saved_state['prev_value'] | |
| self._set_input_buffer(incremental_state, saved_state) | |
| class TransformerFFNLayer(nn.Module): | |
| def __init__(self, hidden_size, filter_size, padding="SAME", kernel_size=1, dropout=0.): | |
| super().__init__() | |
| self.kernel_size = kernel_size | |
| self.dropout = dropout | |
| if kernel_size == 1: | |
| self.ffn_1 = Linear(hidden_size, filter_size) | |
| else: | |
| if padding == 'SAME': | |
| assert kernel_size % 2 == 1 | |
| self.first_offset = -((kernel_size - 1) // 2) | |
| else: | |
| assert padding == 'LEFT' | |
| self.first_offset = -(kernel_size - 1) | |
| self.last_offset = self.first_offset + kernel_size - 1 | |
| self.ffn_1 = nn.ModuleList() | |
| for i in range(kernel_size): | |
| self.ffn_1.append(Linear(hidden_size, filter_size, bias=(i == 0))) | |
| self.ffn_2 = Linear(filter_size, hidden_size) | |
| def forward(self, x, incremental_state=None): | |
| # x: T x B x C | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_input' in saved_state: | |
| prev_input = saved_state['prev_input'] | |
| x = torch.cat((prev_input, x), dim=0) | |
| x = x[-self.kernel_size:] | |
| saved_state['prev_input'] = x | |
| self._set_input_buffer(incremental_state, saved_state) | |
| if self.kernel_size == 1: | |
| x = self.ffn_1(x) | |
| else: | |
| padded = F.pad(x, (0, 0, 0, 0, -self.first_offset, self.last_offset)) | |
| results = [] | |
| for i in range(self.kernel_size): | |
| shifted = padded[i:x.size(0) + i] if i else x | |
| results.append(self.ffn_1[i](shifted)) | |
| res = sum(results) | |
| x = res * self.kernel_size ** -0.5 | |
| if incremental_state is not None: | |
| x = x[-1:] | |
| x = F.relu(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = self.ffn_2(x) | |
| return x | |
| def _get_input_buffer(self, incremental_state): | |
| return get_incremental_state( | |
| self, | |
| incremental_state, | |
| 'f', | |
| ) or {} | |
| def _set_input_buffer(self, incremental_state, buffer): | |
| set_incremental_state( | |
| self, | |
| incremental_state, | |
| 'f', | |
| buffer, | |
| ) | |
| def clear_buffer(self, incremental_state): | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_input' in saved_state: | |
| del saved_state['prev_input'] | |
| self._set_input_buffer(incremental_state, saved_state) | |
| def fill_with_neg_inf(t): | |
| """FP16-compatible function that fills a tensor with -inf.""" | |
| return t.float().fill_(float('-inf')).type_as(t) | |
| def fill_with_neg_inf2(t): | |
| """FP16-compatible function that fills a tensor with -inf.""" | |
| return t.float().fill_(-1e9).type_as(t) | |
| class NewTransformerFFNLayer(nn.Module): | |
| def __init__(self, hidden_size, filter_size, padding="SAME", kernel_size=1, dropout=0.): | |
| super().__init__() | |
| self.kernel_size = kernel_size | |
| self.dropout = dropout | |
| if padding == 'SAME': | |
| self.ffn_1 = nn.Conv1d(hidden_size, filter_size, kernel_size, padding=kernel_size // 2) | |
| elif padding == 'LEFT': | |
| self.ffn_1 = nn.Sequential( | |
| nn.ConstantPad1d((kernel_size - 1, 0), 0.0), | |
| nn.Conv1d(hidden_size, filter_size, kernel_size) | |
| ) | |
| self.ffn_2 = Linear(filter_size, hidden_size) | |
| def forward(self, x, incremental_state=None): | |
| # x: T x B x C | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_input' in saved_state: | |
| prev_input = saved_state['prev_input'] | |
| x = torch.cat((prev_input, x), dim=0) | |
| x = x[-self.kernel_size:] | |
| saved_state['prev_input'] = x | |
| self._set_input_buffer(incremental_state, saved_state) | |
| x = self.ffn_1(x.permute(1, 2, 0)).permute(2, 0, 1) | |
| x = x * self.kernel_size ** -0.5 | |
| if incremental_state is not None: | |
| x = x[-1:] | |
| x = F.relu(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = self.ffn_2(x) | |
| return x | |
| def _get_input_buffer(self, incremental_state): | |
| return get_incremental_state( | |
| self, | |
| incremental_state, | |
| 'f', | |
| ) or {} | |
| def _set_input_buffer(self, incremental_state, buffer): | |
| set_incremental_state( | |
| self, | |
| incremental_state, | |
| 'f', | |
| buffer, | |
| ) | |
| def clear_buffer(self, incremental_state): | |
| if incremental_state is not None: | |
| saved_state = self._get_input_buffer(incremental_state) | |
| if 'prev_input' in saved_state: | |
| del saved_state['prev_input'] | |
| self._set_input_buffer(incremental_state, saved_state) | |
| class EncSALayer(nn.Module): | |
| def __init__(self, c, num_heads, dropout, attention_dropout=0.1, relu_dropout=0.1, | |
| kernel_size=9, padding='SAME'): | |
| super().__init__() | |
| self.c = c | |
| self.dropout = dropout | |
| self.layer_norm1 = LayerNorm(c) | |
| self.self_attn = MultiheadAttention( | |
| self.c, num_heads, self_attention=True, dropout=attention_dropout, bias=False, | |
| ) | |
| self.layer_norm2 = LayerNorm(c) | |
| self.ffn = TransformerFFNLayer(c, 4 * c, kernel_size=kernel_size, dropout=relu_dropout, padding=padding) | |
| def forward(self, x, encoder_padding_mask=None, **kwargs): | |
| layer_norm_training = kwargs.get('layer_norm_training', None) | |
| if layer_norm_training is not None: | |
| self.layer_norm1.training = layer_norm_training | |
| self.layer_norm2.training = layer_norm_training | |
| residual = x | |
| x = self.layer_norm1(x) | |
| x, _, = self.self_attn( | |
| query=x, | |
| key=x, | |
| value=x, | |
| key_padding_mask=encoder_padding_mask | |
| ) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| x = x * (1 - encoder_padding_mask.float()).transpose(0, 1)[..., None] | |
| residual = x | |
| x = self.layer_norm2(x) | |
| x = self.ffn(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| x = x * (1 - encoder_padding_mask.float()).transpose(0, 1)[..., None] | |
| return x | |
| class EncLocalSALayer(nn.Module): | |
| def __init__(self, c, num_heads, dropout, attention_dropout=0.1, relu_dropout=0.1): | |
| super().__init__() | |
| self.c = c | |
| self.dropout = dropout | |
| self.layer_norm1 = LayerNorm(c) | |
| self.self_attn = MultiheadAttention( | |
| self.c, num_heads, self_attention=True, dropout=attention_dropout, bias=False, | |
| ) | |
| self.layer_norm2 = LayerNorm(c) | |
| self.ffn = TransformerFFNLayer(c, 4 * c, kernel_size=9, dropout=relu_dropout) | |
| self.chunk_size = 101 | |
| def forward(self, x, encoder_padding_mask=None, **kwargs): | |
| layer_norm_training = kwargs.get('layer_norm_training', None) | |
| if layer_norm_training is not None: | |
| self.layer_norm1.training = layer_norm_training | |
| self.layer_norm2.training = layer_norm_training | |
| residual = x | |
| x = self.layer_norm1(x) | |
| states = [] | |
| T = x.shape[0] | |
| all_neg_inf = fill_with_neg_inf2(x.new(T, T)) | |
| half_chunk_size = self.chunk_size // 2 | |
| attn_mask = torch.triu(all_neg_inf, half_chunk_size + 1) \ | |
| + torch.tril(all_neg_inf, -half_chunk_size - 1) | |
| encoder_padding_mask = encoder_padding_mask.data | |
| for i in range(0, x.shape[0], half_chunk_size + 1): | |
| k_start = max(0, i - half_chunk_size) | |
| k_end = min(x.shape[0], i + self.chunk_size) | |
| kv = x[k_start:k_end] | |
| q = x[i:i + half_chunk_size + 1] | |
| q_nonpadding = (1 - encoder_padding_mask[:, i:i + half_chunk_size + 1].float()).data | |
| encoder_padding_mask_ = encoder_padding_mask[:, k_start:k_end].data | |
| encoder_padding_mask_[q_nonpadding.sum(-1) == 0, :] = 0 | |
| x_, _, = self.self_attn( | |
| query=q, | |
| key=kv, | |
| value=kv, | |
| key_padding_mask=encoder_padding_mask_, | |
| attn_mask=attn_mask[i:i + half_chunk_size + 1, k_start:k_end] | |
| ) | |
| x_ = x_ * (1 - q_nonpadding.T[:, :, None]) | |
| states.append(x_) | |
| x = torch.cat(states) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| residual = x | |
| x = self.layer_norm2(x) | |
| x = self.ffn(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| return x | |
| class EncLSTMLayer(nn.Module): | |
| def __init__(self, c, dropout): | |
| super().__init__() | |
| self.c = c | |
| self.layer_norm = LayerNorm(c) | |
| self.lstm = nn.LSTM(c, c, 1, bidirectional=True) | |
| self.out_proj = Linear(2 * c, c) | |
| self.dropout = dropout | |
| def forward(self, x, **kwargs): | |
| layer_norm_training = kwargs.get('layer_norm_training', None) | |
| if layer_norm_training is not None: | |
| self.layer_norm.training = layer_norm_training | |
| self.lstm.flatten_parameters() | |
| residual = x | |
| x = self.layer_norm(x) | |
| x, _ = self.lstm(x) | |
| x = self.out_proj(x) | |
| x = F.dropout(x, self.dropout, training=self.training) | |
| x = residual + x | |
| return x | |
| class ConvAttentionLayer(nn.Module): | |
| def __init__(self, c, hidden_size, dropout=0.): | |
| super().__init__() | |
| self.in_projection = Linear(c, hidden_size) | |
| self.out_projection = Linear(hidden_size, c) | |
| self.dropout = dropout | |
| def forward(self, x, key, value, encoder_padding_mask=None, enc_dec_attn_constraint_mask=None): | |
| # x, key, value : T x B x C | |
| # attention | |
| query = self.in_projection(x) | |
| attn_weights = torch.bmm(query.transpose(0, 1), key.transpose(0, 1).transpose(1, 2)) | |
| # don't attend over padding | |
| if encoder_padding_mask is not None: | |
| attn_weights = attn_weights.masked_fill( | |
| encoder_padding_mask.unsqueeze(1), | |
| float('-inf') | |
| ).type_as(attn_weights) # FP16 support: cast to float and back | |
| if enc_dec_attn_constraint_mask is not None: | |
| attn_weights = attn_weights.masked_fill( | |
| enc_dec_attn_constraint_mask.bool(), | |
| float('-inf'), | |
| ).type_as(attn_weights) | |
| attn_logits = attn_weights | |
| # softmax over last dim | |
| sz = attn_weights.size() | |
| attn_scores = F.softmax(attn_weights.view(sz[0] * sz[1], sz[2]), dim=1) | |
| attn_scores = attn_scores.view(sz) | |
| attn_scores = F.dropout(attn_scores, p=self.dropout, training=self.training) | |
| attn = torch.bmm(attn_scores, value.transpose(0, 1)).transpose(0, 1) | |
| # scale attention output (respecting potentially different lengths) | |
| s = value.size(0) | |
| if encoder_padding_mask is None: | |
| attn = attn * (s * math.sqrt(1.0 / s)) | |
| else: | |
| s = s - encoder_padding_mask.type_as(attn).sum(dim=1, keepdim=True) # exclude padding | |
| s = s.transpose(0, 1).unsqueeze(-1) | |
| attn = attn * (s * s.rsqrt()) | |
| # project back | |
| attn = self.out_projection(attn) | |
| return attn, attn_scores, attn_logits | |
| OPERATIONS_ENCODER = { # c = hidden size | |
| 1: lambda c, dropout: EncConvLayer(c, 1, dropout), # h, num_heads, dropout | |
| 2: lambda c, dropout: EncConvLayer(c, 5, dropout), | |
| 3: lambda c, dropout: EncConvLayer(c, 9, dropout), | |
| 4: lambda c, dropout: EncConvLayer(c, 13, dropout), | |
| 5: lambda c, dropout: EncConvLayer(c, 17, dropout), | |
| 6: lambda c, dropout: EncConvLayer(c, 21, dropout), | |
| 7: lambda c, dropout: EncConvLayer(c, 25, dropout), | |
| 8: lambda c, dropout: EncSALayer(c, 8, dropout=dropout, | |
| attention_dropout=0.0, relu_dropout=dropout, | |
| kernel_size=9, | |
| padding='SAME'), | |
| 9: lambda c, dropout: EncSALayer(c, 4, dropout), | |
| 10: lambda c, dropout: EncSALayer(c, 8, dropout), | |
| 11: lambda c, dropout: EncLocalSALayer(c, 2, dropout), | |
| 12: lambda c, dropout: EncLSTMLayer(c, dropout), | |
| 13: lambda c, dropout, g_bias, tao: EncGausSALayer(c, 1, dropout, gaus_bias=g_bias, gaus_tao=tao), | |
| 14: lambda c, dropout: EncSALayer(c, 2, dropout, kernel_size=1), | |
| 15: lambda c, dropout: EncSALayer(c, 2, dropout, kernel_size=15), | |
| } |