【minGPT】注意力模块

文章介绍了注意力机制的概念,将其比作人类看图时的聚焦过程。自注意力机制用于发现信息内部的关联,而多头自注意力则通过多个角度对信息进行解构和重组。文章还提供了因果自注意力的背景,解释了其在生成模型中的作用。最后,通过一个CausalSelfAttention类的代码示例展示了如何在实践中实现自注意力机制。
摘要由CSDN通过智能技术生成

1 理论理解

1.1 注意力机制(Attention)

注意力机制很像人类看图片的逻辑,当我们看一张图片的时候,我们并没有看图片的全部内容,而是将注意力集中在了图片的焦点上。用上了注意力机制,信息(如下面的图片)就不在单纯是信息本身,而是附加了焦点。

1.2 注意力机制的实现

运用注意力机制处理信息就是将信息和关注的维度点乘,或者说将信息投影到关注的维度。比如一件商品有质量,价格,颜色,外形,生产商,发货地点等信息,但是你特别关注商品的价格,那么所有商品的所有信息投影到你的需求上,基本只有价格影响你买还是不买。

1.3 自注意力机制

自注意力机制是为了找到信息内部联系的手段。比如随便一句话:

美国国务卿布林肯将于2月5日至6日访问中国,这是担任国务卿之后首次访华,也是拜登政府上台两年多来,访华级别最高的美国官员。

指的是美国国务卿布林肯,与句子中的其他信息关联就不大。为了找到这种联系,引入了自注意力机制。做法就是将信息映射到不同的维度,然后投影后的信息做点乘(投影)。

做个形象化的比喻,你在广东被人叫靓仔,在广西被人叫叼毛,本质上你还是你,包含你的肉体和灵魂。只是你在不同的空间,时间,以及叫法不同。为了找出这种本质,先把你扔到广东被人叫靓仔,然后把你扔到广西被人叫叼毛,然后把两个空间的你做点乘。

1.4 多头自注意力机制

我们都说人是复杂的,很难用好人,或者坏人来描述。所以要从不同的方面去解构,而且不能只看你一个人怎么看你,还要看很多人怎么看你。类比到多头自注意力机制就是通过多个人观察你,每个人观察的角度不同,关注的点也不同,然后汇总,得到一个比较完整的你。

1.5 因果自注意力

因为GPT是生成模型,是利用前面的信息生成后面的信息的,也就是后面的信息开始是不知道的。但是通过已有的信息我们可以推测未知的信息。

2 代码分析

class CausalSelfAttention(nn.Module):
    """
    A vanilla multi-head masked self-attention layer with a projection at the end.
    It is possible to use torch.nn.MultiheadAttention here but I am including an
    explicit implementation here to show that there is nothing too scary here.
    """

    def  __init__(self, config):
        super().__init__()
        assert config.n_embd % config.n_head == 0
        # key, query, value projections for all heads, but in a batch
        self.c_attn = nn.Linear(config.n_embd, 3 * config.n_embd)
        # output projection
        self.c_proj = nn.Linear(config.n_embd, config.n_embd)
        # regularization
        self.attn_dropout = nn.Dropout(config.attn_pdrop)
        self.resid_dropout = nn.Dropout(config.resid_pdrop)
        # causal mask to ensure that attention is only applied to the left in the input sequence
        self.register_buffer("bias", torch.tril(torch.ones(config.block_size, config.block_size))
                                     .view(1, 1, config.block_size, config.block_size))
        self.n_head = config.n_head
        self.n_embd = config.n_embd

    def forward(self, x):
        B, T, C = x.size() # batch size, sequence length, embedding dimensionality (n_embd)

        # calculate query, key, values for all heads in batch and move head forward to be the batch dim
        #同一个信息映射到不同的空间
        q, k ,v  = self.c_attn(x).split(self.n_embd, dim=2)
        k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
        q = q.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
        v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)

        # causal self-attention; Self-attend: (B, nh, T, hs) x (B, nh, hs, T) -> (B, nh, T, T)
        att = (q @ k.transpose(-2, -1)) * (1.0 / math.sqrt(k.size(-1)))
        att = att.masked_fill(self.bias[:,:,:T,:T] == 0, float('-inf'))
        att = F.softmax(att, dim=-1)
        att = self.attn_dropout(att)
        y = att @ v # (B, nh, T, T) x (B, nh, T, hs) -> (B, nh, T, hs)
        y = y.transpose(1, 2).contiguous().view(B, T, C) # re-assemble all head outputs side by side

        # output projection
        y = self.resid_dropout(self.c_proj(y))
        return y

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值