赞
踩
注意力机制很像人类看图片的逻辑,当我们看一张图片的时候,我们并没有看图片的全部内容,而是将注意力集中在了图片的焦点上。用上了注意力机制,信息(如下面的图片)就不在单纯是信息本身,而是附加了焦点。
运用注意力机制处理信息就是将信息和关注的维度点乘,或者说将信息投影到关注的维度。比如一件商品有质量,价格,颜色,外形,生产商,发货地点等信息,但是你特别关注商品的价格,那么所有商品的所有信息投影到你的需求上,基本只有价格影响你买还是不买。
自注意力机制是为了找到信息内部联系的手段。比如随便一句话:
美国国务卿布林肯将于2月5日至6日访问中国,这是他担任国务卿之后首次访华,也是拜登政府上台两年多来,访华级别最高的美国官员。
他指的是美国国务卿布林肯,与句子中的其他信息关联就不大。为了找到这种联系,引入了自注意力机制。做法就是将信息映射到不同的维度,然后投影后的信息做点乘(投影)。
做个形象化的比喻,你在广东被人叫靓仔,在广西被人叫叼毛,本质上你还是你,包含你的肉体和灵魂。只是你在不同的空间,时间,以及叫法不同。为了找出这种本质,先把你扔到广东被人叫靓仔,然后把你扔到广西被人叫叼毛,然后把两个空间的你做点乘。
我们都说人是复杂的,很难用好人,或者坏人来描述。所以要从不同的方面去解构,而且不能只看你一个人怎么看你,还要看很多人怎么看你。类比到多头自注意力机制就是通过多个人观察你,每个人观察的角度不同,关注的点也不同,然后汇总,得到一个比较完整的你。
因为GPT是生成模型,是利用前面的信息生成后面的信息的,也就是后面的信息开始是不知道的。但是通过已有的信息我们可以推测未知的信息。
- 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

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。