El rango ha aparecido en casi todas las lecciones anteriores: como criterio de compatibilidad, como dimensión del espacio columna, como prueba de independencia y como decisión sujeta a una tolerancia. Esta lección reúne lo que faltaba. Un teorema que se ha usado sin enunciar, y la construcción que convierte el rango en una herramienta de compresión.
Filas y columnas
El rango puede definirse como el número de filas linealmente independientes o como el número de columnas independientes. Son dos definiciones distintas que producen el mismo número:
El resultado no es evidente. Una matriz de tiene a lo sumo tres filas independientes y hasta cien columnas candidatas, y sin embargo el número de columnas independientes tampoco puede superar tres.
La descomposición en valores singulares lo explica en una línea. Si , entonces , y ambas tienen los mismos valores singulares no nulos. Como el rango es el número de valores singulares no nulos, la igualdad es inmediata. La lección sobre subespacios lo había anticipado al asignar la misma dimensión al espacio fila y al espacio columna.
import numpy as np
A = np.array([[1., 2., 3.],
[2., 4., 6.]]) # fila 2 = 2 · fila 1
np.linalg.matrix_rank(A) # 1
np.linalg.matrix_rank(A.T) # 1
Una consecuencia inmediata es la cota . Cuando se alcanza la igualdad, la matriz tiene rango completo. Para una matriz cuadrada eso equivale a ser invertible, que es la condición de la lección sobre la inversa vista ahora como una afirmación sobre dimensiones.
El rango de un producto
De la interpretación del producto como composición se sigue una segunda cota:
La razón es que , porque toda columna de es combinación de las columnas de , y simétricamente para las filas. Componer transformaciones no puede aumentar la dimensión de la imagen.
Esa cota, que parece una limitación, es la base de la última sección: multiplicar dos matrices estrechas produce una matriz grande de rango garantizadamente bajo.
Aproximación de rango bajo
Con datos reales el rango es casi siempre completo, como estableció la lección sobre independencia lineal. La pregunta útil deja de ser cuál es el rango y pasa a ser qué se pierde al tratar la matriz como si tuviera rango .
La descomposición en valores singulares responde de forma exacta. Escribiendo como suma de matrices de rango uno ordenadas por decreciente, y truncando la suma:
El teorema de Eckart-Young establece que es la mejor aproximación posible de rango , y que el error cometido es exactamente lo descartado:
No hay que buscar la mejor aproximación: la proporciona la descomposición, ordenada.
Las barras son los valores singulares; las conservadas aparecen destacadas.
energía 90.18 % · error 31.33 %
almacenamiento 130 / 1024 = 13 %
El rango k cuesta k(2n+1) números en lugar de n².
La figura descompone un campo de y reconstruye con los primeros términos. Con se retiene el de la energía ocupando el del almacenamiento; con , el ocupando el .
Un detalle del ejemplo ilustra la teoría. Las manchas gaussianas son separables, de la forma , y por tanto de rango uno cada una: una figura compuesta solo de manchas tendría rango exactamente finito y nada que truncar. La cresta diagonal y el anillo no son separables, y son las que dan al espectro su cola.
El almacenamiento es la razón práctica. Guardar requiere vectores de longitud , de longitud y valores singulares, es decir números frente a los de la matriz completa. La compresión es rentable cuando .
El rango efectivo
Entre el rango numérico, que es un entero sujeto a una tolerancia, y el espectro completo, que son números, existen medidas intermedias del número de direcciones que importan.
La más común en la práctica es contar cuántos valores singulares hacen falta para alcanzar una fracción dada de la energía:
s = np.linalg.svd(A, compute_uv=False)
energia = np.cumsum(s**2) / np.sum(s**2)
k_90 = np.searchsorted(energia, 0.90) + 1 # direcciones al 90 %
Es la misma cantidad que en el análisis de componentes principales se representa como varianza explicada acumulada, y el criterio para elegir el número de componentes.
Aplicación: adaptación de bajo rango
Ajustar un modelo grande a una tarea concreta requiere modificar sus matrices de pesos. Para una capa con , actualizar por completo significa entrenar parámetros, que para son casi diecisiete millones por capa.
La adaptación de bajo rango parte de una hipótesis: la actualización necesaria tiene rango intrínseco bajo. Si es así, puede escribirse como producto de dos matrices estrechas:
Por la cota del apartado anterior, por construcción, sin necesidad de imponerlo. Los parámetros entrenables pasan de a .
parámetros entrenables 0.39 %
ΔW es d×d; B es d×r y A es r×d, de modo que rank(BA) ≤ r por construcción.
factor de reducción ×256
El ahorro es d²/(2dr) = d/(2r), y crece con el tamaño de la capa.
Con y , los parámetros entrenables se reducen al : un factor de . El ahorro es , de modo que crece con el tamaño de la capa, que es la razón de que la técnica resulte más ventajosa cuanto mayor es el modelo.
La hipótesis de rango bajo es empírica, no un teorema: funciona porque las actualizaciones requeridas para especializar un modelo ya entrenado resultan tener, en la práctica, poca dimensión efectiva. Cuando no se cumple, el rango limita lo que la adaptación puede representar, y el diagnóstico es el mismo que en el resto de la lección: el espacio columna alcanzable tiene dimensión a lo sumo .
Ejercicio. Generar una matriz como producto de dos matrices más ruido gaussiano de escala . Comprobar que matrix_rank devuelve y representar los valores singulares en escala logarítmica, identificando el salto entre los tres primeros y el resto. Verificar después la igualdad de Eckart-Young comparando norm(A - A_3, 'fro') con sqrt(sum(s[3:]**2)).