English · Español
Lab 02 — Implementación de RoPE y la propiedad de posición relativa¶
Objetivo: implementar RoPE en NumPy; verificar numéricamente que \(\langle R_m q, R_n k \rangle = \langle q, R_{n-m} k \rangle\) con precisión 1e-5.
Tiempo estimado: 90–120 minutos.
Prerrequisito: lab 01 commiteado;
theory/03-rope.mdleído.
Lo que produces¶
Un directorio experiments/16-rope/ que contiene:
rope.py— tu implementación, ensrc/minimodel/positional/rope.py.verify.py— script de verificación.verify_output.txt— printout capturado.relative_position_demo.png— gráfico que muestra que la propiedad de posición relativa se cumple a lo largo de \(m - n\).manifest.json.README.md.
TODOs¶
Bloque A — implementación¶
Según src/minimodel/positional/BLUEPRINT.md:
-
rope_frequencies(d_head: int, base: float = 10000.0) -> np.ndarray. Forma(d_head/2,). -
precompute_rope(T: int, d_head: int) -> tuple[np.ndarray, np.ndarray]. Devuelve(cos_pe, sin_pe)de forma(T, d_head/2). -
apply_rope(q, k, cos_pe, sin_pe) -> tuple[np.ndarray, np.ndarray]. Cada uno de forma(T, d_head).
Implementa usando la convención de "pares entrelazados" (ver theory/03-rope.md): par \((2k, 2k+1)\) rotado en conjunto.
def apply_rope(q, k, cos_pe, sin_pe):
# q, k: (T, d_head)
# cos_pe, sin_pe: (T, d_head // 2)
q_even = q[:, 0::2]
q_odd = q[:, 1::2]
q_rope_even = q_even * cos_pe - q_odd * sin_pe
q_rope_odd = q_even * sin_pe + q_odd * cos_pe
q_rope = np.empty_like(q)
q_rope[:, 0::2] = q_rope_even
q_rope[:, 1::2] = q_rope_odd
# same for k
...
return q_rope, k_rope
Unas 15 LOC en total para apply_rope. Hecho a mano; sin atajos.
Bloque B — verifica la propiedad de posición relativa¶
Este es el test clave. La propiedad: \(\langle R_m q, R_n k \rangle = \langle q, R_{n-m} k \rangle\) para cualquier \(q, k, m, n\).
- Elige
d_head = 16, \(T = 32\). - Genera
q, kaleatorios de forma(d_head,)con semilla 0. - Precalcula
cos_pe, sin_pe = precompute_rope(T=32, d_head=16). - Para cada par \((m, n) \in \{(0, 1), (3, 7), (5, 5), (10, 12), (20, 8)\}\):
- Calcula
q_m = apply_rope_single(q, cos_pe[m], sin_pe[m])yk_n = apply_rope_single(k, cos_pe[n], sin_pe[n]). - Calcula
lhs = q_m @ k_n. - Calcula
k_diff = apply_rope_single(k, cos_pe[n - m], sin_pe[n - m])si \(n \geq m\), si no usacos_pe[-(m-n)]con el signo de \(\sin\) invertido. - Calcula
rhs = q @ k_diff. - Asegura
abs(lhs - rhs) < 1e-5. - Imprime los cinco pares en una tabla.
(apply_rope_single es una versión de una sola posición de apply_rope por conveniencia. O implementa el apply_rope completo y haz slicing.)
Bloque C — plotea la propiedad de posición relativa¶
- Para \(m = 0\) fijo, varía \(n\) de 0 a 31.
- En cada \(n\), calcula \(\langle R_m q, R_n k \rangle\).
- Plotea como función de \(n - m\).
- Superpón \(\langle q, R_{n-m} k \rangle\) sobre los mismos ejes.
- Las dos curvas tienen que coincidir exactamente (con tolerancia 1e-5).
- Guarda como
relative_position_demo.png.
Bloque D — sanity: RoPE preserva la norma¶
Las rotaciones son ortogonales: \(\|R q\| = \|q\|\).
-
qaleatorio de forma(d_head,). - Para cada posición \(p \in \{0, 1, 5, 100\}\), calcula la versión rotada.
- Asegura
np.allclose(np.linalg.norm(q_rotated), np.linalg.norm(q), atol=1e-6).
Bloque E — redacción¶
En README.md:
- Enuncia la propiedad de posición relativa. En una frase.
- Reporta la diferencia máxima a través de los cinco casos del Bloque B. Debería ser < 1e-5.
- Confirma la preservación de la norma (Bloque D).
- ¿Por qué V no se rota? Desde
theory/03-rope.md, con tus propias palabras.
Bloque F — manifest¶
{
"experiment": "16-rope",
"date": "YYYY-MM-DD",
"seed": 0,
"versions": { "python": "3.11.x", "numpy": "X.Y.Z" },
"config": {
"d_head": 16,
"T": 32,
"rope_base": 10000.0
},
"results_summary": {
"relative_position_max_diff": null,
"norm_preservation_max_diff": null
}
}
Restricciones¶
- Sin PyTorch.
- Convención de pares entrelazados. Documéntalo claramente en
README.md. Otras implementaciones usan la convención de "split-half"; esa también es válida pero las dos no son bit-equivalentes. - Sin einsums sofisticados. Usa indexación explícita y concatenación. Vectorizado pero legible.
Condiciones de parada¶
Hecho cuando:
- Los seis archivos commiteados.
- Las aserciones del Bloque B pasan todas (diferencia máxima < 1e-5).
- La preservación de la norma del Bloque D pasa.
relative_position_demo.pngmuestra dos curvas coincidentes.README.mdcontesta a las cuatro preguntas del Bloque E.
Escollos¶
- Convención de signos. La matriz de rotación en
theory/03-rope.mdusa \(\begin{pmatrix} \cos & -\sin \\ \sin & \cos \end{pmatrix}\). Esto es "antihorario". Algunas referencias usan horario (signos invertidos). Atente a la convención del archivo de teoría. apply_rope_single(q, cos_pe[m], sin_pe[m]). Cuandom > n, la posición relativa es negativa. La rotación por \(-\theta\) tiene \(\sin(-\theta) = -\sin(\theta)\). Maneja el signo correctamente al calcular el rhs.cos_pe[n - m]requiere \(n - m \geq 0\). Para los casos de test con \(n < m\), calcula la rotación a mano en lugar de indexar.- Precisión float. Con
float32y posiciones grandes, los valores trigonométricos pierden precisión. Para los T pequeños de la Fase 16 esto está bien; márcalo para Fase 22+ si Borja se extiende a contextos largos.
Cuándo consultar solutions/¶
Tras commitear los seis archivos y que las aserciones pasen. Solución en solutions/02-rope-ref.md.
Siguiente lab: 03-extrapolation-compare.md.