問題
言語モデルは未来の単語を盗み見てはいけません。因果的アテンションは未来をマスクします。クエリ行 i が注目できるのはキー行 0 から i までだけです。
各行 i について(queries、keys、values はいずれも n 行):
- 許可された各キー j ≤ i のスコアを計算します:score = (queries[i] · keys[j]) / √d。d は keys の列数です。
- 許可されたスコアだけでソフトマックスを計算します(e^x を計算する前に最大値を引きます)。
- 出力行 i = j ≤ i にわたる Σ weight_j × values[j]。
causal_attention(queries, keys, values) を実装してください。
入力
queries, keys: n 行、各行 d 個の数。
values: n 行、各行 v 個の数。
出力
n × v の出力行列を返してください。
制約
1 ≤ n ≤ 50、1 ≤ d, v ≤ 32
-10 ≤ 各値 ≤ 10
例
例 1
入力:
keys = [
[1.0],
[2.0],
[3.0]
]
values = [
[3.0],
[6.0],
[9.0]
]
queries = [
[0.0],
[0.0],
[0.0]
]
期待される出力:
expected = [
[3.0],
[4.5],
[6.0]
]
入力:
std::vector<std::vector<double>> keys = {
{1.0},
{2.0},
{3.0}
};
std::vector<std::vector<double>> values = {
{3.0},
{6.0},
{9.0}
};
std::vector<std::vector<double>> queries = {
{0.0},
{0.0},
{0.0}
};
期待される出力:
std::vector<std::vector<double>> expected = {
{3.0},
{4.5},
{6.0}
};
入力:
double[][] keys = new double[][] {
new double[] {1.0},
new double[] {2.0},
new double[] {3.0}
};
double[][] values = new double[][] {
new double[] {3.0},
new double[] {6.0},
new double[] {9.0}
};
double[][] queries = new double[][] {
new double[] {0.0},
new double[] {0.0},
new double[] {0.0}
};
期待される出力:
double[][] expected = new double[][] {
new double[] {3.0},
new double[] {4.5},
new double[] {6.0}
};
解説
スコアはすべて 0 なので、各行は見られる値の平均になります。行 0 は 3 だけ、行 1 は 3 と 6 の平均(4.5)、行 2 は3つすべての平均(6)です。
例 2
入力:
keys = [
[1.0, 0.0],
[1.0, 0.0]
]
values = [
[1.0, 2.0],
[3.0, 4.0]
]
queries = [
[1.0, 0.0],
[1.0, 0.0]
]
期待される出力:
expected = [
[1.0, 2.0],
[2.0, 3.0]
]
入力:
std::vector<std::vector<double>> keys = {
{1.0, 0.0},
{1.0, 0.0}
};
std::vector<std::vector<double>> values = {
{1.0, 2.0},
{3.0, 4.0}
};
std::vector<std::vector<double>> queries = {
{1.0, 0.0},
{1.0, 0.0}
};
期待される出力:
std::vector<std::vector<double>> expected = {
{1.0, 2.0},
{2.0, 3.0}
};
入力:
double[][] keys = new double[][] {
new double[] {1.0, 0.0},
new double[] {1.0, 0.0}
};
double[][] values = new double[][] {
new double[] {1.0, 2.0},
new double[] {3.0, 4.0}
};
double[][] queries = new double[][] {
new double[] {1.0, 0.0},
new double[] {1.0, 0.0}
};
期待される出力:
double[][] expected = new double[][] {
new double[] {1.0, 2.0},
new double[] {2.0, 3.0}
};
解説
行 0 は自分だけを見られるので values[0] = [1, 2] をそのままコピーします。行 1 は2つのキーに同じスコアを与えるので、その平均 [2, 3] になります。
参考資料
この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。