Mir ist nicht ganz klar, dass Sie fragen, was Sie wirklich brauchen: Ein üblicher Vorverarbeitungsschritt beim maschinellen Lernen ist die Reduzierung der Dimensionalität + das Aufhellen, was bedeutet, PCA durchzuführen und die Komponenten zu standardisieren, sonst nichts. Aber ich werde mich trotzdem auf Ihre Frage konzentrieren, wie sie formuliert ist, weil sie interessanter ist.
Sei die zentrierte n × d- Datenmatrix mit Datenpunkten in Zeilen und Variablen in Spalten. PCA beträgt Singulärwertzergliederung X = U S V ⊤ ≈ U k S k V ⊤ k , wo die Dimensionsreduktion halten wir nur auszuführen k Komponenten. Eine orthogonale "Faktorrotation" dieser Komponenten impliziert die Auswahl einer orthogonalen k × k- Matrix R und deren Einfügung in die Zerlegung: X ≈ U k S k V.X.n × d
X = U S V.⊤≈ U.kS.kV.⊤k,
kk × kR.Hier
√X ≈ U.kS.kV.⊤k= U.kR R.⊤S.kV.⊤k=n−1−−−−−√U⊤kRRotatedstandardized scores⋅R⊤SkV⊤k/n−1−−−−−√Rotated loadings⊤.
sind gedrehte standardisierte Komponenten und der zweite Term repräsentiert gedrehte gedrehte Belastungen. Die Varianz jeder Komponente nach der Drehung ist durch die Summe der Quadrate des entsprechenden Ladevektors gegeben; vor der Drehung ist es einfach
s 2 i /(n-1). Nach der Rotation ist es etwas anderes.
n - 1- -- -- -- -- -√U.kR.s2ich/ (n-1)
Jetzt sind wir bereit, das Problem in mathematischen Begriffen zu formulieren: gegebene nicht gedrehte Belastungen , finde die RotationsmatrixRso, dass die gedrehten LadungenLRin jeder Spalte die gleiche Quadratsumme haben.L = V.kS.k/ n - 1- -- -- -- -- -√R.L R.
Lass es uns lösen. Spaltenquadratsummen nach der Drehung sind gleich den diagonalen Elementen von Dies ist sinnvoll: Durch Rotation werden einfach die Varianzen von Komponenten, die ursprünglich durchs 2 i /(n-1) gegebensind, gemäß dieser Formel zwischen ihnen neu verteilt. Wir müssen sie so umverteilen, dass sie alle gleich ihrem Durchschnittswertμ werden.
( L R )⊤L R = R.⊤S.2n - 1R .
s2ich/ (n-1)μ
Ich glaube nicht, dass es dafür eine geschlossene Lösung gibt, und tatsächlich gibt es viele verschiedene Lösungen. Eine Lösung kann jedoch leicht sequentiell erstellt werden:
- Nehmen Sie die erste Komponente und die te Komponente. Der erste hat die Varianz σ max > μ und der letzte hat die Varianz σ min < μ .kσmax> μσMindest< μ
- Drehen Sie nur diese beiden so, dass die Varianz der ersten gleich . Die Rotationsmatrix in 2D hängt nur von einem Parameter θ ab, und es ist einfach, die Gleichung aufzuschreiben und das erforderliche θ zu berechnen . Tatsächlich R 2D = ( cos θ sin θ - sin θ cos θ ) und nach der Transformation der erste PC erhalten Varianz cos 2 θ ⋅ & sgr; max + sin 2 θ ⋅ & sgr; min = cos 2 θ ⋅ & sgr;μθθ
R.2D= ( cosθ- SündeθSündeθcosθ)
woraus wir sofort cos 2 θ = μ - σ min erhaltencos2θ ⋅ σmax+ Sünde2θ ⋅ σMindest= cos2θ ⋅ σmax+ ( 1 - cos2θ ) ⋅ σMindest= μ ,
cos2θ = μ - σMindestσmax- σMindest.
- Die erste Komponente ist nun fertig, sie hat die Varianz .μ
- Fahren Sie mit dem nächsten Paar fort und nehmen Sie die Komponente mit der größten Varianz und die mit der kleinsten Varianz. Gehe zu # 2.
( k - 1 )R.
Beispiel
S.2/ (n-1)
⎛⎝⎜⎜⎜10000060000300001⎞⎠⎟⎟⎟.
5
51 + ( 10 - 5 ) = 6
53 + ( 6 - 5 ) = 4
54 + ( 6 - 1 ) = 5
Getan.
Ich habe das Matlab-Skript geschrieben, das diesen Algorithmus implementiert (siehe unten). Für diese Eingabematrix lautet die Folge der Drehwinkel:
48.1897 35.2644 45.0000
Komponentenabweichungen nach jedem Schritt (in Zeilen):
10 6 3 1
5 6 3 6
5 5 4 6
5 5 5 5
Die endgültige Rotationsmatrix (Produkt aus drei 2D-Rotationsmatrizen):
0.6667 0 0.5270 0.5270
0 0.8165 0.4082 -0.4082
0 -0.5774 0.5774 -0.5774
-0.7454 0 0.4714 0.4714
( L R )⊤L R.
5.0000 0 3.1623 3.1623
0 5.0000 1.0000 -1.0000
3.1623 1.0000 5.0000 1.0000
3.1623 -1.0000 1.0000 5.0000
Hier ist der Code:
S = diag([10 6 3 1]);
mu = mean(diag(S));
R = eye(size(S));
vars(1,:) = diag(S);
Supdated = S;
for i = 1:size(S,1)-1
[~, maxV] = max(diag(Supdated));
[~, minV] = min(diag(Supdated));
w = (mu-Supdated(minV,minV))/(Supdated(maxV,maxV)-Supdated(minV,minV));
cosTheta = sqrt(w);
sinTheta = sqrt(1-w);
R2d = eye(size(S));
R2d([maxV minV], [maxV minV]) = [cosTheta sinTheta; -sinTheta cosTheta];
R = R * R2d;
Supdated = transpose(R2d) * Supdated * R2d;
vars(i+1,:) = diag(Supdated);
angles(i) = acosd(cosTheta);
end
angles %// sequence of 2d rotation angles
round(vars) %// component variances on each step
R %// final rotation matrix
transpose(R)*S*R %// final S matrix
Hier ist der Code in Python, der von @feilong bereitgestellt wird:
def amoeba_rotation(s2):
"""
Parameters
----------
s2 : array
The diagonal of the matrix S^2.
Returns
-------
R : array
The rotation matrix R.
Examples
--------
>>> amoeba_rotation(np.array([10, 6, 3, 1]))
[[ 0.66666667 0. 0.52704628 0.52704628]
[ 0. 0.81649658 0.40824829 -0.40824829]
[ 0. -0.57735027 0.57735027 -0.57735027]
[-0.74535599 0. 0.47140452 0.47140452]]
http://stats.stackexchange.com/a/177555/87414
"""
n = len(s2)
mu = s2.mean()
R = np.eye(n)
for i in range(n-1):
max_v, min_v = np.argmax(s2), np.argmin(s2)
w = (mu - s2[min_v]) / (s2[max_v] - s2[min_v])
cos_theta, sin_theta = np.sqrt(w), np.sqrt(1-w)
R[:, [max_v, min_v]] = np.dot(
R[:, [max_v, min_v]],
np.array([[cos_theta, sin_theta], [-sin_theta, cos_theta]]))
s2[[max_v, min_v]] = [mu, s2[max_v] + s2[min_v] - mu]
return R
kσ2ichk