python построение собственных векторов - PullRequest
1 голос
/ 23 января 2020

Я думал, что собственные векторы должны быть ортогональны друг другу. Следующее, кажется, нарушает это. Я хотел проверить, делаю ли я что-то не так. Спасибо за понимание !!!

Вот код для PCA (данные внизу поста)

from numpy import array
from numpy import mean
from numpy import cov
from numpy.linalg import eig


#calculate the mean of each column
M = mean(df.T, axis=1)

# center columns by subtracting column means
C = df - M

# calculate covariance matrix of centered matrix
V = cov(df.T)

# eigendecomposition of covariance matrix
values, vectors = eig(V)

# project data
P = vectors.T.dot(C.T)

#Make a list of (eigenvalue, eigenvector) tuples
eig_pairs = [(np.abs(values[i]), vectors[:,i]) for i in range(len(values))]

# Sort the (eigenvalue, eigenvector) tuples from high to low
eig_pairs.sort(key=lambda x: x[0], reverse=True)


matrix_w = np.hstack((eig_pairs[0][1].reshape(20,1), eig_pairs[1][1].reshape(20,1)))
#print('Matrix W:\n', matrix_w)

Все, что я сделал здесь, чтобы построить собственные векторы, - это взять первые два строки из matrix_w. Это правильно? Я просто вручную ввел их в массив M. Неправильный ли мой matrix_w или неправильный выбор вектора для первых двух основных компонентов?

M =  np.array([[0.00747255,  0.16222854],[-0.18394907,  0.12426324]])
rows,cols = M.T.shape

#Get absolute maxes for axis ranges to center origin
maxes = 1.1*np.amax(abs(M), axis = 0)

for i,l in enumerate(range(0,cols)):
    xs = [0,M[i,0]]
    ys = [0,M[i,1]]
    plt.plot(xs,ys)

plt.plot(0,0,'ok') #<-- plot a black point at the origin
plt.axis('equal')  #<-- set the axes to the same scale

plt.legend(['V'+str(i+1) for i in range(cols)]) #<-- give a legend
plt.grid(b=True, which='major') #<-- plot grid lines
plt.show()```

Вот как выглядят построенные векторы, но они не ортогональны.

enter image description here

Вот данные (уже нормализованные np.log):

[[1.954242509439325,
  1.6901960800285136,
  1.9444826721501687,
  1.2787536009528289,
  1.7558748556724915,
  1.7075701760979363,
  1.2787536009528289,
  1.3222192947339193,
  1.4313637641589874,
  1.3222192947339193,
  1.9084850188786497,
  1.8750612633917,
  1.6434526764861874,
  1.8512583487190752,
  1.3424226808222062,
  1.9590413923210936,
  1.9294189257142926,
  1.8692317197309762,
  1.4771212547196624,
  1.414973347970818],
 [1.9138138523837167,
  1.0,
  1.7781512503836436,
  0.3010299956639812,
  1.7403626894942439,
  1.6127838567197355,
  0.47712125471966244,
  0.3010299956639812,
  0.6020599913279624,
  0.3010299956639812,
  1.8260748027008264,
  1.8512583487190752,
  0.9542425094393249,
  1.662757831681574,
  1.9030899869919435,
  1.8195439355418688,
  1.380211241711606,
  1.9731278535996986,
  0.6989700043360189,
  1.255272505103306],
 [1.9444826721501687,
  1.6232492903979006,
  1.7993405494535817,
  0.6020599913279624,
  1.8808135922807914,
  1.724275869600789,
  1.0413926851582251,
  1.3617278360175928,
  1.0413926851582251,
  0.6989700043360189,
  1.9395192526186185,
  1.9242792860618816,
  1.6020599913279623,
  1.6532125137753437,
  1.9444826721501687,
  1.9731278535996986,
  1.6720978579357175,
  1.5563025007672873,
  1.7558748556724915,
  0.47712125471966244],
 [1.9822712330395684,
  1.792391689498254,
  1.9912260756924949,
  1.505149978319906,
  1.792391689498254,
  1.8260748027008264,
  1.6334684555795864,
  0.8450980400142568,
  1.146128035678238,
  1.146128035678238,
  1.919078092376074,
  1.9493900066449128,
  1.7853298350107671,
  1.9084850188786497,
  1.1760912590556813,
  1.4913616938342726,
  1.9867717342662448,
  1.1139433523068367,
  1.724275869600789,
  1.1760912590556813],
 [1.9731278535996986,
  1.5797835966168101,
  1.6812412373755872,
  1.0413926851582251,
  1.8692317197309762,
  1.568201724066995,
  1.3617278360175928,
  0.9542425094393249,
  1.1139433523068367,
  1.0791812460476249,
  1.8808135922807914,
  1.8808135922807914,
  1.6232492903979006,
  1.7558748556724915,
  1.462397997898956,
  1.9242792860618816,
  1.9030899869919435,
  1.919078092376074,
  1.3010299956639813,
  0.6989700043360189],
 [1.9867717342662448,
  1.7853298350107671,
  1.9344984512435677,
  1.4471580313422192,
  1.8976270912904414,
  1.863322860120456,
  1.0791812460476249,
  0.8450980400142568,
  1.414973347970818,
  1.3617278360175928,
  1.9294189257142926,
  1.9731278535996986,
  1.919078092376074,
  1.3010299956639813,
  1.9590413923210936,
  1.9731278535996986,
  1.9731278535996986,
  1.9242792860618816,
  1.4913616938342726,
  1.380211241711606],
 [1.4313637641589874,
  1.9344984512435677,
  1.99563519459755,
  1.3424226808222062,
  1.9590413923210936,
  1.7403626894942439,
  1.8808135922807914,
  1.2304489213782739,
  1.3010299956639813,
  1.380211241711606,
  1.8808135922807914,
  1.8325089127062364,
  1.9493900066449128,
  1.9590413923210936,
  1.0413926851582251,
  1.9777236052888478,
  1.9731278535996986,
  1.7558748556724915,
  1.0413926851582251,
  1.4471580313422192],
 [1.8573324964312685,
  1.414973347970818,
  1.8864907251724818,
  0.3010299956639812,
  1.3424226808222062,
  1.5314789170422551,
  0.0,
  0.6989700043360189,
  1.3010299956639813,
  0.47712125471966244,
  1.3424226808222062,
  1.7075701760979363,
  0.9030899869919435,
  1.2041199826559248,
  1.9493900066449128,
  1.8129133566428555,
  1.8920946026904804,
  1.9637878273455553,
  0.7781512503836436,
  0.9542425094393249],
 [1.7403626894942439,
  1.4913616938342726,
  1.7853298350107671,
  1.1760912590556813,
  1.462397997898956,
  1.5185139398778875,
  0.0,
  0.6989700043360189,
  1.1760912590556813,
  1.0413926851582251,
  1.6901960800285136,
  1.6232492903979006,
  1.146128035678238,
  1.6127838567197355,
  1.7075701760979363,
  1.7075701760979363,
  1.8573324964312685,
  1.4471580313422192,
  1.1139433523068367,
  1.0413926851582251],
 [1.863322860120456,
  1.8573324964312685,
  1.9294189257142926,
  1.3979400086720377,
  1.4913616938342726,
  1.8388490907372552,
  1.0,
  1.2304489213782739,
  1.2787536009528289,
  1.1760912590556813,
  1.8976270912904414,
  1.845098040014257,
  1.662757831681574,
  1.7853298350107671,
  1.806179973983887,
  1.9138138523837167,
  1.6812412373755872,
  1.7853298350107671,
  1.6812412373755872,
  1.4771212547196624],
 [1.9822712330395684,
  1.2304489213782739,
  1.9637878273455553,
  1.5440680443502757,
  1.8195439355418688,
  1.505149978319906,
  1.2304489213782739,
  1.0413926851582251,
  1.7075701760979363,
  1.6232492903979006,
  1.9084850188786497,
  1.8573324964312685,
  1.6989700043360187,
  1.806179973983887,
  1.0413926851582251,
  1.9637878273455553,
  1.9590413923210936,
  1.4771212547196624,
  1.0413926851582251,
  1.5314789170422551],
 [1.9637878273455553,
  1.2304489213782739,
  1.919078092376074,
  1.1139433523068367,
  1.792391689498254,
  1.7075701760979363,
  0.6020599913279624,
  1.2304489213782739,
  1.4771212547196624,
  1.1760912590556813,
  1.7853298350107671,
  1.8573324964312685,
  1.5314789170422551,
  1.7075701760979363,
  1.0413926851582251,
  1.7993405494535817,
  1.9731278535996986,
  1.4471580313422192,
  0.3010299956639812,
  1.792391689498254],
 [1.4771212547196624,
  1.7160033436347992,
  1.99563519459755,
  1.0413926851582251,
  1.9030899869919435,
  1.8750612633917,
  1.255272505103306,
  0.3010299956639812,
  0.6989700043360189,
  0.47712125471966244,
  1.7558748556724915,
  1.7160033436347992,
  1.662757831681574,
  1.9493900066449128,
  0.6989700043360189,
  1.9867717342662448,
  1.3979400086720377,
  1.4913616938342726,
  0.47712125471966244,
  0.9542425094393249]]

df = pd.DataFrame(data, columns=['Real coffee', 'Instant coffee', 'Tea', 'Sweetener', 'Biscuits',
       'Powder soup', 'Tin soup', 'Potatoes', 'Frozen fish', 'Frozen veggies',
       'Apples', 'Oranges', 'Tinned fruit', 'Jam', 'Garlic', 'Butter',
       'Margarine', 'Olive oil', 'Yoghurt', 'Crisp bread'])

1 Ответ

0 голосов
/ 24 января 2020

Простая проверка ортогональности двух векторов состоит в том, чтобы увидеть, есть ли там произведение точек на ноль. В вашем случае ортогональные векторы должны быть столбцами vectors (т.е. собственными векторами ковариационной матрицы). Например, следующее должно выполняться без появления ошибки

n, m = vectors.shape
for col_i in range(m):
    for col_j in range(m):
        if col_i < col_j:  # use strictly less than because we don't want to consider a column with itself, and the dot product is commutable so order doesn't matter
            is_orthogonal = np.dot(vectors[:, col_i], vectors[:, col_j])
            if not np.isclose(is_orthogonal, 0):
                raise ValueError(f"Eigenvector {col_i} and Eigenvector {col_j} are not orthogonal.")

Более быстрый способ - помнить, что произведение матрицы - это просто произведение точек строк первой матрицы со столбцами второй, т.е. vectors.T @ vectors. Затем мы хотим проверить, что нижний треугольник этого результата, исключая диагональ (для тех же значений, что и if col_i < col_j в l oop), равны нулю:

np.all(np.isclose(np.tril(vec.T @ vec, -1), 0))

Это должно вернуть True

Причина, по которой ваш график не выглядит ортогональным, заключается в том, что вы взяли два 20D-вектора и произвольно спроецировали их до 2D. Когда вы делаете это, нет никакой гарантии, что они останутся ортогональными. В качестве примера рассмотрим общую диаграмму оси xyz:

enter image description here

Вы знаете, что ось z ортогональна оси x, но если вы проецируете ее вплоть до 2D, угол, который вы видите, зависит от угла проекции и больше не является ортогональным.

...