终于把 Transformer 中的注意力机制搞懂了!!!

人工智能
想象一下,当你读到 “The cat sat on the mat” 这句话时,人类可以立即理解单词之间的关系,可以知道 “sat” 与 “cat” 的关系比与“mat”的关系更密切。

大家好,我是小寒

注意力机制是深度学习领域中广泛应用的技术,特别是在自然语言处理和计算机视觉任务中。它使模型能够有选择地关注输入数据的特定部分,以此提升模型的性能。

想象一下,当你读到 “The cat sat on the mat” 这句话时,人类可以立即理解单词之间的关系,可以知道 “sat” 与 “cat” 的关系比与“mat”的关系更密切。

注意力机制使机器能够捕捉类似的关系,帮助它们专注于输入数据的特定部分。

图片

Transformer 中的注意力机制

在 Transformer 模型中,注意力机制是其核心组件,它使得模型可以在处理输入序列的过程中关注到最重要的信息,从而大幅提高了模型在长序列中的表现。

图片

自注意力机制

在自注意力机制中,每个输入向量可以“关注”同一序列中的其他向量,这使得模型能够灵活地关注整个序列的不同部分。

图片图片

下面,我们一起来看一下如何使用代码来实现上述过程。

import numpy as np

word_embeddings = {
    'she':    np.array([0.2, 0.9, 0.1, 0.5]),
    'likes':  np.array([0.8, 0.3, 0.7, 0.2]),
    'coffee': np.array([0.4, 0.6, 0.3, 0.9])
}

X = np.vstack([word_embeddings['she'], 
               word_embeddings['likes'], 
               word_embeddings['coffee']])
               
W_q = np.array([[0.9, 0.1, 0.1, 0.1],
                [0.1, 0.9, 0.1, 0.1],
                [0.1, 0.1, 0.9, 0.1],
                [0.1, 0.1, 0.1, 0.9]])

W_k = np.array([[0.9, 0.1, 0.1, 0.1],
                [0.1, 0.9, 0.1, 0.1],
                [0.1, 0.1, 0.9, 0.1],
                [0.1, 0.1, 0.1, 0.9]])
W_v = np.array([[0.8, 0.2, 0.1, 0.1],
                [0.2, 0.8, 0.2, 0.1],
                [0.1, 0.2, 0.8, 0.1],
                [0.1, 0.1, 0.1, 0.9]])
                
Q = np.dot(X, W_q)
K = np.dot(X, W_k)
V = np.dot(X, W_v)

scores = np.dot(Q, K.T)

d_k = K.shape[1]
scaled_scores = scores / np.sqrt(d_k)

exp_scores = np.exp(scaled_scores)
attention_weights = exp_scores / exp_scores.sum(axis=1, keepdims=True)

output = np.dot(attention_weights, V)

print(output)

多头注意力机制(Multi-Head Attention)

多头注意力机制进一步扩展了自注意力的表达能力。

通过设置多个注意力头(head),每个头从不同的子空间中获取信息,最后将各头的结果拼接起来并进行线性变换。

这样模型可以更好地捕捉多维度的依赖关系,使其在复杂任务中表现更为优异。

图片图片

多头注意力的计算流程

多头注意力机制增加了模型的灵活性,能让模型从不同角度学习到序列中词汇间的关系。

class MultiHeadAttention(nn.Module):    
    
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0 
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
    
    # 缩放点积注意力机制
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
责任编辑:武晓燕 来源: 程序员学长
相关推荐

2024-10-16 07:58:48

2024-08-01 08:41:08

2024-12-03 08:16:57

2024-07-17 09:32:19

2024-09-23 09:12:20

2024-10-08 15:09:17

2024-10-28 00:00:10

机器学习模型程度

2024-10-28 15:52:38

机器学习特征工程数据集

2024-10-08 10:16:22

2024-10-30 08:23:07

2024-11-05 12:56:06

机器学习函数MSE

2024-09-18 16:42:58

机器学习评估指标模型

2024-08-23 09:06:35

机器学习混淆矩阵预测

2024-10-14 14:02:17

机器学习评估指标人工智能

2024-07-24 08:04:24

神经网络激活函数

2024-11-07 08:26:31

神经网络激活函数信号

2024-11-21 10:07:40

2024-12-02 13:28:44

2024-12-02 01:10:04

神经网络自然语言DNN

2024-09-12 08:28:32

点赞
收藏

51CTO技术栈公众号