Ортогональные векторы не строятся ортогонально (PCA в Python) - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь реализовать PCA в Python, но когда я go аннотирую свою фигуру основными осями, оказывается, что мои векторы не ортогональны.

import numpy as np
import matplotlib.pyplot as plt 
import scipy.linalg as LA

N = 1000
xTrue = np.linspace(0, 1000, N)
yTrue = 4 * xTrue
xData = xTrue + np.random.normal(0, 100, N)
yData = yTrue + np.random.normal(0, 100, N)
xData = np.reshape(xData, (N, 1))
yData = np.reshape(yData, (N, 1))
Data = np.hstack((xData, yData))

C = np.cov(Data, rowvar = False)
e_vals, e_vecs = LA.eig(C)
e_vals = np.real(e_vals)
e_vecs = -e_vecs

avg = (1/Data.shape[0] )*sum(Data, 0)

arrowprops = dict(arrowstyle = '->', linewidth = 3, shrinkA = 0, shrinkB = 0, color = 'r')
plt.scatter(Data[:,0], Data[:,1])
plt.title("Principal Component Analysis Example: Linear Data")
for i in [0,1]:
    ax = plt.gca()
    ax.annotate('', avg + np.sqrt(e_vals[i])*e_vecs[:,i], avg, arrowprops = arrowprops)

Я могу убедитесь, что мои собственные векторы ортогональны, показав, что np.matmul(e_vecs, e_vecs.T) - это примерно единичная матрица. Однако изображение, которое я получаю, выглядит следующим образом:

enter image description here

Очевидно, что векторы не являются ортогональными на изображении, но это не имеет смысла, почему они не потому что перевод их через вектор avg не должен был устранить это свойство. Кто-нибудь знает, что с этим не так? Это проблема масштабирования или я пропустил какой-то важный параметр?

1 Ответ

1 голос
/ 04 февраля 2020

Векторы взаимно ортогональны, но при их построении они не выглядят ортогональными из-за масштаба графика (диапазон оси x намного меньше, чем диапазон оси y). Это становится понятным, если для аспекта графика установлено значение 'eqaul' через matplotlib.axes.Axes.set_aspect:

for i in [0,1]:
    ax = plt.gca()
    ax.set_aspect('equal')
    ax.annotate('', avg + np.sqrt(e_vals[i])*e_vecs[:,i], avg, arrowprops = arrowprops)

enter image description here

Конечно, вы можете изменить масштабирование векторов так, чтобы они были визуально ортогональны на наборе осей, для которых аспект не равен, но это в конечном итоге не будет представлять фактические данные. Я бы рекомендовал либо установить аспект на 'equal', используя set_aspect('equal'), как указано выше, либо просто отметить, что векторы ортогональны, но не строятся ортогонально из-за аспекта графика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...