Как сравнить прогнозирующую способность PCA и NMF
Я хотел бы сравнить выходные данные алгоритма с различными предварительно обработанными данными: NMF и PCA. Чтобы получить какой-то сопоставимый результат, вместо того, чтобы выбирать одинаковое количество компонентов для каждого PCA и NMF, я хотел бы выбрать количество, которое объясняет, например, 95% оставшейся дисперсии.
Мне было интересно, возможно ли определить дисперсию, сохраняющуюся в каждом компоненте NMF.
Например, с использованием PCA это будет дано: retainedVariance(i) = eigenvalue(i) / sum(eigenvalue)
Есть идеи?
1 ответ
TL;DR
Вы должны перебрать разные n_components
и оценить explained_variance_score
декодированного X
на каждой итерации. Это покажет вам, сколько компонентов вам нужно, чтобы объяснить 95% отклонений.
Теперь я объясню почему.
Отношения между PCA и NMF
NMF и PCA, как и многие другие неконтролируемые алгоритмы обучения, нацелены на две вещи:
- кодировать вход
X
в сжатое представлениеH
; - раскодировать
H
вернуться кX'
, который должен быть как можно ближе кX
насколько это возможно.
Они делают это каким-то образом:
- Декодирование аналогично в PCA и NMF: они выводят
X' = dot(H, W)
, гдеW
является изученным параметром матрицы. - Кодировка другая. В PCA это также линейно:
H = dot(X, V)
, гдеV
также изученный параметр. В нмф,H = argmin(loss(X, H, W))
(в отношенииH
только), гдеloss
средняя квадратическая ошибка междуX
а такжеdot(H, W)
плюс некоторые дополнительные штрафы. Минимизация выполняется путем спуска координат, и результат может быть нелинейным вX
, - Тренировки тоже разные. PCA учится последовательно: первый компонент минимизирует MSE без ограничений, каждый следующий
k
th-й компонент минимизирует остаточное MSE при условии его ортогональности с предыдущими компонентами. NMF минимизирует то же самоеloss(X, H, W)
как при кодировании, но теперь по отношению к обоимH
а такжеW
,
Как измерить производительность сокращения размерности
Если вы хотите измерить производительность алгоритма кодирования / декодирования, вы можете выполнить обычные шаги:
- Тренируйте свой кодер + декодер на
X_train
- Чтобы измерить производительность в образце, сравните
X_train'=decode(encode(X_train))
сX_train
используя предпочитаемую метрику (например, MAE, RMSE или объясненную дисперсию) - Чтобы измерить внеплановую производительность (обобщающую способность) вашего алгоритма, выполните шаг 2 с невидимым
X_test
,
Давайте попробуем это с PCA
а также NMF
!
from sklearn import decomposition, datasets, model_selection, preprocessing, metrics
# use the well-known Iris dataset
X, _ = datasets.load_iris(return_X_y=True)
# split the dataset, to measure overfitting
X_train, X_test = model_selection.train_test_split(X, test_size=0.5, random_state=1)
# I scale the data in order to give equal importance to all its dimensions
# NMF does not allow negative input, so I don't center the data
scaler = preprocessing.StandardScaler(with_mean=False).fit(X_train)
X_train_sc = scaler.transform(X_train)
X_test_sc = scaler.transform(X_test)
# train the both decomposers
pca = decomposition.PCA(n_components=2).fit(X_train_sc)
nmf = decomposition.NMF(n_components=2).fit(X_train_sc)
print(sum(pca.explained_variance_ratio_))
Он напечатает вам объяснил коэффициент дисперсии 0.9536930834362043
- показатель PCA по умолчанию, оцененный с использованием его собственных значений. Мы можем измерить это более прямым способом - применяя метрику к фактическим и "прогнозируемым" значениям:
def get_score(model, data, scorer=metrics.explained_variance_score):
""" Estimate performance of the model on the data """
prediction = model.inverse_transform(model.transform(data))
return scorer(data, prediction)
print('train set performance')
print(get_score(pca, X_train_sc))
print(get_score(nmf, X_train_sc))
print('test set performance')
print(get_score(pca, X_test_sc))
print(get_score(nmf, X_test_sc))
который дает
train set performance
0.9536930834362043 # same as before!
0.937291711378812
test set performance
0.9597828443047842
0.9590555069007827
Вы можете видеть, что на тренировочном наборе PCA работает лучше, чем NMF, но на тестовом наборе их производительность практически идентична. Это происходит потому, что NMF применяет много регуляризации:
H
а такжеW
(заученный параметр) должен быть неотрицательнымH
должно быть как можно меньше (штрафы L1 и L2)W
должно быть как можно меньше (штрафы L1 и L2)
Эти регуляризации делают подгонку NMF хуже, чем это возможно, к обучающим данным, но они могут улучшить ее обобщающую способность, что произошло в нашем случае.
Как выбрать количество компонентов
В PCA это просто, потому что его компоненты h_1, h_2, ... h_k
выучены последовательно. Если вы добавите новый компонент h_(k+1)
, первый k
не изменится. Таким образом, вы можете оценить производительность каждого компонента, и эти оценки не будут зависеть от количества компонентов. Это позволяет PCA выводить explained_variance_ratio_
массив после единственной подгонки к данным.
NMF более сложный, потому что все его компоненты обучаются одновременно, и каждый зависит от всего остального. Таким образом, если вы добавите k+1
й компонент, первый k
компоненты будут меняться, и вы не сможете сопоставить каждый конкретный компонент с его объясненной дисперсией (или любой другой метрикой).
Но то, что вы можете, это соответствовать новому экземпляру NMF
для каждого числа компонентов и сравнить общую объясненную дисперсию:
ks = [1,2,3,4]
perfs_train = []
perfs_test = []
for k in ks:
nmf = decomposition.NMF(n_components=k).fit(X_train_sc)
perfs_train.append(get_score(nmf, X_train_sc))
perfs_test.append(get_score(nmf, X_test_sc))
print(perfs_train)
print(perfs_test)
который дал бы
[0.3236945680665101, 0.937291711378812, 0.995459457205891, 0.9974027602663655]
[0.26186701106012833, 0.9590555069007827, 0.9941424954209546, 0.9968456603914185]
Таким образом, три компонента (судя по характеристикам набора поездов) или два компонента (по тестовому набору) необходимы для объяснения как минимум 95% отклонения. Обратите внимание, что этот случай необычен и вызван небольшим объемом данных обучения и тестов: обычно производительность на тестовом наборе немного ухудшается, но в моем случае она немного улучшилась.