Неточности с prcomp? R lang PCA для собственных граней

Мой вопрос: в случае наличия матрицы, которую мы хотим использовать для PCA, где количество функций значительно превышает количество испытаний, почему prcomp не ведет себя так, как ожидалось (или я чего-то упускаю)?

Ниже приводится краткое изложение проблемы: полный код здесь, источник сжатых данных 7 МБ здесь (55 МБ без сжатия), целевое изображение здесь.

Моя точная ситуация заключается в том, что у меня есть матрица p на n, матрица X (p = функции, n = испытания), где испытания - это фотографии, сделанные с лицами, а функции - это пиксели на фотографиях (так что матрица 32256 на 148). Что я хочу сделать, так это найти векторы оценок основных компонентов этой матрицы. Поскольку найти ковариационную матрицу XX ^ T слишком дорого, простое решение - найти собственные векторы (v_i) X ^ TX и преобразовать их с помощью X (Xv_i) подробнее.

XTX <- t(X) %*% X # missing the 1 / n - 1 for cov matrix b/c we normalize later anyway
eigen <- eigen(XTX)
eigenvectors.XTX.col <- eigen$vectors

principal.component.scores <- apply(eigenvectors.XTX.col, 2, function(c) {
  normalize.vector(X %*% matrix(c, ncol = 1))
})

В моем случае оценки основных компонентов являются собственными лицами, и их можно использовать для успешной реконструкции целевого лица, как показано здесь: http://cl.ly/image/260w0N0u0Z3y (см. мой полный код, чтобы узнать, как)

Передача X в prcomp должна сделать что-то эквивалентное, но имеет другой результат, чем вышеприведенный доморощенный способ:

pca <- prcomp(X)
pca$x # right size, but wrong pc scores

Результат использования pca$x при восстановлении лица - не полная чушь, а намного хуже: http://cl.ly/image/2p19360u2P43

Я также проверил, что использование prcomp на t(x) дало другую матрицу вращения, поэтому prcomp делает что-то необычное, но что-то загадочное под капотом. Я знаю из здесь что prcomp использует SVD для вычисления векторов загрузки главных компонентов вместо собственного разложения, но это не должно приводить к каким-либо ошибкам здесь (или я так думаю ...).

Как правильно использовать встроенный метод prcomp, способ должен быть, верно?


person polpetti    schedule 24.08.2014    source источник
comment
Из-за математики этот метод не может решить вашу проблему. У вас должно быть как минимум столько же наблюдений, сколько переменных, но желательно больше первых.   -  person Roman Luštrik    schedule 24.08.2014
comment
Спасибо за комментарий @ RomanLuštrik! Этот источник подтверждает то, что вы сказали о методе princomp, но, как я был удивлен, обнаружив в ответе ниже, это не тот случай, когда вам нужно больше наблюдений, чем переменных (это было бы невозможно в некоторых дисциплинах, таких как геномика, или даже здесь с распознавание лиц). Скорее проблема здесь в некоторых раздражающих значениях по умолчанию в prcomp, а также в отсутствии нормализации. Извините за неубедительную проблему в моем вопросе!   -  person polpetti    schedule 24.08.2014


Ответы (1)


Вау, ответ совсем не забавный, он скорее связан с параметрами по умолчанию в методе prcomp:

Чтобы решить эту проблему, я сначала посмотрел на R-источник prcomp и увидел, что матрица вращения должна быть равна svd(X)$v. Проверка этого в командной строке R показала, что с моим X (здесь) этого не произошло. Это связано с тем, что даже несмотря на то, что параметр по умолчанию scale = F равен prcomp, prcomp все равно будет запускать метод R scale, хотя бы для центрирования матрицы, которая по умолчанию имеет значение True, как показано здесь. В моем случае это плохо, потому что я передал данные как уже центрированные (вычтенное среднее изображение).

Таким образом, повторный запуск с prcomp(X, center = F) даст матрицу поворота, равную svd(X)$v, как и ожидалось. С этого момента единственная «ошибка», которую prcomp допускает при построении prcomp(X, center = F)$x, будет заключаться в том, что столбцы не нормализуются, поэтому каждый из них отличается только скалярным множителем из матрицы principal.component.scores, на которую я ссылался выше в моем коде. Без нормализации prcomp(X, center = F)$x результаты будут лучше, но не такими хорошими, как здесь: http://cl.ly/image/3u2y3m1h2S0o

Но после нормализации с помощью pca.x.norm <- apply(pca$x, 2, normalize.vector) результаты prcomp при реконструкции лица идентичны: http://cl.ly/image/24390O3x0A0x

tl; dr - prcomp неожиданно центрирует данные даже с параметром scale = F, плюс для целей собственных граней вам нужно будет нормализовать столбцы prcomp(X, center = F)$x, тогда все будет работать как нужно!

person polpetti    schedule 24.08.2014