2017 年《Attention Is All You Need》开启了大模型时代。
Self-Attention 机制
python
import torch
import torch.nn as nn
import math
class SelfAttention(nn.Module):
def __init__(self, embed_size, heads):
super().__init__()
self.embed_size = embed_size
self.heads = heads
self.head_dim = embed_size // heads
self.values = nn.Linear(embed_size, embed_size)
self.keys = nn.Linear(embed_size, embed_size)
self.queries = nn.Linear(embed_size, embed_size)
self.fc_out = nn.Linear(embed_size, embed_size)
def forward(self, values, keys, query, mask):
N = query.shape[0]
value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]
# 分割多头
values = self.values(values).reshape(N, value_len, self.heads, self.head_dim)
keys = self.keys(keys).reshape(N, key_len, self.heads, self.head_dim)
queries = self.queries(query).reshape(N, query_len, self.heads, self.head_dim)
# 注意力分数
energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])
attention = torch.softmax(energy / math.sqrt(self.head_dim), dim=3)
out = torch.einsum("nhql,nlhd->nqhd", [attention, values])
out = out.reshape(N, query_len, self.heads * self.head_dim)
return self.fc_out(out)位置编码
python
class PositionalEncoding(nn.Module):
def __init__(self, embed_size, max_len=5000):
super().__init__()
pe = torch.zeros(max_len, embed_size)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, embed_size, 2).float() * (-math.log(10000.0) / embed_size))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.pe = pe.unsqueeze(0)
def forward(self, x):
return x + self.pe[:, :x.size(1)]总结
Transformer 的核心是 Self-Attention + 位置编码。
评论
0评论加载中…