Возьмите 20 случайных точек в 10000-мерном пространстве с каждой координатой из . Разделите их на 10 пар («пары») и добавьте среднее значение каждой пары («ребенок») к набору данных. Затем проведите PCA по полученным 30 точкам и постройте график PC1 против PC2.
Происходит замечательная вещь: каждая «семья» образует тройку точек, которые все близко друг к другу. Конечно, каждый ребенок находится ближе к каждому из своих родителей в первоначальном пространстве 10 000 измерений, поэтому можно ожидать, что он будет близок к родителям также в пространстве PCA. Однако в пространстве PCA каждая пара родителей также находится близко друг к другу, хотя в исходном пространстве они являются просто случайными точками!
Как детям удается сплотить родителей в прогнозе PCA?
Можно опасаться, что это как-то зависит от того факта, что дети имеют более низкую норму, чем родители. Кажется, это не имеет значения: если я произвожу детей как гдеиявляются родительскими точками, тогда они будут иметь в среднем ту же норму, что и родители. Но я все еще наблюдаю качественно такое же явление в пространстве PCA:
Этот вопрос использует игрушечный набор данных, но он мотивирован тем, что я наблюдал в реальном наборе данных из исследования ассоциации всего генома (GWAS), где измерения представляют собой однонуклеотидный полиморфизм (SNP). Этот набор данных содержал трио мать-отец-ребенок.
Код
%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')
Ответы:
Во время обсуждения с @ttnphns в комментариях выше, я понял, что такое же явление можно наблюдать со многими менее чем 10 семействами. Три семейства (
n=3
в моем фрагменте кода) появляются примерно в углах равностороннего треугольника. Фактически, достаточно рассмотреть только два семейства (n=2
): они в конечном итоге разделены вдоль ПК1, причем каждое семейство проецируется примерно на одну точку.Случай двух семей можно визуализировать напрямую. Первоначальные четыре точки в 10000-мерном пространстве почти ортогональны и находятся в 4-мерном подпространстве. Таким образом, они образуют 4-симплекс. После центрирования они сформируют правильный тетраэдр, который имеет форму в 3D. Вот как это выглядит:
Перед добавлением детей PC1 может указывать куда угодно; нет предпочтительного направления. Тем не менее, после того, как двое детей расположены в центрах двух противоположных ребер, PC1 пройдет через них! Это расположение из шести пунктов было описано @ttnphns как «гантель»:
Обратите внимание, что противоположные ребра правильного тетраэдра ортогональны друг другу, а также ортогональны линии, соединяющей их центры. Это означает, что каждая семья будет проецироваться на одну точку на ПК1.
источник