Мне не совсем ясно, что вы спрашиваете, что вам действительно нужно: обычным этапом предварительной обработки в машинном обучении является уменьшение размерности + отбеливание, что означает выполнение PCA и стандартизацию компонентов, и ничего больше. Но я все же остановлюсь на вашем вопросе в том виде, как он сформулирован, потому что он более интересен.
Пусть - центрированная матрица данных n × d с точками данных в строках и переменными в столбцах. РСА составляет сингулярное разложение Х = U S V ⊤ ≈ U K S K V ⊤ K , где для выполнения сокращения размерности мы держать только K компоненты. Ортогональное «вращение фактора» из этих компонентов предполагает выбор ортогонального K × K матрицы R и подключить его к разложению: X ≈ U K S к VИксn × d
X = U S V⊤≈ UКSКВ⊤К,
Кк × крВот
X ≈ UКSКВ⊤К= UКR R⊤SКВ⊤К=n−1−−−−−√U⊤kRRotatedstandardized scores⋅R⊤SkV⊤k/n−1−−−−−√Rotated loadings⊤.
- повернутые стандартизированные компоненты, а второй член представляет повернутые нагрузки, транспонированные. Дисперсия каждого компонента после вращения задается суммой квадратов соответствующего вектора нагрузки; перед вращением это просто
s 2 i /(n-1). После вращения это что-то еще.
n−1−−−−−√UkRs2i/(n−1)
Теперь мы готовы сформулировать задачу в математических терминах: с учетом неповрежденных нагрузок , найдите матрицу вращенияRтак, чтобы вращаемые нагрузки,LR, имели равную сумму квадратов в каждом столбце.L = VКSК/ n - 1-----√рL R
Давайте решать это. Суммы столбцов квадратов после вращения равны диагональным элементам Это имеет смысл: вращение просто перераспределяет дисперсии компонентов, которые первоначально определяются какs 2 i /(n-1), между ними, согласно этой формуле. Нам нужно перераспределить их так, чтобы все они стали равными их среднему значениюμ.
( L R )⊤L R = R⊤S2n - 1R .
s2я/ (n-1)μ
Я не думаю, что есть закрытое решение этой проблемы, и на самом деле есть много разных решений. Но решение может быть легко построено последовательным способом:
- Возьмите первый компонент и компонент. Первый из них имеет дисперсию сг макс > М , а последний имеет дисперсию сг мин < μ .КσМаксимум> μσмин< μ
- Вращайте только эти два, так что дисперсия первого становится равной . Вращение матрицы в 2D зависит только от одного параметра θ, и легко записать уравнение и вычислить необходимое θ . Действительно, R 2D = ( Cos & thetas грех & thetas ; - грех & thetas ; соз & thetas ; ) и после преобразования первого ПК будет получить дисперсию сов 2 & thetas ; ⋅ сг макс + грех 2 & thetas ; ⋅ сг мин = соз 2 & thetas ; ⋅ сгμθθ
р2D= ( потому чтоθ- грехθгрехθсозθ)
из которых мы сразу получаем соз 2 & thetas ; = ц - сг минсоз2θ ⋅ σМаксимум+ грех2θ ⋅ σмин= cos2θ ⋅ σМаксимум+ ( 1 - cos2θ ) ⋅ σмин= μ ,
соз2θ = μ - σминσМаксимум- σмин,
- Первый компонент готов, он имеет дисперсию .μ
- Перейдите к следующей паре, взяв компонент с наибольшей дисперсией и компонент с наименьшей дисперсией. Перейти к # 2.
Это перераспределит все дисперсии одинаково по последовательности 2D поворотов. Умножение всех этих матриц вращения даст общее значение R( к - 1 )р .
пример
S2/ (n-1)
⎛⎝⎜⎜⎜10000060000300001⎞⎠⎟⎟⎟,
5
51 + ( 10 - 5 ) = 6 .
53 + ( 6 - 5 ) = 4
54 + ( 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
Конечная матрица вращения (произведение трех 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
( 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
Вот код:
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
Вот код на Python, предоставленный @feilong:
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яК