4. Attention Mechanisms
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
Attention Mechanisms and Self-Attention in Neural Networks
Attention mechanisms allow neural networks to focus on specific parts of the input when generating each part of the output. वे विभिन्न इनपुट्स को विभिन्न वज़न असाइन करते हैं, जिससे मॉडल यह तय करने में मदद मिलती है कि कौन से इनपुट कार्य के लिए सबसे प्रासंगिक हैं। यह मशीन अनुवाद जैसे कार्यों में महत्वपूर्ण है, जहाँ पूरे वाक्य के संदर्भ को समझना सटीक अनुवाद के लिए आवश्यक है।
tip
इस चौथे चरण का लक्ष्य बहुत सरल है: कुछ ध्यान तंत्र लागू करें। ये बहुत सारे दोहराए गए परतें होंगी जो शब्द के शब्दावली में उसके पड़ोसियों के साथ संबंध को कैप्चर करेंगी जो LLM को प्रशिक्षित करने के लिए वर्तमान वाक्य में उपयोग किया जा रहा है।
इसके लिए बहुत सारी परतें उपयोग की जाती हैं, इसलिए बहुत सारे प्रशिक्षित करने योग्य पैरामीटर इस जानकारी को कैप्चर करने जा रहे हैं।
Understanding Attention Mechanisms
परंपरागत अनुक्रम-से-अनुक्रम मॉडल में जो भाषा अनुवाद के लिए उपयोग किए जाते हैं, मॉडल एक इनपुट अनुक्रम को एक निश्चित आकार के संदर्भ वेक्टर में एन्कोड करता है। हालाँकि, यह दृष्टिकोण लंबे वाक्यों के साथ संघर्ष करता है क्योंकि निश्चित आकार का संदर्भ वेक्टर सभी आवश्यक जानकारी को कैप्चर नहीं कर सकता। ध्यान तंत्र इस सीमा को संबोधित करते हैं क्योंकि यह मॉडल को प्रत्येक आउटपुट टोकन उत्पन्न करते समय सभी इनपुट टोकन पर विचार करने की अनुमति देता है।
Example: Machine Translation
जर्मन वाक्य "Kannst du mir helfen diesen Satz zu übersetzen" का अंग्रेजी में अनुवाद करने पर विचार करें। शब्द-दर-शब्द अनुवाद एक व्याकरणिक रूप से सही अंग्रेजी वाक्य उत्पन्न नहीं करेगा क्योंकि भाषाओं के बीच व्याकरणिक संरचनाओं में अंतर होता है। एक ध्यान तंत्र मॉडल को आउटपुट वाक्य के प्रत्येक शब्द को उत्पन्न करते समय इनपुट वाक्य के प्रासंगिक भागों पर ध्यान केंद्रित करने में सक्षम बनाता है, जिससे एक अधिक सटीक और सुसंगत अनुवाद होता है।
Introduction to Self-Attention
Self-attention, या intra-attention, एक तंत्र है जहाँ ध्यान एकल अनुक्रम के भीतर लागू होता है ताकि उस अनुक्रम का प्रतिनिधित्व किया जा सके। यह अनुक्रम में प्रत्येक टोकन को सभी अन्य टोकनों पर ध्यान केंद्रित करने की अनुमति देता है, जिससे मॉडल को टोकनों के बीच की निर्भरताओं को कैप्चर करने में मदद मिलती है चाहे उनकी दूरी अनुक्रम में कितनी भी हो।
Key Concepts
- Tokens: इनपुट अनुक्रम के व्यक्तिगत तत्व (जैसे, वाक्य में शब्द)।
- Embeddings: टोकनों के वेक्टर प्रतिनिधित्व, जो अर्थ संबंधी जानकारी को कैप्चर करते हैं।
- Attention Weights: मान जो यह निर्धारित करते हैं कि प्रत्येक टोकन अन्य टोकनों की तुलना में कितना महत्वपूर्ण है।
Calculating Attention Weights: A Step-by-Step Example
आइए वाक्य "Hello shiny sun!" पर विचार करें और प्रत्येक शब्द को 3-आयामी एम्बेडिंग के साथ प्रदर्शित करें:
- Hello:
[0.34, 0.22, 0.54]
- shiny:
[0.53, 0.34, 0.98]
- sun:
[0.29, 0.54, 0.93]
हमारा लक्ष्य "shiny" शब्द के लिए संदर्भ वेक्टर की गणना करना है।
Step 1: Compute Attention Scores
tip
बस प्रत्येक आयाम मान को क्वेरी के साथ संबंधित टोकन के प्रत्येक आयाम मान से गुणा करें और परिणामों को जोड़ें। आपको प्रत्येक टोकन जोड़ी के लिए 1 मान मिलता है।
वाक्य में प्रत्येक शब्द के लिए, "shiny" के संदर्भ में ध्यान स्कोर की गणना करें उनके एम्बेडिंग के डॉट उत्पाद की गणना करके।
Attention Score between "Hello" and "shiny"
 (1) (1).png)
Attention Score between "shiny" and "shiny"
 (1) (1) (1) (1) (1) (1) (1).png)
Attention Score between "sun" and "shiny"
 (1) (1) (1) (1).png)
Step 2: Normalize Attention Scores to Obtain Attention Weights
tip
गणितीय शर्तों में खो न जाएं, इस फ़ंक्शन का लक्ष्य सरल है, सभी वज़नों को सामान्यीकृत करें ताकि वे कुल मिलाकर 1 हों।
इसके अलावा, softmax फ़ंक्शन का उपयोग किया जाता है क्योंकि यह गुणांक भाग के कारण भिन्नताओं को बढ़ाता है, उपयोगी मानों का पता लगाना आसान बनाता है।
ध्यान स्कोर को ध्यान वज़नों में परिवर्तित करने के लिए softmax फ़ंक्शन लागू करें जो 1 के बराबर होते हैं।
 (1) (1) (1) (1).png)
गुणांक की गणना:
 (1) (1).png)
योग की गणना:
 (1) (1).png)
ध्यान वज़नों की गणना:
 (1) (1).png)
Step 3: Compute the Context Vector
tip
बस प्रत्येक ध्यान वजन को संबंधित टोकन आयामों से गुणा करें और फिर सभी आयामों को जोड़ें ताकि केवल 1 वेक्टर (संदर्भ वेक्टर) प्राप्त हो सके।
संदर्भ वेक्टर को सभी शब्दों के एम्बेडिंग के वज़नी योग के रूप में गणना किया जाता है, ध्यान वज़नों का उपयोग करते हुए।
.png)
प्रत्येक घटक की गणना:
- Weighted Embedding of "Hello":
 (1) (1).png)
- Weighted Embedding of "shiny":
 (1) (1).png)
- Weighted Embedding of "sun":
 (1) (1).png)
वज़नी एम्बेडिंग का योग:
context vector=[0.0779+0.2156+0.1057, 0.0504+0.1382+0.1972, 0.1237+0.3983+0.3390]=[0.3992,0.3858,0.8610]
यह संदर्भ वेक्टर "shiny" शब्द के लिए समृद्ध एम्बेडिंग का प्रतिनिधित्व करता है, जो वाक्य में सभी शब्दों से जानकारी को शामिल करता है।
Summary of the Process
- Compute Attention Scores: लक्ष्य शब्द के एम्बेडिंग और अनुक्रम में सभी शब्दों के एम्बेडिंग के बीच डॉट उत्पाद का उपयोग करें।
- Normalize Scores to Get Attention Weights: ध्यान स्कोर को 1 के बराबर वज़न प्राप्त करने के लिए softmax फ़ंक्शन लागू करें।
- Compute Context Vector: प्रत्येक शब्द के एम्बेडिंग को उसके ध्यान वजन से गुणा करें और परिणामों को जोड़ें।
Self-Attention with Trainable Weights
व्यवहार में, self-attention तंत्र प्रशिक्षण योग्य वज़नों का उपयोग करते हैं ताकि क्वेरी, कुंजी और मानों के लिए सर्वोत्तम प्रतिनिधित्व सीखा जा सके। इसमें तीन वज़न मैट्रिक्स पेश करना शामिल है:
 (1) (1).png)
क्वेरी वही डेटा है जिसका उपयोग पहले की तरह किया जाता है, जबकि कुंजी और मान मैट्रिक्स बस यादृच्छिक-प्रशिक्षण योग्य मैट्रिक्स हैं।
Step 1: Compute Queries, Keys, and Values
प्रत्येक टोकन का अपना क्वेरी, कुंजी और मान मैट्रिक्स होगा, इसके आयाम मानों को परिभाषित मैट्रिक्स से गुणा करके:
.png)
ये मैट्रिक्स मूल एम्बेडिंग को ध्यान की गणना के लिए उपयुक्त एक नए स्थान में परिवर्तित करते हैं।
Example
मान लीजिए:
- इनपुट आयाम
din=3
(एम्बेडिंग आकार) - आउटपुट आयाम
dout=2
(क्वेरी, कुंजी और मानों के लिए इच्छित आयाम)
वज़न मैट्रिक्स को प्रारंभ करें:
import torch.nn as nn
d_in = 3
d_out = 2
W_query = nn.Parameter(torch.rand(d_in, d_out))
W_key = nn.Parameter(torch.rand(d_in, d_out))
W_value = nn.Parameter(torch.rand(d_in, d_out))
क्वेरी, की, और मानों की गणना करें:
queries = torch.matmul(inputs, W_query)
keys = torch.matmul(inputs, W_key)
values = torch.matmul(inputs, W_value)
Step 2: Compute Scaled Dot-Product Attention
Compute Attention Scores
पहले के उदाहरण के समान, लेकिन इस बार, टोकन के आयामों के मानों का उपयोग करने के बजाय, हम टोकन की कुंजी मैट्रिक्स का उपयोग करते हैं (जो पहले से ही आयामों का उपयोग करके गणना की गई है):। इसलिए, प्रत्येक क्वेरी qi
और कुंजी kj
के लिए:
.png)
Scale the Scores
डॉट उत्पादों को बहुत बड़ा होने से रोकने के लिए, उन्हें कुंजी आयाम dk
के वर्गमूल से स्केल करें:
.png)
tip
स्कोर को आयामों के वर्गमूल से विभाजित किया जाता है क्योंकि डॉट उत्पाद बहुत बड़े हो सकते हैं और यह उन्हें नियंत्रित करने में मदद करता है।
Apply Softmax to Obtain Attention Weights: प्रारंभिक उदाहरण की तरह, सभी मानों को सामान्यीकृत करें ताकि उनका योग 1 हो।
.png)
Step 3: Compute Context Vectors
प्रारंभिक उदाहरण की तरह, सभी मानों के मैट्रिक्स को जोड़ें, प्रत्येक को इसके ध्यान वजन से गुणा करें:
.png)
Code Example
https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb से एक उदाहरण लेते हुए, आप इस क्लास को देख सकते हैं जो हमने चर्चा की स्व-संबंधित कार्यक्षमता को लागू करती है:
import torch
inputs = torch.tensor(
[[0.43, 0.15, 0.89], # Your (x^1)
[0.55, 0.87, 0.66], # journey (x^2)
[0.57, 0.85, 0.64], # starts (x^3)
[0.22, 0.58, 0.33], # with (x^4)
[0.77, 0.25, 0.10], # one (x^5)
[0.05, 0.80, 0.55]] # step (x^6)
)
import torch.nn as nn
class SelfAttention_v2(nn.Module):
def __init__(self, d_in, d_out, qkv_bias=False):
super().__init__()
self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
def forward(self, x):
keys = self.W_key(x)
queries = self.W_query(x)
values = self.W_value(x)
attn_scores = queries @ keys.T
attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
context_vec = attn_weights @ values
return context_vec
d_in=3
d_out=2
torch.manual_seed(789)
sa_v2 = SelfAttention_v2(d_in, d_out)
print(sa_v2(inputs))
tip
ध्यान दें कि मैट्रिस को यादृच्छिक मानों के साथ प्रारंभ करने के बजाय, nn.Linear
का उपयोग सभी वेट्स को प्रशिक्षण के लिए पैरामीटर के रूप में चिह्नित करने के लिए किया जाता है।
कारणात्मक ध्यान: भविष्य के शब्दों को छिपाना
LLMs के लिए हम चाहते हैं कि मॉडल केवल उन टोकनों पर विचार करे जो वर्तमान स्थिति से पहले प्रकट होते हैं ताकि अगले टोकन की भविष्यवाणी की जा सके। कारणात्मक ध्यान, जिसे मास्केड ध्यान के रूप में भी जाना जाता है, भविष्य के टोकनों तक पहुंच को रोकने के लिए ध्यान तंत्र को संशोधित करके यह प्राप्त करता है।
कारणात्मक ध्यान मास्क लागू करना
कारणात्मक ध्यान को लागू करने के लिए, हम ध्यान स्कोर पर एक मास्क लागू करते हैं सॉफ्टमैक्स ऑपरेशन से पहले ताकि शेष स्कोर का योग 1 बना रहे। यह मास्क भविष्य के टोकनों के ध्यान स्कोर को नकारात्मक अनंत पर सेट करता है, यह सुनिश्चित करते हुए कि सॉफ्टमैक्स के बाद, उनके ध्यान वेट्स शून्य हैं।
चरण
- ध्यान स्कोर की गणना करें: पहले की तरह ही।
- मास्क लागू करें: एक ऊपरी त्रिकोणीय मैट्रिक्स का उपयोग करें जो विकर्ण के ऊपर नकारात्मक अनंत से भरा हो।
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1) * float('-inf')
masked_scores = attention_scores + mask
- सॉफ्टमैक्स लागू करें: मास्क किए गए स्कोर का उपयोग करके ध्यान वेट्स की गणना करें।
attention_weights = torch.softmax(masked_scores, dim=-1)
ड्रॉपआउट के साथ अतिरिक्त ध्यान वेट्स को मास्क करना
ओवरफिटिंग को रोकने के लिए, हम सॉफ्टमैक्स ऑपरेशन के बाद ध्यान वेट्स पर ड्रॉपआउट लागू कर सकते हैं। ड्रॉपआउट प्रशिक्षण के दौरान ध्यान वेट्स में से कुछ को यादृच्छिक रूप से शून्य कर देता है।
dropout = nn.Dropout(p=0.5)
attention_weights = dropout(attention_weights)
एक नियमित ड्रॉपआउट लगभग 10-20% है।
कोड उदाहरण
कोड उदाहरण https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb से:
import torch
import torch.nn as nn
inputs = torch.tensor(
[[0.43, 0.15, 0.89], # Your (x^1)
[0.55, 0.87, 0.66], # journey (x^2)
[0.57, 0.85, 0.64], # starts (x^3)
[0.22, 0.58, 0.33], # with (x^4)
[0.77, 0.25, 0.10], # one (x^5)
[0.05, 0.80, 0.55]] # step (x^6)
)
batch = torch.stack((inputs, inputs), dim=0)
print(batch.shape)
class CausalAttention(nn.Module):
def __init__(self, d_in, d_out, context_length,
dropout, qkv_bias=False):
super().__init__()
self.d_out = d_out
self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
self.dropout = nn.Dropout(dropout)
self.register_buffer('mask', torch.triu(torch.ones(context_length, context_length), diagonal=1)) # New
def forward(self, x):
b, num_tokens, d_in = x.shape
# b is the num of batches
# num_tokens is the number of tokens per batch
# d_in is the dimensions er token
keys = self.W_key(x) # This generates the keys of the tokens
queries = self.W_query(x)
values = self.W_value(x)
attn_scores = queries @ keys.transpose(1, 2) # Moves the third dimension to the second one and the second one to the third one to be able to multiply
attn_scores.masked_fill_( # New, _ ops are in-place
self.mask.bool()[:num_tokens, :num_tokens], -torch.inf) # `:num_tokens` to account for cases where the number of tokens in the batch is smaller than the supported context_size
attn_weights = torch.softmax(
attn_scores / keys.shape[-1]**0.5, dim=-1
)
attn_weights = self.dropout(attn_weights)
context_vec = attn_weights @ values
return context_vec
torch.manual_seed(123)
context_length = batch.shape[1]
d_in = 3
d_out = 2
ca = CausalAttention(d_in, d_out, context_length, 0.0)
context_vecs = ca(batch)
print(context_vecs)
print("context_vecs.shape:", context_vecs.shape)
एकल-हेड ध्यान को मल्टी-हेड ध्यान में विस्तारित करना
मल्टी-हेड ध्यान व्यावहारिक रूप से आत्म-ध्यान फ़ंक्शन के कई उदाहरणों को निष्पादित करने पर आधारित है, प्रत्येक के अपने वजन होते हैं ताकि विभिन्न अंतिम वेक्टर की गणना की जा सके।
कोड उदाहरण
पिछले कोड का पुन: उपयोग करना और बस एक रैपर जोड़ना जो इसे कई बार लॉन्च करता है संभव हो सकता है, लेकिन यह https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb से एक अधिक अनुकूलित संस्करण है जो सभी सिरों को एक साथ संसाधित करता है (महंगे फॉर लूप की संख्या को कम करता है)। जैसा कि आप कोड में देख सकते हैं, प्रत्येक टोकन के आयामों को सिरों की संख्या के अनुसार विभिन्न आयामों में विभाजित किया गया है। इस तरह, यदि टोकन के 8 आयाम हैं और हम 3 सिरों का उपयोग करना चाहते हैं, तो आयामों को 4 आयामों के 2 ऐरे में विभाजित किया जाएगा और प्रत्येक सिर उनमें से एक का उपयोग करेगा:
class MultiHeadAttention(nn.Module):
def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
super().__init__()
assert (d_out % num_heads == 0), \
"d_out must be divisible by num_heads"
self.d_out = d_out
self.num_heads = num_heads
self.head_dim = d_out // num_heads # Reduce the projection dim to match desired output dim
self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
self.out_proj = nn.Linear(d_out, d_out) # Linear layer to combine head outputs
self.dropout = nn.Dropout(dropout)
self.register_buffer(
"mask",
torch.triu(torch.ones(context_length, context_length),
diagonal=1)
)
def forward(self, x):
b, num_tokens, d_in = x.shape
# b is the num of batches
# num_tokens is the number of tokens per batch
# d_in is the dimensions er token
keys = self.W_key(x) # Shape: (b, num_tokens, d_out)
queries = self.W_query(x)
values = self.W_value(x)
# We implicitly split the matrix by adding a `num_heads` dimension
# Unroll last dim: (b, num_tokens, d_out) -> (b, num_tokens, num_heads, head_dim)
keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
values = values.view(b, num_tokens, self.num_heads, self.head_dim)
queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)
# Transpose: (b, num_tokens, num_heads, head_dim) -> (b, num_heads, num_tokens, head_dim)
keys = keys.transpose(1, 2)
queries = queries.transpose(1, 2)
values = values.transpose(1, 2)
# Compute scaled dot-product attention (aka self-attention) with a causal mask
attn_scores = queries @ keys.transpose(2, 3) # Dot product for each head
# Original mask truncated to the number of tokens and converted to boolean
mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
# Use the mask to fill attention scores
attn_scores.masked_fill_(mask_bool, -torch.inf)
attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
attn_weights = self.dropout(attn_weights)
# Shape: (b, num_tokens, num_heads, head_dim)
context_vec = (attn_weights @ values).transpose(1, 2)
# Combine heads, where self.d_out = self.num_heads * self.head_dim
context_vec = context_vec.contiguous().view(b, num_tokens, self.d_out)
context_vec = self.out_proj(context_vec) # optional projection
return context_vec
torch.manual_seed(123)
batch_size, context_length, d_in = batch.shape
d_out = 2
mha = MultiHeadAttention(d_in, d_out, context_length, 0.0, num_heads=2)
context_vecs = mha(batch)
print(context_vecs)
print("context_vecs.shape:", context_vecs.shape)
एक और संक्षिप्त और कुशल कार्यान्वयन के लिए आप PyTorch में torch.nn.MultiheadAttention
क्लास का उपयोग कर सकते हैं।
tip
ChatGPT का संक्षिप्त उत्तर कि क्यों टोकनों के आयामों को सिरों के बीच विभाजित करना बेहतर है बजाय इसके कि प्रत्येक सिर सभी टोकनों के सभी आयामों की जांच करे:
जबकि प्रत्येक सिर को सभी एम्बेडिंग आयामों को संसाधित करने की अनुमति देना फायदेमंद लग सकता है क्योंकि प्रत्येक सिर को पूर्ण जानकारी तक पहुंच होगी, मानक प्रथा है कि सिरों के बीच एम्बेडिंग आयामों को विभाजित करना। यह दृष्टिकोण गणनात्मक दक्षता और मॉडल प्रदर्शन के बीच संतुलन बनाता है और प्रत्येक सिर को विविध प्रतिनिधित्व सीखने के लिए प्रोत्साहित करता है। इसलिए, एम्बेडिंग आयामों को विभाजित करना आमतौर पर सभी आयामों की जांच करने के बजाय प्राथमिकता दी जाती है।
References
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।