問題
アテンションは単語の順序を無視するため、元の Transformer は各トークンの埋め込みに位置エンコーディングを加えます。サイズ d_model のモデルで、位置 pos と次元 j(どちらも 0 から)について:
- j が偶数:PE[pos][j] = sin(pos / 10000^(j / d_model))
- j が奇数:PE[pos][j] = cos(pos / 10000^((j - 1) / d_model))
つまり次元 0 と 1 は同じ周波数、次元 2 と 3 は次の周波数、というように続きます。
positional_encoding(length, d_model) を実装してください。
入力
length: 位置の数(0 から length - 1)。
d_model: 埋め込みのサイズ。
出力
length × d_model の行列を返してください。
制約
1 ≤ length ≤ 200、1 ≤ d_model ≤ 128
例
入力:
length = 2
d_model = 4
期待される出力:
expected = [
[0.0, 1.0, 0.0, 1.0],
[0.841471, 0.540302, 0.01, 0.99995]
]
入力:
long long length = 2;
long long d_model = 4;
期待される出力:
std::vector<std::vector<double>> expected = {
{0.0, 1.0, 0.0, 1.0},
{0.841471, 0.540302, 0.01, 0.99995}
};
入力:
long length = 2;
long d_model = 4;
期待される出力:
double[][] expected = new double[][] {
new double[] {0.0, 1.0, 0.0, 1.0},
new double[] {0.841471, 0.540302, 0.01, 0.99995}
};
解説
位置 0 はどのペアも sin(0) = 0、cos(0) = 1 なので [0, 1, 0, 1]。位置 1 は周波数 1 と 1 / 10000^(2/4) = 0.01 を使います:[sin 1, cos 1, sin 0.01, cos 0.01] ≈ [0.841471, 0.540302, 0.01, 0.99995]。
入力:
length = 3
d_model = 1
期待される出力:
expected = [
[0.0],
[0.841471],
[0.909297]
]
入力:
long long length = 3;
long long d_model = 1;
期待される出力:
std::vector<std::vector<double>> expected = {
{0.0},
{0.841471},
{0.909297}
};
入力:
long length = 3;
long d_model = 1;
期待される出力:
double[][] expected = new double[][] {
new double[] {0.0},
new double[] {0.841471},
new double[] {0.909297}
};
解説
次元が1つだけなので sin(pos) だけを使います:[[0], [0.841471], [0.909297]]。
参考資料
この課題はCodeUtility用に調整されています。上記の説明と制約に従ってください。