機械学習の一般的な前処理手順は、次元削減+ホワイトニングです。つまり、PCAを実行してコンポーネントを標準化するだけで、他には何も求められません。しかし、それでも、それがより興味深いので、私はそれが定式化されるときにあなたの質問に焦点を合わせます。
ましょう中心に列の行及び変数内のデータポイントを有するデータ行列。PCAは、特異値分解ます。ここでは、次元削減を実行するためにコンポーネントのみを保持します。これらの成分の直交「因子回転」は、直交行列を選択し、分解にプラグインすることを意味します。 N × D X = U S V ⊤ ≈ U K S K V ⊤ K、K 、K × K R X ≈ U K S K V ⊤ K = U K R R ⊤ S K V ⊤ K = √Xn×d
X=USV⊤≈UkSkV⊤k,
kk×kR√X≈UkSkV⊤k=UkRR⊤SkV⊤k=n−1−−−−−√U⊤kRRotatedstandardized scores⋅R⊤SkV⊤k/n−1−−−−−√Rotated loadings⊤.
ここで、は回転された標準化されたコンポーネントであり、2番目の項は転置された回転荷重を表します。回転後の各コンポーネントの分散は、対応する荷重ベクトルの二乗和によって与えられます。回転前は、単にです。回転後は何か別のものです。
s 2 i /(n−1)n−1−−−−−√UkRs2i/(n−1)
これで、数学的な用語で問題を定式化する準備が整いました。与えられた非回転負荷で、回転負荷ような回転行列見つけます、各列に等しい二乗和を持っています。 RLRL=VkSk/n−1−−−−−√RLR
解決しよう。回転後の列の平方和は、の対角要素に等しいこれは理にかなっています。回転は、この式に従って、元々によって与えられたコンポーネントの分散を単純に再分配します。それらをすべて平均値と等しくなるように再配布する必要があります。s 2 i /(n−1)μ
(LR)⊤LR=R⊤S2n−1R.
s2i/(n−1)μ
これには閉じた形の解決策はないと思います。実際、さまざまな解決策があります。しかし、ソリューションは簡単に連続して構築できます。
- 最初のコンポーネントと番目のコンポーネントを取ります。最初のものは分散持ち、最後のものは分散持ってい。σ 最大 > μ σ 分 < μkσmax>μσmin<μ
- 最初の2つの分散がと等しくなるように、これら2つだけを回転させます。2Dの回転行列は1つのパラメータのみに依存し、方程式を書き留めて必要なを計算するのは簡単です。実際に、そして変換後、最初のPCは分散そこからすぐにμθθ
R2D=(cosθ−sinθsinθcosθ)
cos2θ⋅σmax+sin2θ⋅σmin=cos2θ⋅σmax+(1−cos2θ)⋅σmin=μ,
cos2θ=μ−σminσmax−σmin.
- これで、最初のコンポーネントが完了しました。分散はです。μ
- 次のペアに進み、分散が最大のコンポーネントと分散が最小のコンポーネントを取ります。後藤#2。
これにより、一連の 2D回転によってすべての分散が等しく再分散されます。これらすべての回転行列を乗算すると、全体的なが得られます。(k−1)R
例
次の行列を検討してください:平均分散はです。私のアルゴリズムは次のように進みます:S2/(n−1)
⎛⎝⎜⎜⎜10000060000300001⎞⎠⎟⎟⎟.
5
ステップ1:PC1とPC4を回転させ、PC1が分散得るようにします。その結果、PC4の分散はます。51+(10−5)=6
ステップ2:PC2(新しい最大分散)とPC3を回転させ、PC2が分散なるようにします。その結果、PC3は分散取得します。53+(6−5)=4
ステップ3:PC4(新しい最大分散)とPC3を回転させ、PC4が分散取得するようにします。その結果、PC3は分散取得します。4 + (6 − 1 )= 554+(6−1)=5
できました。
このアルゴリズムを実装するMatlabスクリプトを記述しました(以下を参照)。この入力行列の場合、回転角度のシーケンスは次のとおりです。
48.1897 35.2644 45.0000
各ステップ後のコンポーネントの差異(行):
10 6 3 1
5 6 3 6
5 5 4 6
5 5 5 5
最終的な回転行列(3つの2D回転行列の積):
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
そして、最終的な行列は次のとおりです。(LR)⊤LR
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
これがコードです:
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
@feilongが提供するPythonのコードは次のとおりです。
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
この問題は次の問題と完全に等価であることに注意してください:分散持つ相関変数を指定して、等しい分散を持つ変数を生成する回転(つまり、新しい直交基底)を見つけます(もちろん、もはや無相関ではありません)。σ 2 I Kkσ2ik