Как начинающий специалист по данным, вы обычно работаете с наборами данных, которые (возможно, неожиданно) относительно малы. Например, набор данных с 20 столбцами и 40 000 строк кажется новичку довольно большим; однако это песчинка на пляже с точки зрения того, что возможно. Нередко на более высоком уровне данных приходится иметь дело с сотнями столбцов и сотнями миллионов строк.

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

Кроме того, временная сложность обучения и обслуживания модели растет экспоненциально с каждым добавленным столбцом — 21-й столбец в наборе данных из 20 000 точек может стоить еще 5–10 минут времени обучения; однако, экстраполируя на вышеупомянутые сотни миллионов строк, 101-й столбец может стоить дополнительных двенадцати часов времени обучения.

С большими наборами данных становится критически важным, чтобы мы убрали как можно больше ненужных столбцов не только для своевременности, но и для минимизации внутренних счетов за электроэнергию и расходов на пространство для хранения. Это, очевидно, связано с потерей информации, но мы можем позволить себе потерять некоторую информацию, если мы сокращаем вычислительные затраты, сохраняя при этом некоторый базовый стандарт производительности модели, верно? Что, если бы существовал способ разумно принести эту жертву… Введите PCA — анализ главных компонентов.

Анализ основных компонентов — это то, что мы называем «методом уменьшения размерности» — стратегией, используемой для уменьшения количества столбцов в вашем наборе данных путем сжатия нескольких столбцов до одного столбца. На низком уровне PCA создает новый столбец из оптимизированной линейной комбинации исходных столбцов, применяя несколько линейных преобразований к набору данных и определяя относительную ценность информации для каждого столбца перед извлечением информации по столбцу пропорционально количеству информации в этом столбце. содержит.

Теперь по-русски: Дракон состоит из частей девяти животных: рогов оленя, головы верблюда, глаз дьявола, шеи змеи, брюшка большого моллюска, чешуи карпа, когтей орла. , лапы тигра и уши быка. Теперь представьте, что у нас есть набор данных из девяти столбцов, и каждый столбец представляет одно из этих животных. Приходит PCA и обрабатывает эти столбцы животных, беря из каждого только самые важные части — лапы столбца тигра, чешуйку столбца карпа и т. д. — и объединяет их, чтобы сформировать новый столбец дракона из оригинальная девятка. Хотя да, мы потеряли некоторые части каждой колонны животных при синтезе нашей колонны драконов, но мы сохранили и объединили самые влиятельные и мощные части. И теперь у нас случайно есть огнедышащая, сверхзаряженная колонна дракона (здесь я также должен отметить, что вы можете выбрать возврат нескольких «столбцов дракона», каждая дополнительная колонна слабее предыдущей, но все еще состоит из частей из каждый исходный столбец и в результате общий прирост информации). На обратной стороне нашей колонны (колонн) дракона мы теперь можем пройти через процесс обучения модели. Наши серверные хранилища и счета за электроэнергию значительно сократились, а график моделирования ускорился. Помните, однако, что это происходит за счет некоторой заранее определенной потери информации, с которой мы согласны.

Если вы хотите узнать больше о математике, лежащей в основе PCA, я предлагаю страницу в Википедии. Для реализации вам нужно знать всего несколько шагов, так как scikit-learn делает этот процесс невероятно простым. Теперь мы перейдем к процессу PCA в python! Для этого мы будем использовать малоизвестный и редко используемый набор данных iris.

import pandas as pd
from sklearn import datasets
# load iris dataset into notebook; convert it to DataFrame
iris = datasets.load_iris()
df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])
df['target'] = iris['target']
# preview DataFrame
df.head()

Во-первых, мы разделим наш DataFrame на целевые столбцы и столбцы функций, а затем выполним разделение обучения и тестирования — как всегда при предварительной обработке машинного обучения.

# split DataFrame into X (features) and y (target)
X = df.drop('target', axis=1)
y = df['target']
# perform train-test split on dataset
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

После предварительной обработки мы масштабируем наши данные, центрируя каждый столбец с помощью объекта StandardScaler. В некоторых редких случаях стандартное масштабирование ваших данных заранее может быть невыгодным или необходимым, например, в случае разреженного набора данных, но обычно мы хотим масштабировать заранее. Также обратите внимание, что PCA автоматически масштабирует ваши данные о среднем значении по столбцу, поэтому вам нужен стандартный масштабатор только в том случае, если вы хотите также масштабировать относительно крайних значений.

# standard scale our data
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
X_train_scaled = ss.fit_transform(X_train)
X_test_scaled = ss.transform(X_test)

Затем мы создаем экземпляр нашего объекта PCA. Основной параметр, который имеет значение для вашего объекта PCA n_components. Если установлено целое число, это сообщает объекту PCA, сколько столбцов, известных как «основные компоненты» или «ПК», нужно вернуть после преобразования. Возможно, более полезным будет то, что мы можем установить n_components равным десятичному числу с плавающей запятой, что сообщит объекту PCA о необходимости возврата количества столбцов, чтобы десятичная часть информации с плавающей запятой сохранялась в возвращаемых столбцах. Если мы хотим использовать более детальный подход к количеству возвращаемых ПК, мы можем взглянуть на график, показывающий уменьшение отдачи от прироста информации для каждого дополнительного PCA, чтобы определить оптимальное количество PCA для include — давайте сначала посмотрим на это.

# instantiate a PCA object and fit it to our train data
from sklearn.decomposition import PCA
pca = PCA(random_state=42)
pca.fit(X_train_scaled)
num_features = [1,2,3,4]
explained_variance = pca.explained_variance_ratio_.cumsum()
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(num_features, (100*explained_variance))
plt.xticks(ticks=[1,2,3,4]);
plt.xlabel('Number of PCAs')
plt.ylabel('Percent Variance Explained')
plt.title('Percent Explained Variance by Number of PCs', fontsize=14)
plt.show()

Объясненную дисперсию можно рассматривать как количество информации, которую мы сохраняем из исходного набора данных после применения преобразования PCA. Мы фиксируем 6 процентных пунктов дисперсии при переходе от 1 ПК к 2 ПК, но только около 1,5 процентных пункта при переходе от 2 к 3 ПК; а использование 4 ПК, то есть исходного набора данных, противоречит цели и также не дает какого-либо значительного прироста информации. Таким образом, похоже, что 2 PCA — это наше приятное место, где мы значительно сокращаем входную информацию по сравнению только с 1 PC, сохраняя при этом высокую степень объясненной дисперсии. Давайте продолжим и преобразуем наши X_train_scaled и X_test_scaled, используя n_components=2. Обратите внимание, что в качестве общей отправной точки вы захотите сохранить не менее 80% информации из исходного набора данных в качестве основы.

# transform original columns to PCs
# option 1: choose the number of components to return
pca = PCA(n_components=2, random_state=42)
# option 2: choose the fraction of explained variance to capture
#    pca = PCA(n_components=.8, random_state=42)
X_train_pca = pca.fit_transform(X_train_scaled)
X_test_pca = pca.transform(X_test_scaled)
# convert PCs to DataFrames to see what a PC looks like
X_train_pca = pd.DataFrame(X_train_pca, columns=['PC1', 'PC2'])
X_test_pca = pd.DataFrame(X_test_pca, columns=['PC1', 'PC2'])
# preview PCA dataset
X_train_pca.head()

Например, сегодня мы будем использовать параметрическую модель классификатора kNN. Импортируйте и создайте экземпляр kNN для обычного моделирования и моделирования PCA, чтобы мы могли продемонстрировать разницу во времени моделирования.

# import and instantiate kNNs
from sklearn.neighbors import KNeighborsClassifier
knn_regular = KNeighborsClassifier(n_neighbors=5)
knn_pca = KNeighborsClassifier(n_neighbors=5)

Теперь мы подгоним и оценим модель по необработанным данным, не относящимся к PCA, и найдем затраченное время, а также точность.

import time
start = time.time()
knn_regular.fit(X_train, y_train)
accuracy_regular = knn_regular.score(X_test, y_test)
end = time.time()
elapsed_regular = end - start
print('Regular Model Train and Test Time: ' + str(elapsed_regular))
print('Regular Model Accuracy:            ' + str(accuracy_regular))

Выглядит неплохо!

Нет, мы сделаем то же самое для данных PCA.

start = time.time()
knn_pca.fit(X_train_pca, y_train)
accuracy_pca = knn_pca.score(X_test_pca, y_test)
end = time.time()
elapsed_pca = end - start
print('PCA Model Train and Test Time: ' + str(elapsed_pca))
print('PCA Model Accuracy:            ' + str(accuracy_pca))

Вау! Без потери точности мы смогли значительно сократить время обучения и проверки.

time_decrease_pct = (elapsed_regular - elapsed_pca) / elapsed_regular
print('We reduced time in training and validation by: ' 
      + str(round((100*time_decrease_pct), 2)) + '%')

23,43%!! А теперь представьте, если бы мы применили это к модели, для обучения которой потребовалось несколько часов или даже дней… это серьезно сэкономило время.

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

# look at the weights of PCA components
pca.components_

Мы можем интерпретировать каждое число в каждой строке массива как веса, примененные к каждому из исходных столбцов при создании соответствующего ПК. Итак, уравнение, используемое для расчета первого ПК, выглядит примерно так:

PC1 = 0,52*столб1 - 0,24*столб2 + 0,58*столб3 + 0,56*столб4

Мы можем понимать каждое из этих чисел как относительную важность информации для каждого столбца — в этом случае, поскольку абсолютное значение коэффициента третьего столбца является самым высоким, мы можем сказать, что третий столбец предоставляет самую богатую информацию.

Прежде чем мы закончим, следует отметить, что PCA не очень важен, мощен или необходим, если вы не имеете дело с большими наборами данных, потому что нет веской причины жертвовать информацией, если вы не ограничены во времени. Тем не менее, когда вы продвигаетесь вперед в своей судьбе в качестве специалиста по данным, используйте эту технику экономно: как настоящий воин-дракон, вы должны быть на высоте, но никогда не заходите слишком далеко.

Первоначально опубликовано на http://github.com.