Prendi 20 punti casuali in uno spazio di 10.000 dimensioni con ciascuna coordinata iid da . Dividili in 10 coppie ("coppie") e aggiungi la media di ciascuna coppia ("un figlio") al set di dati. Quindi esegui PCA sui 30 punti risultanti e traccia il PC1 contro il PC2.
Accade una cosa notevole: ogni "famiglia" forma una tripletta di punti che sono tutti vicini. Naturalmente ogni bambino è più vicino a ciascuno dei suoi genitori nello spazio originale di 10.000 dimensioni, quindi ci si potrebbe aspettare che sia vicino ai genitori anche nello spazio PCA. Tuttavia, nello spazio PCA ogni coppia di genitori è anche vicina, anche se nello spazio originale sono solo punti casuali!
In che modo i bambini riescono a riunire i genitori nella proiezione PCA?
Si potrebbe temere che ciò sia in qualche modo influenzato dal fatto che i bambini hanno una norma inferiore rispetto ai genitori. Questo non sembra avere importanza: se produco i bambini come dove ed sono i punti dei genitori, poi si avrà, in media, la stessa norma, come i genitori. Ma osservo ancora qualitativamente lo stesso fenomeno nello spazio PCA:
Questa domanda utilizza un set di dati giocattolo, ma è motivata da ciò che ho osservato in un set di dati del mondo reale da uno studio di associazione sul genoma (GWAS) in cui le dimensioni sono polimorfismi a singolo nucleotide (SNP). Questo set di dati conteneva trii madre-padre-figlio.
Codice
%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')