어려움 0명 해결 정답률 0%

Multi-Head Self-Attention

Project the input into queries, keys and values, run attention in several heads in parallel, and combine them.

배우게 될 내용

  • Project inputs into queries, keys and values
  • Run attention in several heads
  • Concatenate heads and project the result

문제

번역본 보기

Multi-head attention lets a Transformer attend to different things at once. With input X (n tokens × d columns) and weight matrices of size d × d:

  1. Q = X × w_q, K = X × w_k, V = X × w_v
  2. Split the d columns into num_heads heads of d_k = d / num_heads consecutive columns (head h uses columns h×d_k to (h+1)×d_k - 1).
  3. For each head, run scaled dot-product attention on its columns: for token i, score_j = (Q_i · K_j) / √d_k over that head's columns, softmax over all n tokens j, and output = Σ weight_j × V_j (that head's columns).
  4. Put the heads' outputs back in their columns (concatenate) and multiply by w_o.

Implement multi_head_attention(x, w_q, w_k, w_v, w_o, num_heads).

Input

x: n × d input matrix.

w_q, w_k, w_v, w_o: d × d weight matrices.

num_heads: Number of heads (d is divisible by it).

Output

Return the n × d output matrix.

제약 조건

1 ≤ n ≤ 30, 1 ≤ d ≤ 32, 1 ≤ num_heads ≤ d and d is divisible by num_heads

-5 ≤ each value ≤ 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 is all zeros, so every score is 0 and each token averages the value rows: V = X, so both rows become [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}
};

설명

With a single token each head attends only to itself, so the concatenated output is V = [2, 4]. w_o swaps the two columns: [4, 2].

접근 방법

먼저 스스로 풀어 본 뒤 힌트를 하나씩 열어 보세요.

힌트 1

Project the input into queries, keys, and values first, then split the feature dimension into equal head-sized chunks.

힌트 2

Run the same attention procedure inside each head independently, using the smaller head dimension for scaling.

힌트 3

Concatenate head outputs in their original column order before the final output projection, and keep matrix dimensions aligned carefully.

예상 복잡도

O(n^2 * d + n * d^2) time, O(n * d) extra space

참고 자료

이 문제는 CodeUtility에 맞게 수정되었습니다. 위의 설명과 제한 조건을 따르세요.

다른 사람의 풀이 보기

커뮤니티 솔루션

아직 공개된 풀이가 없습니다. 문제를 풀고 첫 풀이를 공유하세요.