Espacios vectoriales

Independencia lineal con Python

La definición de independencia lineal y sus caracterizaciones equivalentes, el proceso de Gram-Schmidt como prueba constructiva, y el factor de inflación de la varianza para medir la dependencia aproximada de datos reales.

El curso ha empleado la expresión columnas linealmente independientes como criterio en varias ocasiones: al caracterizar las matrices invertibles, al describir el núcleo y al hablar de colinealidad. Esta lección establece la definición y, sobre todo, se ocupa de un problema que la definición no resuelve: con datos reales, la independencia exacta es la norma y resulta poco informativa.

La definición

Los vectores v1,,vk\vec{v}_1,\dots,\vec{v}_k de un espacio vectorial son linealmente independientes si la única combinación lineal que produce el vector nulo es la trivial:

i=1kλivi=0λ1==λk=0\sum_{i=1}^{k} \lambda_i \vec{v}_i = \vec{0} \quad\Longrightarrow\quad \lambda_1 = \cdots = \lambda_k = 0

En caso contrario son linealmente dependientes, y existe al menos un λj0\lambda_j \neq 0. Despejando ese término,

vj=1λjijλivi\vec{v}_j = -\frac{1}{\lambda_j}\sum_{i \neq j} \lambda_i \vec{v}_i

de modo que vj\vec{v}_j pertenece al span de los restantes y no amplía el subespacio generado.

Disponiendo los vectores como columnas de una matriz XX, la condición se traduce en afirmaciones ya conocidas, todas equivalentes entre sí:

FormulaciónCondición
definiciónXλ=0X\vec{\lambda} = \vec{0} solo con λ=0\vec{\lambda} = \vec{0}
núcleoker(X)={0}\ker(X) = \{\vec{0}\}
rangorank(X)=k\operatorname{rank}(X) = k
matriz de GramXXX^\top X no singular
determinante, si XX es cuadradadetX0\det X \neq 0
import numpy as np X = np.column_stack([[1., 0., 0.], [0., 1., 0.], [1., 1., 0.]]) # v₃ = v₁ + v₂ np.linalg.matrix_rank(X) # 2 < 3: dependientes

Las tres primeras filas de la tabla ya aparecieron por separado en lecciones anteriores. La equivalencia entre ellas es lo que hace intercambiables las herramientas: matrix_rank, null_space y det responden a la misma pregunta desde ángulos distintos.

Gram-Schmidt como prueba constructiva

Verificar el rango responde si hay dependencia. El proceso de Gram-Schmidt responde además dónde está, y lo hace construyendo una base ortonormal del span.

El procedimiento es la proyección de la lección anterior aplicada repetidamente. Para cada vector, se le resta su proyección sobre el subespacio ya construido y se normaliza el residuo:

vk=vkj<kvk,qjqj,qk=vkvk\vec{v}_k' = \vec{v}_k - \sum_{j<k} \langle \vec{v}_k, \vec{q}_j\rangle\, \vec{q}_j, \qquad \vec{q}_k = \frac{\vec{v}_k'}{\lVert \vec{v}_k' \rVert}
v1′
100

v1 · norma del residuo = 1

residuo nulo: dependiente

Paso 1 / 9

El criterio aparece en la norma del residuo. Si vk=0\lVert\vec{v}_k'\rVert = 0, el vector estaba enteramente contenido en el span de los anteriores y no aporta una dirección nueva. El botón sustituye v3=(1,1,0)\vec{v}_3 = (1,1,0), que es la suma de los dos primeros, por (0,0,1)(0,0,1): el residuo pasa de 00 a 11 y el conjunto se vuelve independiente.

Esa es la conexión con la factorización QR de la lección sobre eliminación gaussiana: los vectores qj\vec{q}_j son las columnas de QQ y los coeficientes vk,qj\langle\vec{v}_k,\vec{q}_j\rangle las entradas de RR. Gram-Schmidt es QR expuesto paso a paso, aunque la implementación de LAPACK emplea reflexiones de Householder, numéricamente más estables.

La pregunta binaria y los datos reales

Con datos medidos, la dependencia exacta prácticamente no ocurre: basta el ruido de la última cifra para que el rango salga completo. La lección sobre el núcleo describió la consecuencia inmediata —el rango numérico depende de una tolerancia—, pero hay una segunda, más de fondo.

El rango responde con un número entero a una pregunta que es continua. Dos columnas casi paralelas y dos columnas ortogonales reciben la misma respuesta, independientes, mientras que el modelo que se ajuste sobre ellas se comportará de forma radicalmente distinta.

σ1
28.36
σ2
2.45
σ3
1.93
matrix_rank
3
cond(X)
14.71
VIF de x₃
7.29
α
0.50

x₃ = (1 − α)·d + α·(x₁ + x₂). En α = 1 es exactamente la suma de las otras dos.

El rango solo cambia en el extremo; el número de condición y el VIF crecen en todo el recorrido.

La figura interpola la tercera columna entre una dirección independiente y la suma de las dos primeras. El comportamiento de los tres indicadores difiere por completo:

α\alphaσ3\sigma_3cond(X)\operatorname{cond}(X)VIFrango
01.9711.81.33
0.51.9314.77.33
0.751.0629.742.83
0.90.4083.63383
0.990.03989838 7123
102

El rango permanece en 33 hasta el último instante y entonces salta. El número de condición y el VIF crecen de forma continua y ya señalan un problema grave en α=0.9\alpha = 0.9, donde el rango aún declara independencia.

La propia figura ilustra de paso un detalle numérico. Obtiene los valores singulares a partir de los autovalores de XXX^\top X, y formar esa matriz eleva al cuadrado el número de condición, de modo que σ3\sigma_3 conserva aproximadamente la mitad de las cifras significativas. El umbral aplicable es entonces εσ1\sqrt{\varepsilon}\,\sigma_1 y no εσ1\varepsilon\,\sigma_1; con el umbral habitual, la columna dependiente de α=1\alpha = 1 se declararía independiente. Es el mismo argumento que desaconseja las ecuaciones normales en la lección sobre la inversa y la transpuesta.

El factor de inflación de la varianza

El VIF de la columna jj mide cuánto de ella explican las demás. Se obtiene regresando esa columna sobre el resto y leyendo el coeficiente de determinación:

VIFj=11Rj2\mathrm{VIF}_j = \frac{1}{1 - R_j^2}

Su interpretación es directa: la varianza del coeficiente estimado β^j\hat{\beta}_j queda multiplicada por VIFj\mathrm{VIF}_j respecto de la que tendría si esa columna fuese ortogonal a las demás. Un VIF\mathrm{VIF} de 42.842.8 significa un intervalo de confianza 42.86.5\sqrt{42.8} \approx 6.5 veces más ancho.

def vif(X, j): otras = np.delete(X, j, axis=1) A = np.column_stack([np.ones(len(X)), otras]) beta, *_ = np.linalg.lstsq(A, X[:, j], rcond=None) residuo = X[:, j] - A @ beta r2 = 1 - residuo @ residuo / ((X[:, j] - X[:, j].mean()) ** 2).sum() return 1 / (1 - r2)

Las convenciones habituales sitúan el umbral de preocupación en VIF>5\mathrm{VIF} > 5 o VIF>10\mathrm{VIF} > 10, según la fuente. Son reglas prácticas sin fundamento teórico: lo que importa es la comparación con la magnitud del efecto que se pretende estimar.

Qué hacer con la dependencia

Detectada la colinealidad, las respuestas dependen del objetivo.

Si el interés está en predecir, la colinealidad no impide un buen ajuste: el modelo alcanza la misma proyección sobre el espacio columna, como estableció la lección anterior. La regularización L2 estabiliza los coeficientes al seleccionar el representante de norma mínima, y las predicciones apenas se resienten.

Si el interés está en interpretar los coeficientes, la colinealidad es un obstáculo real y no hay técnica que lo elimine: los datos no contienen la información necesaria para separar los efectos. Las alternativas son eliminar columnas redundantes, combinarlas en un índice, o recoger datos en los que las variables varíen de forma independiente.

La reducción de dimensionalidad por componentes principales resuelve el problema numérico por construcción, ya que sus direcciones son ortogonales, pero a costa de la interpretabilidad: cada componente es una combinación de todas las variables originales.


Ejercicio. Construir una matriz 8×38\times 3 cuya tercera columna sea la suma de las dos primeras más un ruido de escala ε\varepsilon, y representar VIF3\mathrm{VIF}_3 frente a ε\varepsilon para ε{1,101,102,103}\varepsilon \in \{1, 10^{-1}, 10^{-2}, 10^{-3}\}. Comprobar que matrix_rank devuelve 33 en los cuatro casos y explicar por qué ese resultado no contradice lo observado.