Машинное обучение имеет широкий спектр методов уменьшения размерности. Это один из самых важных аспектов в области науки о данных. В результате в этой статье я представлю один из наиболее важных методов уменьшения размерности, используемых сегодня, известный как анализ главных компонентов (PCA).

Но сначала нам нужно понять, что такое уменьшение размерности и почему оно так важно.

Уменьшение размерности

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

Почему это полезно?

Работа с многомерными пространствами может быть неудобной по ряду причин, включая тот факт, что необработанные данные часто расплывчаты из-за проклятия размерности, а обработка данных обычно требует больших вычислительных ресурсов.
Уменьшение размерности популярно. в таких областях, как обработка сигналов, распознавание голоса, нейроинформатика и биоинформатика, которые имеют дело с огромным количеством наблюдений и / или переменных.

Анализ главных компонентов

Линия «наилучшего соответствия» в двух, трех или более крупных измерениях может быть определена как линия, которая минимизирует средний квадрат перпендикулярного расстояния от точки до линии. Вторую наиболее подходящую линию можно выбрать таким же образом из перпендикулярных направлений к первой. Если вам это кажется бессмысленным, не волнуйтесь, мы подробно рассмотрим эти вещи в этом посте.

Зеленые точки - это фактические точки, а синие точки - это проецируемые точки.
Для начала PCA определяет направление (вектор u⁽¹⁾ ∈ ℝⁿ), на которое будут проецироваться данные, чтобы минимизировать ошибку проекции. Расстояние показано розовыми линиями на рисунке выше. PCA выбирает линию в направлении с наименьшей квадратичной ошибкой, которая определяется расстоянием между выбранной линией и точкой. Мы также можем сделать вывод из предыдущего рисунка, что оранжевая линия является худшей линией, поскольку расстояние между точками и линией велико. Здесь также можно выбрать отрицательное направление, но здесь и положительное, и отрицательное направление попадают в одну линию.

В общем, сокращение от n-мерного до k-мерного: найдите k векторов u⁽¹⁾, u⁽²⁾,…., U⁽ᵐ⁾, на которые нужно проецировать данные, чтобы минимизировать ошибку проекции.

Чтобы помочь вам понять, мы сначала поэкспериментируем с примером 2D-набора данных, чтобы получить интуитивное представление о том, как работает PCA, а затем используем его в более крупном наборе данных.

Давайте загрузим наш образец набора данных и очень быстро визуализируем его:

mat3 = loadmat('ex7data1.mat')
X3 = mat3['X']
plt.scatter(X3[:, 0], X3[:, 1], alpha=0.5)

Перед использованием наших данных нам необходимо их нормализовать. В этом посте я не буду углубляться в нормализацию. Чтобы узнать больше о нормализации нажмите здесь.

def featureNormalize(X):
    
    mu = np.mean(X, axis=0)
    sigma = np.std(X, axis=0)
    X_norm = (X - mu)/sigma
    
    return X_norm, mu, sigma

Алгоритм PCA

1. Вычислить ковариационную матрицу.

Мера связи между двумя переменными - ковариация. Он определяет, насколько две переменные отличаются от своих средних значений. Это может помочь нам понять, как связаны две переменные.

Ковариационная матрица представлена ​​греческой буквой (сигма) в приведенном выше уравнении, что отличается от суммирования. Умножая x⁽ⁱ⁾ и x⁽ⁱ⁾ на транспонирование, мы можем получить ковариационную матрицу.

2. Вычислить собственные векторы.

Подробное объяснение собственных значений и собственных векторов сделало бы эту статью слишком длинной, я просто воспользуюсь методом numpy svd (). Однако для вашего удобства я оставлю процесс вычисления собственных значений и собственных векторов в конце статьи. Просто собственные значения и собственные векторы помогут нам найти направление проекции линии PCA. Нажмите здесь, чтобы узнать больше о собственных значениях и собственных векторах. Здесь U - это набор векторов u⁽¹⁾, u⁽²⁾,…., U⁽ᵐ⁾, на которые проецируются данные.

После использования svd () мы получаем U как указанную выше матрицу. Возвращенная U-матрица состоит из направлений для n-мерности, нам нужно выбрать k, чтобы уменьшить n-размерную матрицу до k-размерности. k-мерная матрица называется U_reduce.

Мы можем получить Z, который является уменьшенной размерностью, умножив U_reduce transpose на X, что уменьшит x⁽ⁱ⁾ размера (n x 1) до (k x 1).

Мы можем приблизительно вернуть наши исходные данные (X≈Xₐₚₚᵣₒₓ = U_reduce ⋅ Z), умножив U_reduce на Z. Исходные данные и приблизительные данные будут выглядеть, как на следующем рисунке:

def PCA(X):
    m, n = X.shape
    cov_matrix = 1/m * X.T @ X
    U, S, V = np.linalg.svd(cov_matrix)
    return U, S, V
X_norm, mu, sigma = featureNormalize(X3)
U, S, V = PCA(X_norm)

plt.scatter(X3[:, 0], X3[:, 1], alpha=0.5)
plt.plot([mu[0], (mu + 1.5 * S[0] * U[:, 0].T)[0]], [mu[1], (mu + 1.5 * S[0] * U[:, 0].T)[1]], color="black", linewidth=3)
plt.plot([mu[0], (mu + 1.5 * S[1] * U[:, 1].T)[0]], [mu[1], (mu + 1.5 * S[1] * U[:, 1].T)[1]], color="black", linewidth=3)
plt.xlim(-1,7)
plt.ylim(2,8)

def projectData(X, U, K):
    
    m = X.shape[0]
    Z = np.zeros((m, K))
    for i in range(m):
        for j in range(K):
            projection_k = X[i, :] @ U[:, j] #x @ U_reduce
            Z[i, j] = projection_k
    return Z
K=1
Z = projectData(X_norm, U, K)
def recoverData(Z, U, K):
    z = Z.shape[0]
    u = U.shape[0]
    X_rec = np.zeros((z, u))
    
    for i in range(z):
        for j in range(u):
            X_rec[i, j] = Z[i, :] @ U[j, :K]
    return X_rec
X_rec  = recoverData(Z, U, K)
plt.scatter(X_norm[:,0],X_norm[:,1],marker="o",label="Original",facecolors="none",edgecolors="b",s=15)
plt.scatter(X_rec[:,0],X_rec[:,1],marker="o",label="Approximation",facecolors="none",edgecolors="r",s=15)
plt.title("The Normalized and Projected Data after PCA")
plt.legend()

Выбор k (количество главных компонентов)

Мы можем выбрать k следующим образом:

Сохраняется 95–99% отклонений - это хорошо и приемлемо.

Применение PCA

  1. Сопоставление x⁽ⁱ⁾ → z⁽ⁱ⁾ должно определяться запуском PCA только на обучающем наборе.
  2. Не используйте PCA для уменьшения количества функций до k. Это может сработать, но это не лучший способ решить проблему переобучения.
  3. Перед внедрением PCA сначала попробуйте выполнить все, что вы хотите делать с необработанными данными. Только если он не делает то, что вы хотите, внедряйте PCA.

Это много алгебры и математики, давайте погрузимся в нашу редукцию размерности на лицах с помощью PCA.

Давайте быстро загрузим и визуализируем наш набор данных:

mat4 = loadmat('ex7faces.mat')
X4 = mat4['X']
fig, ax = plt.subplots(nrows=10,ncols=10,figsize=(8,8))
for i in range(0,100,10):
    for j in range(10):
        ax[int(i/10),j].imshow(X4[i+j,:].reshape(32,32,order="F"),cmap="gray")
        ax[int(i/10),j].axis("off")

Давайте применим PCA к этому набору данных и визуализируем его:

X_norm2, mu2, sigma2 = featureNormalize(X4)
U2, S2, V2 = PCA(X_norm2)
U_reduced = U2[:,:36].T
fig2, ax2 = plt.subplots(6,6,figsize=(8,8))
for i in range(0,36,6):
    for j in range(6):
        ax2[int(i/6),j].imshow(U_reduced[i+j,:].reshape(32,32,order="F"),cmap="gray")
        ax2[int(i/6),j].axis("off")

Давайте уменьшим размер лица с 1024 до 100:

K2 = 100
Z2 = projectData(X_norm2, U2, K2)
print("The projected data Z has a size of:",Z2.shape)
X_rec2  = recoverData(Z2, U2, K2)
fig3, ax3 = plt.subplots(10,10,figsize=(8,8))
for i in range(0,100,10):
    for j in range(10):
        ax3[int(i/10),j].imshow(X_rec2[i+j,:].reshape(32,32,order="F"),cmap="gray")
        ax3[int(i/10),j].axis("off")

Дополнительные примечания к собственным значениям и собственным векторам

Процедура поиска собственных значений и собственных векторов:
1. Найдите характеристическое уравнение.
2. Решите характеристическое уравнение, чтобы получить характеристические корни. Они иначе известны как собственные значения или скрытые корни.
3. Чтобы найти собственные векторы, решите (A-λI) X = 0 для различных значений λ.

Вывод

Сегодня мы узнали, что такое PCA и как он на самом деле работает. Затем он был создан с нуля с использованием Python numpy, pandas и matplotlib. Это более полезно во многих приложениях, которые помогают уменьшить размеры данных с очень низкой потерей данных. Набор данных и окончательный код загружены в Github.

Проверить это можно здесь PCA.

Если вам понравился этот пост, то посмотрите мои предыдущие посты из этой серии о

1. Что такое машинное обучение?

2. Какие бывают типы машинного обучения?

3. Линейная регрессия с одной переменной

4. Многовариантная линейная регрессия

5. Логистическая регрессия

6. Что такое нейронные сети?

7. Классификатор цифр с использованием нейронных сетей

8. Сжатие изображений с кластеризацией K-средних

9. Обнаружение отказавших серверов в сети с помощью обнаружения аномалий

Последняя вещь

Если вам понравилась моя статья, аплодисменты и подписка будут «объединять», и для Medium полезно продвигать эту статью, чтобы другие могли ее прочитать. Я Джагаджит, и я буду поймать вас в следующем.