Self-Attention은 시퀀스 내의 각 요소가 서로를 참조하는 메커니즘입니다. 입력 시퀀스의 모든 요소가 Query, Key, Value로 사용된다.
이를 통해 각 요소가 시퀀스 내 다른 요소들과의 관계를 학습할 수 있다.
예를 들어, 문장 내에서 단어 간의 관계를 학습하여 번역이나 요약에 활용할 수 있다.
<Self-Attention 메커니즘의 구현> Scaled Dot-Product Attention
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(Q, K, V):
d_k = Q.size(-1) # Key의 차원 수
scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(d_k, dtype=torch.float32)) # 유사도 계산 및 스케일링
attn_weights = F.softmax(scores, dim=-1) # Softmax를 통한 가중치 계산
output = torch.matmul(attn_weights, V) # 가중합을 통한 최종 출력 계산
return output, attn_weights
2. Multi-Head Attention
Multi-Head Attention은 여러 개의 Self-Attention을 병렬로 수행하는 메커니즘이다.
각 헤드는 서로 다른 부분의 정보를 학습하며, 이를 통해 모델이 다양한 관점에서 데이터를 처리할 수 있다.
<Multi-Head Attention 메커니즘의 구현>
class MultiHeadAttention(nn.Module):
def __init__(self, embed_size, heads):
super(MultiHeadAttention, self).__init__()
self.embed_size = embed_size
self.heads = heads
self.head_dim = embed_size // heads
assert (
self.head_dim * heads == embed_size
), "Embedding size needs to be divisible by heads"
self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)
self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)
self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)
self.fc_out = nn.Linear(heads * self.head_dim, embed_size)
def forward(self, values, keys, query, mask=None):
N = query.shape[0]
value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]
# Linear transformations
values = self.values(values).view(N, value_len, self.heads, self.head_dim)
keys = self.keys(keys).view(N, key_len, self.heads, self.head_dim)
queries = self.queries(query).view(N, query_len, self.heads, self.head_dim)
# Scaled dot-product attention
out, _ = scaled_dot_product_attention(queries, keys, values)
out = out.view(N, query_len, self.heads * self.head_dim)
out = self.fc_out(out)
return out
가중치를 두어 보다 중요한 정보만 중심으로 정리하는 데이터 처리 기법을 배우게 되었다. 정보를 요약할 때 유용하게 쓰일 것 같다.