La lección anterior estableció que toda aplicación lineal es una matriz y que una aplicación afín no es lineal. Esta desarrolla las consecuencias prácticas de ambas afirmaciones: qué matrices producen las transformaciones habituales del plano, y cómo se incorpora la traslación, que la definición excluye.
El catálogo
Las transformaciones lineales del plano se reducen a unas pocas familias, cada una con su matriz. Los parámetros que las describen determinan por completo su efecto.
det = 1.00
El determinante, de la lección correspondiente, clasifica lo que ocurre. La rotación tiene : conserva áreas y orientación. El escalado elegido aquí también, porque los factores son recíprocos. La reflexión tiene , y el signo negativo es la inversión de la orientación. La proyección tiene , porque aplasta el plano sobre una recta y pierde información de forma irreversible.
La matriz de proyección sobre la recta de ángulo es la de la lección sobre subespacios, con unitario, que desarrollada da
Transformar un conjunto de puntos
Una única matriz transforma cualquier número de puntos. Colocándolos como columnas de una matriz , el producto transforma todos a la vez:
import numpy as np
t = np.pi / 2
R = np.array([[np.cos(t), -np.sin(t)],
[np.sin(t), np.cos(t)]])
P = np.array([[1., 0., 1.],
[0., 1., 1.]]) # tres puntos, como columnas
R @ P
# array([[ 0., -1., -1.],
# [ 1., 0., 1.]])
Aquí aparece una discrepancia de convención que merece explicitarse. En gráficos y en la mayoría de los textos de álgebra lineal, los puntos son columnas y la transformación multiplica por la izquierda: . En aprendizaje automático los ejemplos son filas, como estableció la lección sobre matrices, y la misma operación se escribe .
X = P.T # los mismos puntos, como filas
np.allclose(X @ R.T, (R @ P).T) # True
Ninguna convención es preferible; lo que causa errores es mezclarlas. La comprobación de .shape sigue siendo la manera de saber cuál emplea un código ajeno.
Coordenadas homogéneas
La traslación no es lineal: desplaza el origen, y la lección anterior mostró que es obligatorio. No existe ninguna matriz que traslade el plano.
La solución habitual consiste en trabajar una dimensión más arriba. Un punto se representa como , y la traslación pasa a ser el producto por una matriz :
Esas son las coordenadas homogéneas. La aplicación sigue sin ser lineal en , pero es lineal en restringida al plano . El bloque superior izquierdo contiene la parte lineal y la tercera columna la traslación.
La ganancia es de composición. Con toda transformación afín escrita como una matriz , componerlas es multiplicarlas, y una secuencia arbitraria de rotaciones, escalados y traslaciones se reduce a un único producto. Es lo que hacen las canalizaciones gráficas y las bibliotecas de transformación de imágenes.
La tercera columna contiene la traslación; la tercera fila mantiene el bloque como matriz.
El orden importa, y la figura lo hace evidente. rota alrededor del origen y después desplaza; desplaza primero y rota el resultado alrededor del origen, de modo que la figura describe un arco. La silueta violeta es el orden que no está seleccionado.
La diferencia se lee en la propia matriz. Con y , la tercera columna vale en y en : en el segundo caso la traslación ha sido rotada junto con todo lo demás, porque se aplicó antes.
De ahí sale la receta para rotar alrededor de un punto que no sea el origen, que ninguna matriz puede expresar:
trasladar el centro al origen, rotar, y deshacer la traslación. Se lee de derecha a izquierda, como toda composición.
Aplicación: aumento de datos
El aumento de datos en visión consiste en aplicar transformaciones geométricas aleatorias a las imágenes de entrenamiento, de modo que el modelo aprenda a reconocer un objeto con independencia de su posición, escala u orientación.
def afin_aleatoria(rng, escala=(0.9, 1.1), giro=15, desp=0.1):
t = rng.uniform(-giro, giro) * np.pi / 180
k = rng.uniform(*escala)
c, s = np.cos(t), np.sin(t)
R = np.array([[k * c, -k * s, rng.uniform(-desp, desp)],
[k * s, k * c, rng.uniform(-desp, desp)],
[0., 0., 1.]])
return R
Cada llamada devuelve una matriz , y componer varias transformaciones es multiplicarlas. Las bibliotecas del ámbito trabajan exactamente así, y lo que añaden es la interpolación: aplicar la matriz a la retícula de píxeles produce coordenadas no enteras, y el valor en cada píxel de destino debe estimarse a partir de sus vecinos.
La justificación de la técnica es una hipótesis sobre el problema, no sobre el álgebra: se asume que la etiqueta es invariante bajo esas transformaciones. Rotar un dígito manuscrito no cambia qué dígito es, pero rotarlo puede convertir un en un . El rango de los parámetros codifica esa suposición, y elegirlo mal introduce ejemplos mal etiquetados.
Ejercicio. Construir la matriz que rota alrededor del punto componiendo en coordenadas homogéneas, y comprobar que deja fijo ese punto. Verificar después que el bloque superior izquierdo del producto coincide con y explicar por qué.