RoPE(旋转位置编码),Llama中使用的位置编码,是一种相对位置编码。注意力分数必然仅由标记之间的“相对距离”决定。因此,Llama 模型中的位置索引应该具有平移不变性。 但是当我将所有位置索引添加给定数字(例如 1000)时,模型的性能实际上会受到影响(这可以从下游任务的性能差异看出)。但为什么?不应该是
平移不变性吗?
您可以在 NumPy 中看到,使用标准 RoPE 实现(为简单起见,未批处理):
sequence_length = 5
positions = np.arange(sequence_length)
# Construct some dummy query and key arrays of shape [S, H].
hidden_size = 4
q = np.arange(hidden_size)[None].repeat(sequence_length, axis=0)
k = np.arange(hidden_size)[None].repeat(sequence_length, axis=0)
frequencies = 1e4 ** (np.arange(0, hidden_size, 2.0) / hidden_size)
inputs = positions[:, None] / frequencies[None, :]
sin, cos = np.sin(inputs), np.cos(inputs)
q1, q2 = np.split(q, 2, axis=-1)
q_rot = np.concatenate([q1 * cos - q2 * sin, q1 * sin + q2 * cos], axis=-1)
k1, k2 = np.split(k, 2, axis=-1)
k_rot = np.concatenate([k1 * cos - k2 * sin, k1 * sin + k2 * cos], axis=-1)
np.einsum('td,Td->tT', q_rot, k_rot)
这应该导致:
array([[14. , 12.16070923, 8.33341272],
[12.16070923, 14. , 12.16070923],
[ 8.33341272, 12.16070923, 14. ]])
移动位置(例如
positions = 100 + np.arange(sequence_length)
)会得到完全相同的结果。上面的代码以双精度运行,这是 NumPy 默认的。以 float32 精度运行,差异仍然可以忽略不计(在 1e-7 内),但使用 float16 我们已经开始看到很大的差异(~1e-2)。
由于大型模型通常以混合精度运行,这可以解释您的观察结果。