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')
Respuestas:
Durante la discusión con @ttnphns en los comentarios anteriores, me di cuenta de que se puede observar el mismo fenómeno con muchas menos de 10 familias. Tres familias (
n=3
en mi fragmento de código) aparecen aproximadamente en las esquinas de un triángulo equilátero. De hecho, es suficiente considerar solo dos familias (n=2
): terminan separadas a lo largo de PC1, con cada familia proyectada aproximadamente en un punto.El caso de dos familias se puede visualizar directamente. Los cuatro puntos originales en el espacio de 10.000 dimensiones son casi ortogonales y residen en un subespacio de 4 dimensiones. Entonces forman un 4-simplex. Después de centrar, formarán un tetraedro regular que es una forma en 3D. Así es como se ve:
Antes de agregar a los niños, PC1 puede apuntar a cualquier parte; No hay una dirección preferida. Sin embargo, después de que dos niños se colocan en el centro de dos bordes opuestos, ¡PC1 los atravesará! @Ttnphns describió esta disposición de seis puntos como una "mancuerna":
Tenga en cuenta que los bordes opuestos de un tetraedro regular son ortogonales entre sí y también son ortogonales a la línea que conecta sus centros. Esto significa que cada familia se proyectará en un solo punto en PC1.
Quizás incluso de manera menos intuitiva, si los dos niños son escalados por el factor para darles la misma norma que los padres, entonces "sobresaldrán" del tetraedro, resultando en la proyección de PC1 con ambos padres colapsados juntos y el niño está más alejado. Esto se puede ver en la segunda figura en mi pregunta: cada familia tiene sus padres muy cerca en el avión PC1 / PC2 (¡AUNQUE ESTÁN SIN RELACIÓN!), Y su hijo está un poco más alejado.2-√
fuente