46. Álgebra lineal aplicada a ciencia de datos

Una tabla de datos es una matriz: sus filas representan observaciones y sus columnas, variables. Esta perspectiva permite limpiar, transformar, resumir y modelar información con operaciones algebraicas.

46.1 Introducción

La ciencia de datos busca obtener conocimiento a partir de observaciones. El álgebra lineal ofrece un lenguaje común para representar conjuntos de datos y ejecutar cálculos sobre muchas observaciones a la vez.

datos ⟶ preparación ⟶ exploración ⟶ modelo ⟶ evaluación

Una buena representación matricial facilita tanto el razonamiento matemático como la implementación eficiente.

46.2 La matriz de datos

Una convención frecuente coloca n observaciones en las filas y p variables en las columnas. La matriz X tiene entonces dimensión n × p.

Xij = valor de la variable j en la observación i
const columnas = ["edad", "horasEstudio", "nota"];
const X = [
  [20, 5, 7.5],
  [22, 8, 9.0],
  [19, 3, 6.0]
];

console.log({ observaciones: X.length, variables: X[0].length });
console.log(columnas[2], X[1][2]); // nota 9

46.3 Vectores de observaciones y variables

Cada fila de X es un vector que describe una observación. Cada columna reúne los valores de una variable para toda la muestra.

function columna(matriz, indice) {
  return matriz.map(fila => fila[indice]);
}

const X = [[20, 5], [22, 8], [19, 3]];
console.log(X[0]);          // primera observación: [20, 5]
console.log(columna(X, 1)); // segunda variable: [5, 8, 3]

Definir y documentar la orientación evita errores al multiplicar matrices o utilizar bibliotecas con convenciones diferentes.

46.4 Codificación de variables categóricas

Las categorías no deben convertirse en números ordinales si no existe un orden real. La codificación one-hot crea una columna indicadora por categoría.

rojo → (1, 0, 0)    verde → (0, 1, 0)    azul → (0, 0, 1)
function oneHot(valores) {
  const categorias = [...new Set(valores)];
  return {
    categorias,
    matriz: valores.map(valor => categorias.map(c => Number(c === valor)))
  };
}

console.log(oneHot(["rojo", "azul", "rojo", "verde"]));

Con muchas categorías pueden preferirse representaciones dispersas para no almacenar una gran cantidad de ceros.

46.5 Datos faltantes

Los valores ausentes pueden eliminarse o imputarse según su origen y proporción. Una opción sencilla es reemplazarlos por la media o la mediana calculada con los datos disponibles.

function imputarMedia(valores) {
  const presentes = valores.filter(Number.isFinite);
  const media = presentes.reduce((s, x) => s + x, 0) / presentes.length;
  return valores.map(x => Number.isFinite(x) ? x : media);
}

console.log(imputarMedia([10, NaN, 14, 12])); // [10, 12, 14, 12]

La imputación introduce supuestos y puede reducir artificialmente la variabilidad. Conviene registrar qué valores fueron imputados.

46.6 Centrado de datos

Centrar una variable consiste en restar su media. Geométricamente, se traslada la nube de puntos para que su centro quede en el origen.

Xc = X − 1μT
function centrar(X) {
  const medias = X[0].map((_, j) =>
    X.reduce((s, fila) => s + fila[j], 0) / X.length
  );
  return { medias, datos: X.map(fila => fila.map((x, j) => x - medias[j])) };
}

console.log(centrar([[1, 10], [2, 20], [3, 30]]));

46.7 Estandarización

Cuando las variables utilizan escalas distintas, se suele restar la media y dividir por la desviación estándar.

z = (x − μ)/σ
function estandarizar(valores) {
  const media = valores.reduce((s, x) => s + x, 0) / valores.length;
  const varianza = valores.reduce((s, x) => s + (x - media) ** 2, 0) /
    valores.length;
  const desviacion = Math.sqrt(varianza);
  return valores.map(x => desviacion === 0 ? 0 : (x - media) / desviacion);
}

console.log(estandarizar([10, 20, 30]));

La elección entre desviación poblacional o muestral debe ser consistente. Una columna constante se transforma normalmente en ceros.

46.8 Matriz de covarianza

La covarianza mide cómo varían conjuntamente dos variables. Si Xc está centrada, la matriz de covarianza muestral es:

S = XcTXc/(n − 1)
function covarianza(x, y) {
  const mx = x.reduce((s, v) => s + v, 0) / x.length;
  const my = y.reduce((s, v) => s + v, 0) / y.length;
  return x.reduce((s, v, i) => s + (v - mx) * (y[i] - my), 0) /
    (x.length - 1);
}

console.log(covarianza([1, 2, 3], [2, 4, 6])); // 2

S es simétrica; su diagonal contiene las varianzas de las variables.

46.9 Correlación

La correlación de Pearson normaliza la covarianza y produce un valor entre −1 y 1.

rxy = cov(x, y)/(sxsy)
function correlacion(x, y) {
  const media = v => v.reduce((s, n) => s + n, 0) / v.length;
  const mx = media(x), my = media(y);
  const productos = x.reduce((s, n, i) => s + (n - mx) * (y[i] - my), 0);
  const sx = Math.sqrt(x.reduce((s, n) => s + (n - mx) ** 2, 0));
  const sy = Math.sqrt(y.reduce((s, n) => s + (n - my) ** 2, 0));
  return productos / (sx * sy);
}

console.log(correlacion([1, 2, 3], [2, 4, 6])); // 1

Correlación no implica causalidad y solo resume asociación lineal. Los valores atípicos pueden modificarla mucho.

46.10 Distancias y similitudes

La distancia euclídea compara observaciones en el espacio de variables. La similitud coseno compara sus direcciones.

MedidaUso frecuente
EuclídeaVariables numéricas en escalas comparables
ManhattanDistancias por ejes y mayor robustez
CosenoTextos y vectores de alta dimensión
MahalanobisVariables correlacionadas
const euclidea = (a, b) => Math.hypot(...a.map((x, i) => x - b[i]));
const manhattan = (a, b) => a.reduce((s, x, i) => s + Math.abs(x - b[i]), 0);

console.log(euclidea([1, 2], [4, 6]));  // 5
console.log(manhattan([1, 2], [4, 6])); // 7

46.11 Componentes principales

El análisis de componentes principales (PCA) encuentra direcciones ortogonales de máxima varianza. Los autovectores de la matriz de covarianza dan las direcciones y sus autovalores, la varianza explicada.

Svi = λivi
λ1 ≥ λ2 ≥ ... ≥ 0

En la práctica también puede calcularse PCA mediante la SVD de la matriz centrada, lo cual suele ser numéricamente conveniente.

const autovalores = [7, 2, 1];
const total = autovalores.reduce((s, x) => s + x, 0);
const proporcion = autovalores.map(x => x / total);
const acumuladaDos = proporcion[0] + proporcion[1];

console.log(proporcion);   // [0.7, 0.2, 0.1]
console.log(acumuladaDos); // 0.9

46.12 Proyección y reducción dimensional

Elegidos k componentes, cada observación centrada se proyecta sobre ellos. Si W contiene los componentes como columnas:

Z = XcW

Z tiene k columnas y conserva tanta variación como permitan los componentes seleccionados.

function proyectar(vector, componentes) {
  return componentes.map(componente =>
    vector.reduce((s, valor, i) => s + valor * componente[i], 0)
  );
}

const componentes = [[1 / Math.sqrt(2), 1 / Math.sqrt(2)], [0, 1]];
console.log(proyectar([2, 4], componentes));

PCA ayuda a visualizar y comprimir datos, pero sus componentes pueden ser difíciles de interpretar y no utilizan la variable objetivo.

46.13 Regresión lineal como producto matricial

La regresión lineal predice una variable y mediante una combinación de características:

ŷ = Xβ

Para incorporar un término independiente se agrega una columna de unos a X.

function predecir(fila, coeficientes) {
  return fila.reduce((s, x, i) => s + x * coeficientes[i], 0);
}

const beta = [10, 2.5, -1]; // intercepto y dos pendientes
const observacion = [1, 4, 3];
console.log(predecir(observacion, beta)); // 17

46.14 Ajuste por mínimos cuadrados

Los coeficientes se eligen para minimizar la suma de los residuos al cuadrado:

minimizar ||Xβ − y||2

Si X tiene columnas linealmente independientes, las ecuaciones normales son XTXβ = XTy. QR o SVD suelen ser más estables que calcular una inversa explícita.

function errorMedioCuadratico(reales, predichos) {
  return reales.reduce((s, y, i) => s + (y - predichos[i]) ** 2, 0) /
    reales.length;
}

console.log(errorMedioCuadratico([3, 5, 7], [2.8, 5.2, 6.9]));
// 0.03

46.15 Regularización

Cuando hay muchas variables, colinealidad o sobreajuste, la regresión ridge penaliza coeficientes grandes:

minimizar ||Xβ − y||2 + λ||β||2
(XTX + λI)β = XTy

Normalmente no se penaliza el intercepto. Las variables deben estar en escalas comparables para que la penalización sea justa.

function penalizacionRidge(coeficientes, lambda, incluyeIntercepto = true) {
  const inicio = incluyeIntercepto ? 1 : 0;
  return lambda * coeficientes.slice(inicio)
    .reduce((s, beta) => s + beta ** 2, 0);
}

console.log(penalizacionRidge([10, 2, -3], 0.5)); // 6.5

46.16 Agrupamiento con k-means

k-means alterna entre asignar cada observación al centroide más cercano y recalcular cada centroide como la media de su grupo.

asignar ⟶ promediar ⟶ repetir hasta estabilizar
function centroide(puntos) {
  return puntos[0].map((_, j) =>
    puntos.reduce((s, punto) => s + punto[j], 0) / puntos.length
  );
}

console.log(centroide([[1, 2], [3, 4], [5, 6]])); // [3, 4]

El resultado depende de la escala, la inicialización y k. El método funciona mejor con grupos aproximadamente compactos y esféricos.

46.17 Factorización y sistemas de recomendación

Una matriz R de usuarios por productos suele contener pocas calificaciones. La factorización de bajo rango aproxima R mediante dos matrices pequeñas:

R ≈ UVT

Las filas de U representan preferencias latentes de usuarios y las filas de V, propiedades latentes de productos. Su producto escalar estima una calificación.

function calificacionEstimada(usuario, producto) {
  return usuario.reduce((s, valor, i) => s + valor * producto[i], 0);
}

const usuario = [0.8, 0.1, 0.6];
const pelicula = [4.5, 1.0, 3.8];
console.log(calificacionEstimada(usuario, pelicula)); // 5.98

46.18 Evaluación, fuga de datos y estabilidad

Los datos se separan en entrenamiento, validación y prueba. Medias, desviaciones, componentes principales e imputaciones deben aprenderse solo con entrenamiento y luego aplicarse sin reajustar a los demás conjuntos.

dividir primero ⟶ ajustar transformaciones con entrenamiento ⟶ transformar ⟶ evaluar

Calcular transformaciones con todo el conjunto produce fuga de datos y una evaluación demasiado optimista.

También deben vigilarse valores atípicos, columnas redundantes, escalas incompatibles, matrices mal condicionadas y conjuntos sin representatividad. Para datos grandes se utilizan matrices dispersas, operaciones por bloques y bibliotecas numéricas optimizadas.

function transformarConEntrenamiento(valores, mediaTrain, desvioTrain) {
  return valores.map(x => (x - mediaTrain) / desvioTrain);
}

const prueba = [12, 18];
console.log(transformarConEntrenamiento(prueba, 10, 4)); // [0.5, 2]

46.19 Qué debes recordar de este tema

  • Una matriz de datos suele organizar observaciones por filas y variables por columnas.
  • Centrar traslada los datos; estandarizar también ajusta sus escalas.
  • La covarianza y la correlación describen relaciones lineales entre variables.
  • Las distancias dependen de la representación y la escala elegidas.
  • PCA proyecta datos sobre direcciones ortogonales de máxima varianza.
  • La regresión lineal expresa predicciones mediante ŷ = Xβ.
  • La regularización ayuda a controlar coeficientes y sobreajuste.
  • k-means utiliza distancias y medias para formar grupos.
  • Las factorizaciones de bajo rango revelan estructuras latentes.
  • Todo preprocesamiento debe aprenderse únicamente con los datos de entrenamiento.

46.20 Conclusión

El álgebra lineal convierte tablas en objetos matemáticos que pueden compararse, proyectarse, descomponerse y modelarse. Comprender estas operaciones permite interpretar mejor los métodos y detectar cuándo sus supuestos no se cumplen.

En el próximo tema veremos cómo estas mismas herramientas sostienen modelos de inteligencia artificial y el aprendizaje de sus parámetros.