Алгоритм за один цикл находит одну главную компоненту.
Существуют разные реализации этого алгоритма, я взял отсюда:
https://www.mathworks.com/matlabcentral/fileexchange/42142-nipals-algorithm-for-principle-component-analysis/content/nipals.m?requestedDomain=www.mathworks.com - встроенная в Matlab функция, которая выполняет ту же задачу, но имеет другое количество аргументов (и вообще, брать готовые непонятные функции - не наш метод).
Порядок работы алгоритма:
1. Начальные условия, выбор первого столбца в качестве первой компоненты , где k = 1: N - текущая ГК, где N - число вычисляемых ГК.
Tk = X(:,1);
2. Нахождение приближённых значений вектора нагрузок для текущих начальных условий путём проекции исходной матрицы на вектор ГК
Pk = (X'*Tk/(Tk'*Tk));
3. Нормирование полученного значения
Pk = Pk/norm(Pk);
4. Уточнение вектора счетов
Tk2 = X*Pk/(Pk'*Pk);
5. Вычиление конвергенции(сходимости) (ежели текущий вектор близок к собственному вектору, то разность стремится к нулю)
d0 = (Tk2-Tk)'*(Tk2-Tk);
6. Присваивание уточнённого значения вектора счетов текущему для следующей итерации
|
|
Tk = Tk2;
7. Проверка конвергенции: ежели меньше константы, например 0.0001, значит k-тая ГК найдена, поиск следующей компоненты. ежели нет, переход на п. 2
8. Вычитание вклада найденной ГК из исходных данных,
X = X - Tk*Pk';
добавление найденной ГК в конечную матрицу счетов и нагрузок
T(:,k) = Tk;
P(:,k) = Pk;
Полностью код алгоритма может выглядеть таким образом:
for k = 1:nc
% перебор по всем ГК
Tk = X(:,1); % шаг 1
d0 = 1; % переменная для конвергенции
while d0 > 0.0001
% шаг 7, цикл по проверке конвергенции
Pk = (X'*Tk/(Tk'*Tk)); % шаг 2
Pk = Pk/norm(Pk); % шаг 3
Tk2 = X*Pk/(Pk'*Pk); % шаг 4
d0 = (Tk2-Tk)'*(Tk2-Tk);% шаг 5
Tk = Tk2; % шаг 6
end
X = X - Tk*Pk'; % шаг 8
T(:,k) = Tk; % шаг 8
P(:,k) = Pk; % шаг 8
end