Ce que vous faites est faux: cela n'a aucun sens de calculer PRESS for PCA comme ça! Plus précisément, le problème réside dans votre étape # 5.
Approche naïve de PRESS pour PCA
Soit l'ensemble de données composé de points dans l'espace dimensionnel: . Pour calculer l'erreur de reconstruction pour un seul point de données de test , vous effectuez l'ACP sur l'ensemble d'apprentissage sans ce point, prenez un certain nombre d'axes principaux sous forme de colonnes de , et recherchez l'erreur de reconstruction comme . PRESS est alors égal à la somme de tous les échantillons de testd x ( i ) ∈ R d ,ndx ( i ) X ( - i ) k U ( - i ) ‖ x ( i ) - x ( i ) ‖ 2 = ‖ x ( i ) - U ( - i ) [ U ( - i ) ] ⊤ x ( i ) R E S Sx(i)∈Rd,i=1…nx(i)X(−i)kU(−i) i P∥∥x(i)−x^(i)∥∥2=∥∥x(i)−U(−i)[U(−i)]⊤x(i)∥∥2i, donc l'équation raisonnable semble être:
PRESS=?∑i=1n∥∥x(i)−U(−i)[U(−i)]⊤x(i)∥∥2.
Par souci de simplicité, j'ignore les problèmes de centrage et de mise à l'échelle ici.
L'approche naïve est fausse
Le problème ci-dessus est que nous utilisons pour calculer la prédiction , et c'est une très mauvaise chose.xx(i)x^(i)
Notez la différence cruciale dans un cas de régression, où la formule de l'erreur de reconstruction est fondamentalement la même , mais la prédiction est calculée en utilisant les variables prédictives et non en utilisant . Cela n'est pas possible en PCA, car en PCA il n'y a pas de variables dépendantes et indépendantes: toutes les variables sont traitées ensemble.y ( i )∥∥y(i)−y^(i)∥∥2y^(i)y(i)
En pratique, cela signifie que la PRESSE telle que calculée ci-dessus peut diminuer avec un nombre croissant de composants et n'atteindre jamais un minimum. Ce qui laisserait penser que tous les composants sont significatifs. Ou peut-être que dans certains cas, il atteint un minimum, mais tend toujours à sur-adapter et à surestimer la dimensionnalité optimale.kd
Une approche correcte
Il existe plusieurs approches possibles, voir Bro et al. (2008) Validation croisée des modèles de composants: un regard critique sur les méthodes actuelles pour un aperçu et une comparaison. Une approche consiste à laisser de côté une dimension d'un point de données à la fois (c'est-à-dire au lieu de ), de sorte que les données d'apprentissage deviennent une matrice avec une valeur manquante , puis de prédire ("imputer") cette valeur manquante avec PCA. (On peut bien sûr tenir au hasard une fraction plus importante d'éléments de matrice, par exemple 10%). Le problème est que le calcul de l'ACP avec des valeurs manquantes peut être assez lent sur le plan informatique (il repose sur l'algorithme EM), mais doit être répété plusieurs fois ici. Mise à jour: voir http://alexhwilliams.info/itsneuronalblog/2018/02/26/crossval/ xx(i)jx(i) pour une discussion agréable et l'implémentation de Python (PCA avec des valeurs manquantes est implémenté via l'alternance des moindres carrés).
Une approche que j'ai trouvée beaucoup plus pratique consiste à omettre un point de données à la fois, à calculer l'ACP sur les données d'entraînement (exactement comme ci-dessus), puis à parcourir les dimensions de , les laisser un par un et calculer une erreur de reconstruction en utilisant le reste. Cela peut être assez déroutant au début et les formules ont tendance à devenir assez désordonnées, mais la mise en œuvre est plutôt simple. Permettez-moi d'abord de donner la formule (quelque peu effrayante), puis de l'expliquer brièvement:x(i)x(i)
PRESSPCA=∑i=1n∑j=1d∣∣∣x(i)j−[U(−i)[U(−i)−j]+x(i)−j]j∣∣∣2.
Considérez la boucle intérieure ici. Nous avons omis un point et calculé composantes principales sur les données d'apprentissage, . Maintenant, nous gardons chaque valeur comme test et utilisons les dimensions restantes pour effectuer la prédiction . La prédiction est la ème coordonnée de "la projection" (dans le sens des moindres carrés) de sur le sous-espace étendu par . Pour le calculer, trouvez un point dans l'espace PC plus proche dex(i)kU(−i)x(i)jx(i)−j∈Rd−1x^(i)jjx(i)−jU(−i)z^Rkx(i)−j en calculant où est avec -ième ligne expulsé et signifie pseudoinverse. Mappez maintenant vers l'espace d'origine: et prendre sa -ème coordonner . z^=[U(−i)−j]+x(i)−j∈RkU(−i)−j j[⋅ ] + z U ( - i ) [U(−i)j[⋅]+z^U(−i)[U(−i)−j]+x(i)−jj[⋅]j
Une approximation de la bonne approche
Je ne comprends pas très bien la normalisation supplémentaire utilisée dans la PLS_Toolbox, mais voici une approche qui va dans le même sens.
Il existe une autre façon de mapper sur l'espace des composants principaux: , c'est-à-dire simplement prendre la transposition au lieu du pseudo-inverse. En d'autres termes, la dimension qui est laissée de côté pour les tests n'est pas comptée du tout et les poids correspondants sont également simplement supprimés. Je pense que cela devrait être moins précis, mais pourrait souvent être acceptable. La bonne chose est que la formule résultante peut maintenant être vectorisée comme suit (j'omet le calcul):jx(i)−jz^approx=[U(−i)−j]⊤x(i)−j
PRESSPCA,approx=∑i=1n∑j=1d∣∣∣x(i)j−[U(−i)[U(−i)−j]⊤x(i)−j]j∣∣∣2=∑i=1n∥∥(I−UU⊤+diag{UU⊤})x(i)∥∥2,
où j'ai écrit tant que pour la compacité, et signifie mettre tous les éléments non diagonaux à zéro. Notez que cette formule ressemble exactement à la première (PRESSE naïve) avec une petite correction! Notez également que cette correction ne dépend que de la diagonale de , comme dans le code PLS_Toolbox. Cependant, la formule est toujours différente de ce qui semble être implémenté dans PLS_Toolbox, et je ne peux pas expliquer cette différence. U d i a g {⋅} U U ⊤U(−i)Udiag{⋅}UU⊤
Mise à jour (février 2018): ci- dessus, j'ai appelé une procédure "correcte" et une autre "approximative" mais je ne suis plus si sûr que cela ait un sens. Les deux procédures ont du sens et je pense que ni l'une ni l'autre n'est plus correcte. J'aime vraiment que la procédure "approximative" ait une formule plus simple. De plus, je me souviens que j'avais un ensemble de données où la procédure "approximative" a donné des résultats qui semblaient plus significatifs. Malheureusement, je ne me souviens plus des détails.
Exemples
Voici comment ces méthodes se comparent pour deux jeux de données bien connus: le jeu de données Iris et le jeu de données Wine. Notez que la méthode naïve produit une courbe décroissante monotone, tandis que les deux autres méthodes produisent une courbe avec un minimum. Notez en outre que dans le cas d'Iris, la méthode approximative suggère 1 PC comme nombre optimal, mais la méthode pseudoinverse suggère 2 PC. (Et en regardant n'importe quel nuage de points PCA pour le jeu de données Iris, il semble que les deux premiers PC portent un signal.) Et dans le cas du vin, la méthode pseudoinverse pointe clairement vers 3 PC, tandis que la méthode approximative ne peut pas décider entre 3 et 5.
Code Matlab pour effectuer une validation croisée et tracer les résultats
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')
tempRepmat(kk,kk) = -1
ligne? La ligne précédente ne garantit-elle pas déjà quetempRepmat(kk,kk)
-1 est égal à? Aussi, pourquoi les inconvénients? L'erreur va être quadrillée de toute façon, alors ai-je bien compris que si les inconvénients sont supprimés, rien ne changera?