चुनौतियों पर वापस जाएँ
कठिन 0 हल किए गए 0% स्वीकृति

मल्टी-हेड सेल्फ़-अटेंशन

इनपुट को क्वेरी, की और वैल्यू में प्रोजेक्ट करें, कई हेड में समानांतर अटेंशन चलाएँ और उन्हें जोड़ें।

आप क्या सीखेंगे

  • इनपुट को क्वेरी, की और वैल्यू में प्रोजेक्ट करना
  • कई हेड में अटेंशन चलाना
  • हेड जोड़कर परिणाम प्रोजेक्ट करना

समस्या

मल्टी-हेड अटेंशन Transformer को एक साथ कई चीज़ों पर ध्यान देने देता है। इनपुट X (n टोकन × d कॉलम) और d × d वज़न मैट्रिक्स के साथ:

  1. Q = X × w_q, K = X × w_k, V = X × w_v
  2. d कॉलम को num_heads हेड में बाँटें, हर हेड में d_k = d / num_heads लगातार कॉलम (हेड h कॉलम h×d_k से (h+1)×d_k - 1 तक उपयोग करता है)।
  3. हर हेड के लिए उसके कॉलम पर स्केल्ड डॉट-प्रोडक्ट अटेंशन चलाएँ: टोकन i के लिए उस हेड के कॉलम पर score_j = (Q_i · K_j) / √d_k, सभी n टोकन j पर softmax, और आउटपुट = Σ weight_j × V_j (उस हेड के कॉलम)।
  4. हेड के आउटपुट को उनके कॉलम में वापस रखें (कॉन्कैटिनेशन) और w_o से गुणा करें।

multi_head_attention(x, w_q, w_k, w_v, w_o, num_heads) लागू करें।

इनपुट

x: n × d इनपुट मैट्रिक्स।

w_q, w_k, w_v, w_o: d × d वज़न मैट्रिक्स।

num_heads: हेड की संख्या (d इससे विभाज्य है)।

आउटपुट

n × d आउटपुट मैट्रिक्स लौटाएँ।

सीमाएँ

1 ≤ n ≤ 30, 1 ≤ d ≤ 32, 1 ≤ num_heads ≤ d और d, num_heads से विभाज्य है

-5 ≤ हर मान ≤ 5

उदाहरण

उदाहरण 1
इनपुट:
x = [
    [1.0, 0.0],
    [0.0, 1.0]
]
w_k = [
    [1.0, 0.0],
    [0.0, 1.0]
]
w_o = [
    [1.0, 0.0],
    [0.0, 1.0]
]
w_q = [
    [0.0, 0.0],
    [0.0, 0.0]
]
w_v = [
    [1.0, 0.0],
    [0.0, 1.0]
]
num_heads = 1

अपेक्षित आउटपुट:
expected = [
    [0.5, 0.5],
    [0.5, 0.5]
]
इनपुट:
std::vector<std::vector<double>> x = {
    {1.0, 0.0},
    {0.0, 1.0}
};
std::vector<std::vector<double>> w_k = {
    {1.0, 0.0},
    {0.0, 1.0}
};
std::vector<std::vector<double>> w_o = {
    {1.0, 0.0},
    {0.0, 1.0}
};
std::vector<std::vector<double>> w_q = {
    {0.0, 0.0},
    {0.0, 0.0}
};
std::vector<std::vector<double>> w_v = {
    {1.0, 0.0},
    {0.0, 1.0}
};
long long num_heads = 1;

अपेक्षित आउटपुट:
std::vector<std::vector<double>> expected = {
    {0.5, 0.5},
    {0.5, 0.5}
};
इनपुट:
double[][] x = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
double[][] w_k = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
double[][] w_o = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
double[][] w_q = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {0.0, 0.0}
};
double[][] w_v = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
long num_heads = 1;

अपेक्षित आउटपुट:
double[][] expected = new double[][] {
    new double[] {0.5, 0.5},
    new double[] {0.5, 0.5}
};

व्याख्या

w_q पूरी तरह शून्य है, इसलिए सभी स्कोर 0 हैं और हर टोकन वैल्यू पंक्तियों का औसत लेता है: V = X, इसलिए दोनों पंक्तियाँ [0.5, 0.5] बन जाती हैं।

उदाहरण 2
इनपुट:
x = [
    [2.0, 4.0]
]
w_k = [
    [1.0, 0.0],
    [0.0, 1.0]
]
w_o = [
    [0.0, 1.0],
    [1.0, 0.0]
]
w_q = [
    [1.0, 0.0],
    [0.0, 1.0]
]
w_v = [
    [1.0, 0.0],
    [0.0, 1.0]
]
num_heads = 2

अपेक्षित आउटपुट:
expected = [
    [4.0, 2.0]
]
इनपुट:
std::vector<std::vector<double>> x = {
    {2.0, 4.0}
};
std::vector<std::vector<double>> w_k = {
    {1.0, 0.0},
    {0.0, 1.0}
};
std::vector<std::vector<double>> w_o = {
    {0.0, 1.0},
    {1.0, 0.0}
};
std::vector<std::vector<double>> w_q = {
    {1.0, 0.0},
    {0.0, 1.0}
};
std::vector<std::vector<double>> w_v = {
    {1.0, 0.0},
    {0.0, 1.0}
};
long long num_heads = 2;

अपेक्षित आउटपुट:
std::vector<std::vector<double>> expected = {
    {4.0, 2.0}
};
इनपुट:
double[][] x = new double[][] {
    new double[] {2.0, 4.0}
};
double[][] w_k = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
double[][] w_o = new double[][] {
    new double[] {0.0, 1.0},
    new double[] {1.0, 0.0}
};
double[][] w_q = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
double[][] w_v = new double[][] {
    new double[] {1.0, 0.0},
    new double[] {0.0, 1.0}
};
long num_heads = 2;

अपेक्षित आउटपुट:
double[][] expected = new double[][] {
    new double[] {4.0, 2.0}
};

व्याख्या

केवल एक टोकन होने पर हर हेड सिर्फ़ ख़ुद पर ध्यान देता है, इसलिए जोड़ा गया आउटपुट V = [2, 4] है। w_o दोनों कॉलम की अदला-बदली करता है: [4, 2]।

कैसे हल करें

पहले खुद कोशिश करें, फिर एक-एक करके संकेत खोलें।

संकेत 1

पहले input को queries, keys, और values में project करें, फिर feature dimension को equal head-sized chunks में split करें.

संकेत 2

हर head के अंदर वही attention procedure independently run करें, scaling के लिए smaller head dimension use करके.

संकेत 3

Final output projection से पहले head outputs को उनके original column order में concatenate करें, और matrix dimensions को carefully aligned रखें.

अपेक्षित जटिलता

समय O(n^2 * d + n * d^2), अतिरिक्त स्थान O(n * d)

संदर्भ

यह चुनौती CodeUtility के लिए अनुकूलित की गई है। ऊपर दिए गए स्टेटमेंट और सीमाओं का पालन करें।

दूसरों से सीखें

समुदाय समाधान

अभी तक कोई प्रकाशित समाधान नहीं। पहला साझा करने के लिए इस चुनौती को हल करें।