らんだむな記憶

blogというものを体験してみようか!的なー

特徴量の次元を低下させるとか(2)

特徴量の次元を低下させるとか - らんだむな記憶の続き。
3D->2Dを試してみる。といっても適当にやっているので、うまくできているんだか...。

考え方としては、
(1)データの平均が原点になるように調節。スケールはどうでもいいので、標準偏差で割るとかはしてない。
(2)データから作る共分散行列を対角化。対角化は直交行列Uをもちいてなされる。
(3)そのうち、上位2つの大きさの固有値に属する固有ベクトルv1, v2をとる。v1, v2は直交行列の相異なる列ベクトルなので直交する(一時独立)。
(4)v1, v2のベクトル積(v = v1 x v2)をとる。vはv1とv2に直交するので要するに、v1, v2が張る平面の法線ベクトルになる。
(5)法線ベクトルvを使って、z = f(x, y) の形で平面の方程式を導いて、x, yにメッシュグリッドを突っ込んでプロット。

X = [
    5, 6, 10;
    2, 2, 8;
    -2, -7, 4;
    8, 3, 2;
    0, -5, 2;
];

% set mean value of feature vectors to 0
mu = mean(X);
for i = 1:size(X(:, 1))
    X(i, :) = X(i, :) - mu;
end

figure('Position',[0, 0, 500, 500]);

% plot adjusted feature vectors
plot3(X(:, 1), X(:, 2), X(:, 3), 'ko','LineWidth', 1, 'MarkerFaceColor', 'y', 'MarkerSize', 7);
hold on;

% axis square
axis([-7 7 -7 7 -7 7], 'square');

% diagonalization of the covarinace matrix
[m, n] = size(X);
Sigma = (1/m) * X' * X;
[U, S, V] = svd(Sigma);

% pick eigen vectors belonging to larger eigen values
K = 2;
U_reduce = U(:, 1:K);

% calculate normal vector of the plane representing subspace by vector product
v = [ U_reduce(2, 1) * U_reduce(3, 2) - U_reduce(3, 1) * U_reduce(2, 2),
      U_reduce(3, 1) * U_reduce(1, 2) - U_reduce(1, 1) * U_reduce(3, 2),
      U_reduce(1, 1) * U_reduce(2, 2) - U_reduce(2, 1) * U_reduce(1, 2) ];

x = y = linspace(-10, 10, 20);
[xx, yy] = meshgrid(x, y);

% plot subspace spanned by eigen vectors

% ax + by + cz = 0 ==> z = (-a/c)x + (-b/c)y
z = -v(1, 1)/v(3, 1) * xx -v(2, 1)/v(3, 1) * yy;
hidden off;
mesh(x, y, z);

% features projected onto the subspace
t = X * U_reduce;
proj = t * U_reduce';
plot3(proj(:, 1), proj(:, 2), proj(:, 3), 'k+','LineWidth', 3, 'Color', 'r', 'MarkerSize', 7);
hold off;

平面のプロットON:
f:id:derwind:20150927042750j:plain

平面のプロットOFF:
f:id:derwind:20150927042757j:plain

あー、赤い点は同一平面上にあるかもなぁとは見えなくもないが、全然分からんなwww
遠近感がなさすぎ。ただ、もともとのデータとして "部分空間" に偏ったものをとってなくて、適当な値を入れただけだから、こんなもんかも。
特徴量の次元を下げる時は本当に偏っているのか評価しないと全然意味分からんことになるよな。そりゃ。

GUIの設定で回転を選べたので、回転して平面を横からも眺めてみた。うーん、どこに射影されているのかピンと来ないが、一応平面上には載ってはいるようだ...。
コードはバグってるし、x, y, z軸のスケールが合ってないわで腐ってたのでコードも図も修正。

平面を真横から観察:
f:id:derwind:20150927042819j:plain

平面上への直交射影な雰囲気が出たと信じたい。

更に、3D->1Dを試してみる。データの偏りがそこまで1次元部分空間に密集しているわけではないので、強引な結果にはなるだろうけど...。
以下のコードを追加する。

% plot subspace spanned by only one eigen vectors
U_reduce2 = U(:, 1);
s = 0:0.1:1;
x2 = linspace(-10, 10, numel(s));
y2 = linspace(-10, 10, numel(s));
z2 = linspace(-10, 10, numel(s));
plot3(U_reduce2(1, 1) * x2, U_reduce2(2, 1) * y2, U_reduce2(3, 1) * z2);

% features projected onto the 1-dimensional subspace
t2 = X * U_reduce2;
proj2 = t2 * U_reduce2';
plot3(proj2(:, 1), proj2(:, 2), proj2(:, 3), 'bo','LineWidth', 1, 'MarkerFaceColor', 'g', 'MarkerSize', 7);

そうして図を描くと...
f:id:derwind:20150927045054j:plain

直線が平面上に含まれ、かつデータから直線上への直交射影が見える。