Как выполнить перекрестную проверку для PCA, чтобы определить количество основных компонентов?

12

Я пытаюсь написать свою собственную функцию для анализа главных компонентов, PCA (конечно, многое уже написано, но я просто заинтересован в том, чтобы реализовать что-то самостоятельно). Основная проблема, с которой я столкнулся, - это этап перекрестной проверки и вычисления прогнозируемой суммы квадратов (PRESS). Неважно, какую перекрестную проверку я использую, речь идет в основном о теории позади, но рассмотрим перекрестную проверку без участия (LOOCV). Из теории я узнал, что для выполнения LOOCV необходимо:

  1. удалить объект
  2. масштабировать остальное
  3. выполнить PCA с некоторым количеством компонентов
  4. масштабировать удаленный объект в соответствии с параметрами, полученными в (2)
  5. предсказать объект в соответствии с моделью PCA
  6. рассчитать ПРЕСС для этого объекта
  7. повторно выполнить тот же алгоритм для других объектов
  8. суммировать все значения ПРЕССА
  9. прибыль

Поскольку я очень новичок в этой области, чтобы быть уверенным, что я прав, я сравниваю результаты с результатами некоторых программ, которые у меня есть (также, чтобы написать код, я следую инструкциям в программном обеспечении). Я получаю полностью те же результаты, вычисляя остаточную сумму квадратов и R2 , но вычисление PRESS является проблемой.

Не могли бы вы сказать мне, правильно ли то, что я реализую на этапе перекрестной проверки:

case 'loocv'

% # n - number of objects
% # p - number of variables
% # vComponents - the number of components used in CV
dataSets = divideData(n,n); 
         % # it is just a variable responsible for creating datasets for CV 
         % #  (for LOOCV datasets will be equal to [1, 2, 3, ... , n]);'
tempPRESS = zeros(n,vComponents);

for j = 1:n
  Xmodel1 = X; % # X - n x p original matrix
  Xmodel1(dataSets{j},:) = []; % # delete the object to be predicted
  [Xmodel1,Xmodel1shift,Xmodel1div] = skScale(Xmodel1, 'Center', vCenter, 
                                              'Scaling', vScaling); 
          % # scale the data and extract the shift and scaling factor
  Xmodel2 = X(dataSets{j},:); % # the object to be predicted
  Xmodel2 = bsxfun(@minus,Xmodel2,Xmodel1shift); % # shift and scale the object
  Xmodel2 = bsxfun(@rdivide,Xmodel2,Xmodel1div);
  [Xscores2,Xloadings2] = myNipals(Xmodel1,0.00000001,vComponents); 
          % # the way to calculate the scores and loadings
                % # Xscores2 - n x vComponents matrix
                % # Xloadings2 - vComponents x p matrix
  for i = 1:vComponents
    tempPRESS(j,i) = sum(sum((Xmodel2* ...
       (eye(p) - transpose(Xloadings2(1:i,:))*Xloadings2(1:i,:))).^2));
  end
end
PRESS = sum(tempPRESS,1);

В программном обеспечении ( PLS_Toolbox ) это работает так:

for i = 1:vComponents
    tempPCA = eye(p) - transpose(Xloadings2(1:i,:))*Xloadings2(1:i,:);
    for kk = 1:p
        tempRepmat(:,kk) = -(1/tempPCA(kk,kk))*tempPCA(:,kk);
          % # this I do not understand
        tempRepmat(kk,kk) = -1; 
          % # here is some normalization that I do not get
    end 
    tempPRESS(j,i) = sum(sum((Xmodel2*tempRepmat).^2)); 
end

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

Кирилл
источник
Дальнейшая проверка, понимаю ли я дополнительный фрагмент нормализации: какова роль tempRepmat(kk,kk) = -1строки? Разве предыдущая строка уже не гарантирует, что tempRepmat(kk,kk)равно -1? Кроме того, почему минусы? В любом случае ошибка будет возведена в квадрат, так что я правильно понимаю, что если убрать минусы, ничего не изменится?
говорит амеба: восстанови монику
Я проверял это в прошлом, и ничего не изменится. Это правильно. Я обнаружил только некоторые параллели с надежными реализациями PCA, потому что каждое вычисленное значение PRESS в такой реализации (до суммирования всего) имеет свой вес.
Кирилл
Я ищу код R, эквивалентный коду MATLAB, указанному в ответе, и получил вознаграждение.
AIM_BLB
3
@CSA, запрос кода здесь не по теме (даже, предположительно, через комментарии и вознаграждения). Вы должны быть в состоянии спросить об этом при переполнении стека : вы можете скопировать код, привести источник с ссылкой здесь и запросить перевод. Я считаю, что все, что было бы по теме там.
gung - Восстановить Монику

Ответы:

21

То, что вы делаете, неправильно: вычислять PRESS для PCA не имеет смысла! В частности, проблема заключается в вашем шаге № 5.


Наивный подход к PRESS для PCA

Пусть набор данных состоит из точек в d- мерном пространстве: x ( i )R d ,ndx(i)Rd,i=1nx(i)X(i)kU(i)x(i)x^(i)2=x(i)U(i)[U(i)]x(i)2i

PRESS=?i=1nx(i)U(i)[U(i)]x(i)2.

Для простоты я игнорирую проблемы центрирования и масштабирования здесь.

Наивный подход неправильный

Проблема выше в том, что мы используем для вычисления предсказания , и это очень плохо.x(i)x^(i)

Обратите внимание на принципиальное отличие от случая регрессии, где формула ошибки восстановления в основном такая же: , но прогноз вычисляется с использованием переменных-предикторов, а не с использованием . Это невозможно в PCA, потому что в PCA нет зависимых и независимых переменных: все переменные обрабатываются вместе.y(i)y^(i)2y^(i)y(i)

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

Правильный подход

Существует несколько возможных подходов, см. Bro et al. (2008) Перекрестная проверка моделей компонентов: критический взгляд на текущие методы для обзора и сравнения. Один из подходов состоит в том, чтобы исключить одно измерение одной точки данных за раз (т.е. вместо ), чтобы обучающие данные стали матрицей с одним отсутствующим значением и затем для прогнозирования («вменения») этого недостающего значения с помощью PCA. (Конечно, можно произвольно удерживать некоторую большую часть матричных элементов, например, 10%). Проблема в том, что вычисление PCA с пропущенными значениями может быть довольно медленным в вычислительном отношении (оно основывается на алгоритме EM), но здесь необходимо многократно повторяться. Обновление: см. Http://alexhwilliams.info/itsneuronalblog/2018/02/26/crossval/xj(i)x(i) для хорошего обсуждения и реализации Python (PCA с отсутствующими значениями реализуется через чередующиеся наименьшие квадраты).

Подход, который я нашел гораздо более практичным, состоит в том, чтобы исключать одну точку данных за раз, вычислять PCA на данных обучения (точно так же, как указано выше), но затем циклически проходить измерения , оставьте их по одному и вычислите ошибку восстановления, используя остальные. Это может быть довольно запутанным в начале, и формулы имеют тенденцию становиться довольно грязными, но реализация довольно проста. Позвольте мне сначала дать (несколько пугающую) формулу, а затем кратко объяснить ее:x(i)x(i)

PRESSPCA=i=1nj=1d|xj(i)[U(i)[Uj(i)]+xj(i)]j|2.

Рассмотрим внутренний цикл здесь. Мы пропустили одну точку и вычислили основных компонентов на обучающих данных, . Теперь мы сохраняем каждое значение в качестве теста и используем оставшиеся измерения для выполнения прогноза , Предсказание - это координата "проекции" (в смысле наименьших квадратов) на подпространство, охватываемое по . Чтобы вычислить его, найдите точку в пространстве ПК которая ближе всего кx(i)kU(i)xj(i)xj(i)Rd1x^j(i)jxj(i)U(i)z^Rkxj(i) путем вычисления где равно с строкой выгнан, и означает псевдообратный. Теперь отобразите обратно в исходное пространство: и взять его координату . z^=[Uj(i)]+xj(i)RkUj(i)U(i)j[]+z^U(i)[Uj(i)]+xj(i)j[]j

Приближение к правильному подходу

Я не совсем понимаю дополнительную нормализацию, используемую в PLS_Toolbox, но вот один подход, который идет в том же направлении.

Есть еще один способ отобразить на пространство главных компонентов: , т.е. просто сделайте транспонирование вместо псевдообратного. Другими словами, измерение, оставленное для тестирования, вообще не учитывается, и соответствующие веса также просто выбрасываются. Я думаю, что это должно быть менее точно, но часто может быть приемлемым. Хорошо, что полученная формула теперь может быть векторизована следующим образом (я опускаю вычисления):xj(i)z^approx=[Uj(i)]xj(i)

PRESSPCA,approx=i=1nj=1d|xj(i)[U(i)[Uj(i)]xj(i)]j|2=i=1n(IUU+diag{UU})x(i)2,

где я написал как для компактности, а означает установку всех недиагональных элементов на ноль. Обратите внимание, что эта формула выглядит точно так же, как первая (наивная ПРЕССА) с небольшой коррекцией! Также обратите внимание, что это исправление зависит только от диагонали , как в коде PLS_Toolbox. Однако формула все еще отличается от того, что, по-видимому, реализовано в PLS_Toolbox, и эту разницу я не могу объяснить. U d i a g {} U UU(i)Udiag{}UU

Обновление (февраль 2018 г.): выше я назвал одну процедуру «правильной», а другую «приблизительной», но я больше не уверен, что это имеет смысл. Обе процедуры имеют смысл, и я думаю, что ни одна из них не является более правильной. Мне очень нравится, что «приблизительная» процедура имеет более простую формулу. Кроме того, я помню, что у меня был какой-то набор данных, где «приблизительная» процедура дала результаты, которые выглядели более значимыми. К сожалению, я больше не помню деталей.


Примеры

Вот как эти методы сравниваются для двух известных наборов данных: набор данных Iris и набор данных wine. Обратите внимание, что наивный метод создает монотонно убывающую кривую, тогда как два других метода дают кривую с минимумом. Отметим далее, что в случае радужной оболочки, приближенный метод предлагает 1 ПК в качестве оптимального числа, а псевдообратный метод предлагает 2 ПК. (И, глядя на любую диаграмму рассеяния PCA для набора данных Iris, кажется, что оба первых ПК несут некоторый сигнал.) И в случае с вином псевдообратный метод явно указывает на 3 ПК, тогда как приблизительный метод не может выбирать между 3 и 5.

введите описание изображения здесь


Код Matlab для перекрестной проверки и построения результатов

function pca_loocv(X)

%// loop over data points 
for n=1:size(X,1)
    Xtrain = X([1:n-1 n+1:end],:);
    mu = mean(Xtrain);
    Xtrain = bsxfun(@minus, Xtrain, mu);
    [~,~,V] = svd(Xtrain, 'econ');
    Xtest = X(n,:);
    Xtest = bsxfun(@minus, Xtest, mu);

    %// loop over the number of PCs
    for j=1:min(size(V,2),25)
        P = V(:,1:j)*V(:,1:j)';        %//'
        err1 = Xtest * (eye(size(P)) - P);
        err2 = Xtest * (eye(size(P)) - P + diag(diag(P)));
        for k=1:size(Xtest,2)
            proj = Xtest(:,[1:k-1 k+1:end])*pinv(V([1:k-1 k+1:end],1:j))'*V(:,1:j)'; 
            err3(k) = Xtest(k) - proj(k);
        end

        error1(n,j) = sum(err1(:).^2);
        error2(n,j) = sum(err2(:).^2);
        error3(n,j) = sum(err3(:).^2);
    end    
end

error1 = sum(error1);
error2 = sum(error2);
error3 = sum(error3);
%// plotting code
figure
hold on
plot(error1, 'k.--')
plot(error2, 'r.-')
plot(error3, 'b.-')
legend({'Naive method', 'Approximate method', 'Pseudoinverse method'}, ...
    'Location', 'NorthWest')
legend boxoff
set(gca, 'XTick', 1:length(error1))
set(gca, 'YTick', [])
xlabel('Number of PCs')
ylabel('Cross-validation error')
амеба говорит восстановить монику
источник
Спасибо за ваш ответ! Я знаю эту газету. И я применил перекрестную проверку строк, описанную там (кажется, что она точно соответствует коду, который я предоставил). Я сравниваю с программным обеспечением PLS_Toolbox, но у них есть одна строка кода в LOOCV, которую я действительно не понимаю (я написал в оригинальном вопросе).
Кирилл
Да, они называют это «перекрестной проверкой по строкам», и ваша реализация кажется хорошей, но, пожалуйста, обратите внимание, что это плохой способ выполнить перекрестную проверку (как указано и также эмпирически продемонстрировано в Bro и др.), И в основном вам следует никогда не используйте это! Что касается строки кода, которую вы не понимаете - вы собираетесь обновить свой вопрос? Не уверен, что вы имеете в виду.
говорит амеба, восстанови Монику
Дело в том, что эта реализация способна достичь минимума в CV.
Кирилл
PRESS из очень близко к LOO% объясненной дисперсии - Я бы не сказал , что это хорошо или плохо, но это определенно что - то нужно , чтобы быть в курсе. И как% объясненной дисперсии будет приближаться к 1, когда модель PCA приближается к рангу набора данных, эта X PRESS будет приближаться к 0.x^x
cbeleites недоволен SX
@Kirill: Спасибо, фрагмент кода теперь имеет смысл (возможно, вы можете удалить вышеприведенные комментарии, которые сейчас устарели). Я понятия не имею, что он должен делать, но если вы говорите, что вычисленная ошибка прогнозирования достигает минимума, то это, вероятно, эффективно вводит некоторый штраф для большего (количество компонентов; т.е. переменная в вашем коде). Честно говоря, я бы скептически относился к любому такому методу (если только у него нет теоретического обоснования), особенно если учесть, что существуют лучшие подходы, как тот, который я описал в своем ответе. ki
говорит амеба: восстанови монику
1

Чтобы добавить еще более общее замечание к хорошему ответу @ amoeba:

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

Подконтрольные модели всегда имеют свой конечный результат так, что вам не нужно сильно беспокоиться об этом: по определению и конструкции утверждает, что имеет то же значение, что и , так что вы можете напрямую сравнить его. у уy^y^y

Чтобы создать значимые показатели производительности, вам нужно подумать, какие виды свободы модели не имеют смысла для вашего приложения, а какие нет. Это привело бы к ПРЕССУ на счетах, возможно (обычно?) После некоторого прокрутообразного вращения / переворота.

НАЖМИТЕ на х Я думаю (у меня нет времени, чтобы выяснить, что делают их 2 строки кода - но, возможно, вы могли бы пройтись по строкам и посмотреть?):

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


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

cbeleites недоволен SX
источник