Curso de Matemáticas para IA · Lección 5 de 180

Índices de tensores para IA: lectura de muestras, tokens y características

Aprende a leer subíndices de tensores, traducir direcciones lote-token-característica a NumPy y detectar errores de ejes que parecen válidos en código de IA.

Comparte este artículo

Un programa de IA lee X[1, 2, 0] y devuelve 0.8. Una expresión cercana, X[1, 0, 2], devuelve 0.3. Ambas direcciones son válidas. Solo una significa «la primera característica del último token del segundo ejemplo».

La diferencia es un índice: una posición utilizada para localizar un valor dentro de una estructura ordenada. Los índices son pequeñas piezas de notación, pero determinan qué ejemplo, token, característica, píxel o salida del modelo utiliza realmente un cálculo. Por eso, un índice incorrecto puede producir un número aparentemente creíble en lugar de un error útil.

Al terminar esta lección, podrás leer muestras y coordenadas indexadas, seguir una dirección de tensor lote-token-característica, traducir un subíndice matemático a NumPy y detectar una dirección cuyos números son legales pero cuyos significados de eje son incorrectos. Esto añade orden a las colecciones de datos de la lección 4. El sitio oficial complementario de Mathematics for Machine Learning sitúa esta notación en el recorrido que va de los datos numéricos a los vectores, matrices y modelos utilizados más adelante en el curso.

Un índice responde «¿qué posición?»

Supón que un dataset ordenado contiene tres ejemplos:

D=(x1,x2,x3).D=(x_1,x_2,x_3).

El subíndice de x2x_2 dice «selecciona el ejemplo de la posición 2». No dice que el valor del ejemplo sea 2. Si el segundo ejemplo es el par x2=(1.7,0.4)x_2=(1.7,-0.4), entonces x2x_2 nombra el par completo.

Añade un segundo subíndice para seleccionar una coordenada dentro de ese ejemplo:

x2,1=1.7andx2,2=0.4.x_{2,1}=1.7 \qquad\text{and}\qquad x_{2,2}=-0.4.

Lee x2,1x_{2,1} de izquierda a derecha: elige el ejemplo 2 y después la coordenada 1. Los índices forman una dirección; el número almacenado en esa dirección es el valor.

Esto también separa la posición de la identidad. Mover una muestra de la posición 2 a la posición 7 cambia su índice aunque su identificador estable, los píxeles de la imagen y la etiqueta no cambien. Los índices son direcciones útiles, no nombres permanentes de objetos del mundo real.

Cada subíndice elige un eje

Un eje es una dirección en la que se organiza un array. Una tabla tiene un eje de filas y otro de columnas. Aquí, un tensor es un array multidimensional: puede tener esos dos ejes o añadir más para conceptos como lotes y tokens.

Considera un tensor de activaciones

XRB×T×F,X\in\mathbb{R}^{B\times T\times F},

donde:

  • BB es el número de ejemplos del lote;
  • TT es el número de posiciones de token por ejemplo; y
  • FF es el número de características almacenadas para cada token.

La notación RB×T×F\mathbb{R}^{B\times T\times F} dice que cada entrada es un número real y que el tensor tiene forma B×T×FB\times T\times F. Una entrada escalar es

Xb,t,f,X_{b,t,f},

que significa: elige la posición de lote bb, la posición de token tt y la posición de característica ff, en ese orden.

Para un tensor con forma 2×3×42\times3\times4, una convención matemática basada en uno permite

1b2,1t3,1f4.1\le b\le2, \qquad 1\le t\le3, \qquad 1\le f\le4.

La forma proporciona el rango de cada índice. Los nombres de los ejes proporcionan el significado. Ninguno de los dos hechos sustituye al otro.

Una dirección, seguida hasta llegar a un valor

Usa el siguiente tensor de dos lotes. Cada elemento del lote contiene tres filas de tokens y cada token tiene cuatro valores de características.

Sigue la dirección X2,3,1: elige el elemento 2 del lote, después el token 3 y, por último, la característica 1. La celda seleccionada contiene 0,8.
Cuadrícula tensorial del elemento del lote 1 Tres filas de tokens y cuatro columnas de características para el elemento 1 del lote.Elemento del lote 1índice de característica →índice de token →f1f2f3f4token 10.20.8-0.10.4token 21.1-0.30.50.0token 30.70.60.2-0.4 Cuadrícula tensorial del elemento del lote 2 Tres filas de tokens y cuatro columnas de características para el elemento 2 del lote. El token 3 y la característica 1 están seleccionados, con un valor de 0,8.Elemento del lote 2índice de característica →índice de token →f1f2f3f4token 1-0.20.90.30.1token 20.4-0.71.20.5token 30.8 ★0.1-0.61.5★ X₂,₃,₁ = 0.8
Elemento del lote 1: filas de tokens por columnas de características
TokenCaracterística 1Característica 2Característica 3Característica 4
10.20.8-0.10.4
21.1-0.30.50.0
30.70.60.2-0.4
Elemento del lote 2: filas de tokens por columnas de características
TokenCaracterística 1Característica 2Característica 3Característica 4
1-0.20.90.30.1
20.4-0.71.20.5
30.80.1-0.61.5

Esta lectura paso a paso importa más que memorizar un orden de letras. Otro proyecto podría almacenar los tokens antes que los lotes o usar ejes de altura, anchura y canal para imágenes. El código y la documentación deben declarar el contrato.

NumPy empieza en cero

Muchos textos de matemáticas etiquetan las posiciones empezando en 1. Python y NumPy utilizan indexación basada en cero, así que la primera posición es 0. La guía oficial de indexación de NumPy también confirma que un entero por dimensión selecciona un elemento y que el índice no negativo válido para un eje de tamaño dd satisface 0i<d0\le i<d.

Posición previstaMatemáticas basadas en unoNumPy basado en cero
Elemento 2 del loteb=2b=2b = 1
Token 3t=3t=3t = 2
Característica 1f=1f=1f = 0
Dirección completaX2,3,1X_{2,3,1}X[1, 2, 0]

Este es el tensor completo y varias selecciones verificadas:

import numpy as np

X = np.array([
    [[ 0.2,  0.8, -0.1,  0.4],
     [ 1.1, -0.3,  0.5,  0.0],
     [ 0.7,  0.6,  0.2, -0.4]],
    [[-0.2,  0.9,  0.3,  0.1],
     [ 0.4, -0.7,  1.2,  0.5],
     [ 0.8,  0.1, -0.6,  1.5]],
])

print("shape:", X.shape)
print("one activation:", X[1, 2, 0])
print("last token of example 2:", X[1, 2])
print("feature 1 of every last token:", X[:, 2, 0])
shape: (2, 3, 4)
one activation: 0.8
last token of example 2: [ 0.8  0.1 -0.6  1.5]
feature 1 of every last token: [0.7 0.8]

Los dos puntos de X[:, 2, 0] significan «conserva todas las posiciones de este eje». El primer eje permanece, mientras que token y característica reciben índices específicos, así que el resultado contiene un valor por cada uno de los dos elementos del lote.

El atributo shape informa de (2, 3, 4), pero la tupla por sí sola no dice «lote, token, característica». Esos nombres proceden del contrato de datos del programa.

Volvamos a las expresiones iniciales:

X[1, 2, 0]  # 0.8: batch 2, token 3, feature 1
X[1, 0, 2]  # 0.3: batch 2, token 1, feature 3

Ambas direcciones encajan en la forma. NumPy no puede saber que la segunda línea intercambió los significados de token y característica. Es un error de indexación semántico: el programa recupera una entrada real, pero no la que pretendía el cálculo.

Entre las defensas útiles están anotar el contrato de ejes junto al tensor, comprobar la forma en los límites y asignar nombres descriptivos a las variables de índice:

batch_index = 1
token_index = 2
feature_index = 0

activation = X[batch_index, token_index, feature_index]
assert X.shape == (2, 3, 4)
assert activation == 0.8

La aserción comprueba este ejemplo. Las variables descriptivas conservan el razonamiento que llevó a la dirección.

Los errores de límites son más seguros que los errores silenciosos de ejes

Para la forma basada en cero (2, 3, 4), la última dirección no negativa es X[1, 2, 3]. X[2, 0, 0] no es válida porque el índice de lote 2 pediría un tercer elemento de un eje que solo contiene dos. NumPy lanza IndexError en lugar de devolver un valor inventado.

Los índices negativos son una convención de Python: -1 selecciona la última posición de un eje, así que X[-1, -1, -1] es otra forma de leer X[1, 2, 3]. Es código válido, pero no debe traducirse silenciosamente a un subíndice matemático basado en uno. Declara la convención siempre que la distinción importe.

La próxima lección utilizará estas direcciones dentro de sumas. Cuando xix_i signifique claramente el ii-ésimo ejemplo y i\ell_i su pérdida, un símbolo como ii\sum_i\ell_i se convierte en una instrucción compacta para visitar cada pérdida indexada y combinar los valores.

Comprueba lo que has entendido

Pregunta 1

Si x₄ = (2.5, −1.0, 0.3), ¿a qué se refieren x₄ y x₄,₂?

Mostrar la solución paso a paso

Primero, lee el número de subíndices.

  1. x4x_4 tiene un índice, así que selecciona el ejemplo completo de la posición 4.
  2. El ejemplo dado es el valor de tres coordenadas (2.5,1.0,0.3)(2.5,-1.0,0.3).
  3. x4,2x_{4,2} añade un índice de coordenada, así que selecciona la coordenada 2 dentro de ese ejemplo.

Por tanto,

x4=(2.5,1.0,0.3)andx4,2=1.0.x_4=(2.5,-1.0,0.3) \qquad\text{and}\qquad x_{4,2}=-1.0.

El subíndice 4 es una dirección; no es el valor almacenado.

Pregunta 2

Usa la visualización para calcular X₂,₂,₃. Muestra cada elección de eje.

Mostrar la solución paso a paso

Sigue los índices en el orden lote-token-característica declarado.

  1. b=2b=2 elige el elemento 2 del lote.
  2. t=2t=2 elige su segunda fila de tokens: (0.4,0.7,1.2,0.5)(0.4,-0.7,1.2,0.5).
  3. f=3f=3 elige la tercera coordenada de esa fila.

Así,

X2,2,3=1.2.X_{2,2,3}=1.2.

Elegir la característica 3 antes que el token 2 cambiaría la pregunta porque los ejes están ordenados.

Pregunta 3

Traduce la dirección matemática basada en uno X₂,₃,₄ a NumPy basado en cero y encuentra su valor.

Mostrar la solución paso a paso

Resta 1 a cada posición al pasar de la convención basada en uno indicada a NumPy:

(2,3,4)(1,2,3).(2,3,4)\longrightarrow(1,2,3).

Por tanto, la dirección de código es X[1, 2, 3]. En el elemento 2 del lote, el token 3 es (0.8,0.1,0.6,1.5)(0.8,0.1,-0.6,1.5) y la característica 4 es 1.51.5. Por tanto,

X2,3,4=1.5.X_{2,3,4}=1.5.

Pregunta 4

Para un tensor basado en cero con forma (2, 3, 4), clasifica X[0, 2, 3], X[1, 3, 0] y X[2, 0, 0] como dentro o fuera de los límites.

Mostrar la solución paso a paso

Traduce la forma a rangos no negativos válidos:

b{0,1},t{0,1,2},f{0,1,2,3}.b\in\{0,1\},\qquad t\in\{0,1,2\},\qquad f\in\{0,1,2,3\}.
  • X[0, 2, 3] está dentro de los límites porque cada índice pertenece a su rango.
  • X[1, 3, 0] está fuera de los límites porque el índice de token 3 no está en {0,1,2}\{0,1,2\}.
  • X[2, 0, 0] está fuera de los límites porque el índice de lote 2 no está en {0,1}\{0,1\}.

El primer eje que falla basta para que NumPy rechace la dirección completa.

Pregunta 5

Un desarrollador pretende el lote 2, token 3 y característica 1, pero escribe X[1, 0, 2]. ¿Por qué no se produce un error de límites y cómo debe repararse la línea?

Mostrar la solución paso a paso

Para la forma (2, 3, 4), los índices (1, 0, 2) son mecánicamente válidos:

1<2,0<3,2<4.1<2,\qquad 0<3,\qquad 2<4.

Por tanto, NumPy devuelve el valor del lote 2, token 1 y característica 3, que es 0.30.3. La biblioteca no puede inferir los significados de eje pretendidos.

Convierte las posiciones basadas en uno previstas (2,3,1)(2,3,1) a posiciones basadas en cero $(1,2,0)`. La línea reparada es:

activation = X[1, 2, 0]  # 0.8

Es un error semántico, no un error de límites, por lo que los nombres descriptivos de variables y un contrato explícito de ejes son defensas útiles.

Pregunta 6

¿Qué selecciona X[-1, -1, -1] y por qué −1 no es una identidad permanente para ese valor?

Mostrar la solución paso a paso

En NumPy, -1 significa «la última posición de este eje». Para la forma (2, 3, 4), las últimas posiciones basadas en cero son (1, 2, 3). Por tanto,

X[1,1,1]=X[1,2,3]=1.5.X[-1,-1,-1]=X[1,2,3]=1.5.

El significado depende de la forma y el orden actuales. Si se añadiera otro elemento del lote o token, -1 apuntaría a otro sitio. Es una dirección relativa, no un identificador estable asociado al valor almacenado.

Fuentes

  1. Mathematics for Machine Learning companion website
  2. Mathematics for Machine Learning book PDF
  3. NumPy documentation: indexing on ndarrays
  4. NumPy documentation: ndarray shape