Tome 20 puntos aleatorios en un espacio de 10.000 dimensiones con cada coordenada iid de . Divídalos en 10 pares ("parejas") y agregue el promedio de cada par ("un niño") al conjunto de datos. Luego haga PCA en los 30 puntos resultantes y trace PC1 vs PC2.
Ocurre algo notable: cada "familia" forma un triplete de puntos que están todos juntos. Por supuesto, cada niño está más cerca de cada uno de sus padres en el espacio original de 10.000 dimensiones, por lo que uno podría esperar que esté cerca de los padres también en el espacio de PCA. Sin embargo, en el espacio PCA, cada par de padres también está muy cerca, ¡aunque en el espacio original son solo puntos aleatorios!
¿Cómo logran los niños unir a los padres en la proyección PCA?
Uno podría preocuparse de que esto esté influenciado de alguna manera por el hecho de que los niños tienen una norma más baja que los padres. Esto no parece importar: si produzco a los niños como , donde e son puntos de los padres, entonces tendrán, en promedio, la misma norma, ya que los padres. Pero todavía observo cualitativamente el mismo fenómeno en el espacio PCA:
Esta pregunta está utilizando un conjunto de datos de juguete, pero está motivada por lo que observé en un conjunto de datos del mundo real de un estudio de asociación de genoma completo (GWAS) donde las dimensiones son polimorfismos de un solo nucleótido (SNP). Este conjunto de datos contenía tríos madre-padre-hijo.
Código
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
def generate_families(n = 10, p = 10000, divide_by = 2):
X1 = np.random.randn(n,p) # mothers
X2 = np.random.randn(n,p) # fathers
X3 = (X1+X2)/divide_by # children
X = []
for i in range(X1.shape[0]):
X.extend((X1[i], X2[i], X3[i]))
X = np.array(X)
X = X - np.mean(X, axis=0)
U,s,V = np.linalg.svd(X, full_matrices=False)
X = U @ np.diag(s)
return X
n = 10
plt.figure(figsize=(4,4))
X = generate_families(n, divide_by = 2)
for i in range(n):
plt.scatter(X[i*3:(i+1)*3,0], X[i*3:(i+1)*3,1])
plt.tight_layout()
plt.savefig('families1.png')
plt.figure(figsize=(4,4))
X = generate_families(n, divide_by = np.sqrt(2))
for i in range(n):
plt.scatter(X[i*3:(i+1)*3,0], X[i*3:(i+1)*3,1])
plt.tight_layout()
plt.savefig('families2.png')