Анализ основных компонентов (PCA) — это алгоритм машинного обучения без учителя, который в основном используется для уменьшения размерности данных.
Основы PCA
В качестве примера возьмем двумерную плоскость с 2 элементами, как показано на рисунке:
Горизонтальная ось представляет функцию 1, вертикальная ось представляет функцию 2, а 4 точки представляют двухмерные образцы функций. Если вы хотите уменьшить размер образца до одного измерения, вы можете сопоставить эти точки с горизонтальной осью, вертикальной осью или другими осями следующим образом:
После сопоставления с разными осями расстояние между выборками будет другим, и необходима ось, которая максимизирует расстояние между выборками. Предположим, что это направление оси.
Дисперсия может быть использована для расстояния между образцамиЧтобы измерить, чем больше дисперсия, тем реже выборки.
Затем среднее значение возвращается к обработке 0 (ухудшение), т. е., так что. Обработка среднего возврата к 0 изменяет исходный образец и преобразует его в новый образец.. сопоставьте его с осьюполучить новые образцы, дисперсия в это время составляет:
V ar( X p r )=1 м ∑ i =1 м (X ( i) p r ) 2
так каквектор, поэтому фактическая дисперсия выражается как:
V ar( X p r )=1 м ∑ i =1 м | | X ( i) p r | | 2
окончательный расчет, как показано на рисунке:
(— единичный вектор), поэтому искомая целевая функция получается:
попрошайничествосделатьмаксимум; для многомерных признаков, т.е.максимум.
Метод градиентного подъема решает проблемы PAC
В градиентном восхождении,представляет собойнаправление увеличения.
Для целевой функции PAC: найтисделатьмаксимум, который можно решить с помощью градиентного восхождения.
Градиент:
∇ f = ⎛ ⎝⎜ ⎜⎜ ⎜⎜ ⎜ ∂ f ∂ w 1 ∂ f ∂ w 2 ⋯ ∂ f ∂ wn ⎞ ⎠⎟ ⎟⎟ ⎟⎟ ⎟ = 2 m ⎛ ⎝⎜ ⎜⎜ ⎜⎜ ⎜⎜ (i) 1 w 1 + X (i) 2 w 2 + ... + X (i) nwn) X (i) 1 Σ mi = 1 (X (i) 1 w 1 + X (i) 2 w 2 +... + X (i) nwn) X (i) 2 ⋯ Σ mi = 1 (X (i) 1 w 1 + X (i) 2 w 2 +... + X (i) nwn) X (i) n ⎞ ⎠ ⎟ ⎟ ⎟ ⎟ ⎟ = 2 m ⎛ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ Σ mi = 1 (X (i) w) X (i) 1 Σ mi = 1 (X (i) w) X (i) 2 ⋯ Σ mi = 1 (X (I) w) X (i) n ⎞ ⎠ ⎟ ⎟ ⎟ ⎟ ⎟ = 2 m ⋅ X T (X w)
Примечание. Процесс преобразования здесь опущен.
Используйте формулу градиентаМетод градиентного восхождения на самом деле представляет собой пакетное градиентное восхождение (существуют также стохастическое градиентное восхождение и мини-пакетное градиентное восхождение, которые не рассматриваются в этой статье).
Метод градиентного восхождения для нахождения главных компонент
Найдите первую главную компоненту
Сначала определите набор данных с двумя функциями, всего 100 образцов:
import numpy as np
X = np.empty((100, 2))
X[:, 0] = np.random.uniform(0., 100., size=100)
X[:, 1] = 0.75 * X[:, 0] + 3. + np.random.normal(0, 10., size=100)
Визуализация выглядит следующим образом:
demean()
пара методовВыполните обработку среднего возврата к 0:
def demean(X):
return X - np.mean(X, axis=0)
X_demean = demean(X)
После того, как среднее возвращается к 0Визуализация выглядит следующим образом:
f()
способ найти функциюЗначение:
def f(w, X):
return np.sum(X.dot(w) ** 2) / len(X)
df()
метод по градиентной формулеНайдите градиент:
def df(w, X):
return X.T.dot(X.dot(w)) * 2 / len(X)
gradient_ascent()
Метод представляет собой процесс метода градиентного восхождения, вn_iters
В цикле каждый раз новый, если новыйи старыйсоответствующая функцияРазница значений удовлетворяет точностиepsilon
, значит подходящий:
def gradient_ascent(X, initial_w, eta, n_iters=1e4, epsilon=1e-8):
w = direction(initial_w)
cur_iter = 0
while cur_iter < n_iters:
gradient = df(w, X)
last_w = w
w = w + eta * gradient
w = direction(w) # 将w转换成单位向量
if(abs(f(w, X) - f(last_w, X)) < epsilon):
break
cur_iter += 1
return w
который вызывает методdirection()
, дляПреобразовать в единичный вектор:
def direction(w):
return w / np.linalg.norm(w)
Затем используйте метод градиентного подъема, сначала установите начальныйи скорость обучения:
initial_w = np.random.random(X.shape[1])
eta = 0.001
позвонить напрямуюgradient_ascent()
метод:
w = gradient_ascent(X_demean, initial_w, eta)
получитес образцом визуализации, как показано (Представляет собой прямую линию):
Найти первые n основных компонентов
Первая главная компонента была найдена ранее, как найти следующую главную компоненту? Возьмем в качестве примера двухмерные объекты, как показано на рисунке:
образецв первой главной компонентеКомпонент на, компоненты на следующем главном компоненте, поэтому необходимо только удалить компонент данных по первому главному компоненту, а затем вычислить первый главный компонент для новых данных.
first_n_component()
способ найтиПервые n главных компонент , в цикле for каждый раз, когда ищутся главные компоненты, случайный(initial_w), после получения основного компонента удалить компонент на этом основном компонентеX_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
:
def first_n_component(n, X, eta=0.001, n_iters=1e4, epsilon=1e-8):
X_pca = X.copy()
X_pca = demean(X_pca)
res = []
for i in range(n):
initial_w = np.random.random(X_pca.shape[1])
w = gradient_ascent(X_pca, initial_w, eta)
res.append(w)
X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
return res
карта уменьшения размерности
После получения нескольких основных компонентов данные высокой размерности можно преобразовать в данные низкой размерности с помощью этих основных компонентов.
Для многомерных данных с m образцами и n признаками(m*n), первые k (k
X =⎛ ⎝⎜ ⎜⎜ ⎜⎜ X ( 1 ) 1 X ( 1 ) 2 ⋯ X ( 1 ) n X ( 2 ) 1 X ( 2 ) 2 ⋯ X ( 2 ) n X ( m ) 2 .. .X ( m) n ⎞ ⎠ ⎟ ⎟ ⎟ ⎟ ⎟ , W k = ⎛ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ W ( 1 ) 1 W ( 1 ) 2 ⋯ W ( 1 ) n W ( 2 ) 1 W ( 2 ) 2 ⋯ W ( 2 ) п ⋯ W ( k ) 1 W ( k ) 2 . . . W ( k ) n ⎞ ⎠ ⎟ ⎟ ⎟ ⎟ ⎟
Новые данные после приведения n-размерности к k-мерности:.
Информация может быть потеряна во время этого процесса уменьшения размерности. Если в исходных данных есть какая-то бесполезная информация, уменьшение размерности также может иметь эффект уменьшения сухости.
Также возможно восстановить новые данные после приведения размерности к исходной размерности:.
Внедрить PCA
определить классPCA
, в функции-конструктореn_components
Представляет количество главных компонентов, то есть измерение после уменьшения размера,components_
представляет собой главный компонент;
функцияfit()
с вышеуказаннымfirst_n_component()
Тот же метод используется для нахождения;
функцияtransform()
будетСопоставляя с каждым компонентом главного компонента, мы получаем, то есть уменьшение размерности;
функцияtransform()
будетСопоставляя с исходным пространством признаков, мы получаем.
import numpy as np
class PCA:
def __init__(self, n_components):
self.n_components = n_components
self.components_ = None
def fit(self, X, eta=0.001, n_iters=1e4):
def demean(X):
return X - np.mean(X, axis=0)
def f(w, X):
return np.sum(X.dot(w) ** 2) / len(X)
def df(w, X):
return X.T.dot(X.dot(w)) * 2 / len(X)
def direction(w):
return w / np.linalg.norm(w)
def first_component(X, initial_w, eta, n_iters, epsilon=1e-8):
w = direction(initial_w)
cur_iter = 0
while cur_iter < n_iters:
gradient = df(w, X)
last_w = w
w = w + eta * gradient
w = direction(w)
if(abs(f(w, X) - f(last_w, X)) < epsilon):
break
cur_iter += 1
return w
X_pca = demean(X)
self.components_ = np.empty(shape=(self.n_components, X.shape[1]))
for i in range(self.n_components):
initial_w = np.random.random(X_pca.shape[1])
w = first_component(X_pca, initial_w, eta, n_iters)
self.components_[i:] = w
X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
return self
def transform(self, X):
return X.dot(self.components_.T)
def inverse_transform(self, X):
return X.dot(self.components_)
PCA в Scikit Learn
Вместо градиентного подъема PCA в Scikit Learn использует соответствующий математический метод. Он используется следующим образом:
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
параметрn_components
представляет число главных компонентов.
Поскольку уменьшение размерности PCA приведет к потере информации об исходных данных, PCA в Scikit Learn указывает, сколько информации сохраняется в процессе уменьшения размерности, когда 0
pca = PCA(0.95)
То есть сохраняется 95% исходных данных, и программа автоматически получитcomponents_
.
Глядя на PCA с kNN
Теперь давайте посмотрим на преимущества PCA с помощью алгоритма классификации kNN. Сначала используйте обычный рукописный набор данных. Набор данных MNIST. Процедура получения образца набора данных:
import numpy as np
from sklearn.datasets import fetch_mldata
mnist = fetch_mldata("MNIST original")
X, y = mnist['data'], mnist['target']
# MNIST 数据集已经默认分配好了训练数据集和测试数据集,即前60000个数据为训练数据
X_train = np.array(X[:60000], dtype=float)
y_train = np.array(y[:60000], dtype=float)
X_test = np.array(X[60000:], dtype=float)
y_test = np.array(y[60000:], dtype=float)
Давайте посмотрим на эффективность алгоритма kNN без использования PCA:
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
%time knn_clf.fit(X_train, y_train)
В настоящее времяfit
Время, затраченное на процесс, равно:
CPU times: user 29.6 s, sys: 306 ms, total: 29.9 s
Wall time: 30.7 s
Затем проверьте точность набора тестовых данных:
%time knn_clf.score(X_test, y_test)
Время, затраченное на этот процесс, равно:
CPU times: user 10min 23s, sys: 2.05 s, total: 10min 25s
Wall time: 10min 31s
И правильная скорость в тестовом наборе данных составляет 0,9688.
Затем взгляните на преимущества PCA.При использовании PCA установите для хранения информации значение 90%:
from sklearn.decomposition import PCA
pca = PCA(0.9)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
knn_clf = KNeighborsClassifier()
%time knn_clf.fit(X_train_reduction, y_train)
В настоящее времяfit
Время, затраченное на процесс, равно:
CPU times: user 317 ms, sys: 5.31 ms, total: 323 ms
Wall time: 323 ms
Затем проверьте точность набора тестовых данных:
X_test_reduction = pca.transform(X_test)
%time knn_clf.score(X_test_reduction, y_test)
Время, затраченное на этот процесс, равно:
CPU times: user 1min 15s, sys: 469 ms, total: 1min 15s
Wall time: 1min 17s
Видно, что затраты времени после использования PCA значительно сокращаются, а правильная скорость набора тестовых данных составляет 0,9728, что не только не уменьшается, но и увеличивается, так как здесь теряется информация в процессе уменьшения размерности. бесполезная информация эффект сушки.