線形判別分析射影プロットを再現


9

線形判別分析(LDA)で投影点と格闘しています。多変量統計手法に関する多くの本は、LDAの考え方を下の図で示しています。

図1

問題の説明は次のとおりです。まず、決定境界を描き、垂直線を追加し、データポイントの投影をプロットする必要があります。垂線に投影点を追加する方法を知りたい。

提案/ポインタはありますか?


2
2クラスの場合、最初に決定境界を、次に判別軸を描画することは可能ですが、LDAの実際のロジックは反対です。最初に判別線を引く必要があります。判別方法の質問(+コメント内の重要なリンク)をご覧ください。そして、境界に関する:12
ttnphns 2014

1
アンドレジ。固有ベクトルを抽出します。判別式(判別式スコア)の値はそれらに依存していることがわかっています。ここで重要なの、(中央の)元の変数の空間に判別スコアを表示したいので、その空間で回転した元の変数として判別式を概念化する必要があるということです(正確に主成分を概念化するとき)。回転とは、元の中央に配置されたデータに回転行列を乗算したものです...
ttnphns '11 / 08/11

1
(続き)行列が固有ベクトルである行列は、その各列(つまり、各固有ベクトル)の二乗の合計が単位正規化されている場合、回転行列と見なすことができます。したがって、固有ベクトルを正規化し、これらの固有ベクトルで乗算された中央データとしてコンポーネントスコアを計算します。
ttnphns 2014

1
(続き)残っているのは、判別式の軸を、判別式スコアを表す点で並べられた直線として表示することです。したがって、タイル張りの線をプロットするには、元の軸(変数)上の各タイリングポイントの座標を見つける必要があります。座標は簡単に計算できます。各座標はカテーテル、判別スコアはヒポテヌーズ、それらの間の角度のcosは固有ベクトルマトリックスの対応する要素です:cathet = hypoth * cos。
ttnphns 2014

1
Andrej、したがって、判別軸(図1に点が投影される軸)は、の最初の固有ベクトルによって与えられます。クラスが2つだけの場合、この固有ベクトルはに等しく、はクラスの重心です。このベクトル(または取得した固有ベクトル)を正規化して、単位軸ベクトルを取得します。これは軸を描画するのに十分です。(中心の)ポイントをこの軸に投影するには、計算するだけです。ここではへの線形プロジェクターです。もうすぐそこにいるようです。投稿を編集して、行き詰まっている場所を正確に説明できます。W1BW1(m1m2)mivXvvvvv
amoeba 14

回答:


6

判別軸(図1に点が投影される軸)は、の最初の固有ベクトルによって与えられます。クラスが2つだけの場合、この固有ベクトルはに比例しここで、はクラスの重心です。このベクトル(または取得した固有ベクトル)を正規化して、単位軸ベクトルを取得します。これは軸を描画するのに十分です。W1BW1(m1m2)miv

(中心の)ポイントをこの軸に投影するには、単に計算します。ここで、はへの線形プロジェクターです。Xvvvvv

以下は、ドロップボックスとLDAプロジェクションからのデータサンプルです。

LDAプロジェクション

以下は、この図を作成するためのMATLABコードです(要求されたとおり)。

% # data taken from your example
X = [-0.9437    -0.0433; -2.4165    -0.5211; -2.0249    -1.0120; ...
    -3.7482 0.2826; -3.3314 0.1653; -3.1927 0.0043; -2.2233 -0.8607; ...
    -3.1965 0.7736; -2.5039 0.2960; -4.4509 -0.3555];
G = [1 1 1 1 1 2 2 2 2 2];

% # overall mean
mu = mean(X);

% # loop over groups
for g=1:max(G)
    mus(g,:) = mean(X(G==g,:)); % # class means
    Ng(g) = length(find(G==g)); % # number of points per group
end

Sw = zeros(size(X,2)); % # within-class scatter matrix
Sb = zeros(size(X,2)); % # between-class scatter matrix
for g=1:max(G)
    Xg = bsxfun(@minus, X(G==g,:), mus(g,:)); % # centred group data
    Sw = Sw + transpose(Xg)*Xg;
    Sb = Sb + Ng(g)*(transpose(mus(g,:) - mu)*(mus(g,:) - mu));
end

St = transpose(bsxfun(@minus,X,mu)) * bsxfun(@minus,X,mu); % # total scatter matrix
assert(sum(sum((St-Sw-Sb).^2)) < 1e-10, 'Error: Sw + Sb ~= St')

% # LDA
[U,S] = eig(Sw\Sb);

% # projecting data points onto the first discriminant axis
Xcentred = bsxfun(@minus, X, mu);
Xprojected = Xcentred * U(:,1)*transpose(U(:,1));
Xprojected = bsxfun(@plus, Xprojected, mu);

% # preparing the figure
colors = [1 0 0; 0 0 1];
figure
hold on
axis([-5 0 -2.5 2.5])
axis square

% # plot discriminant axis
plot(mu(1) + U(1,1)*[-2 2], mu(2) + U(2,1)*[-2 2], 'k')
% # plot projection lines for each data point
for i=1:size(X,1)
    plot([X(i,1) Xprojected(i,1)], [X(i,2) Xprojected(i,2)], 'k--')
end
% # plot projected points
scatter(Xprojected(:,1), Xprojected(:,2), [], colors(G, :))
% # plot original points
scatter(X(:,1), X(:,2), [], colors(G, :), 'filled')

すばらしい!とても役立つ、1つの質問:なぜ私たちは最初の固有ベクトルだけに興味があるのですか?
2018

5

そして「私の」解決策。@ttnphnsと@amoebaに感謝します。

set.seed(2014)
library(MASS)
library(DiscriMiner) # For scatter matrices
library(ggplot2)
library(grid)
# Generate multivariate data
mu1 <- c(2, -3)
mu2 <- c(2, 5)
rho <- 0.6
s1 <- 1
s2 <- 3
Sigma <- matrix(c(s1^2, rho * s1 * s2, rho * s1 * s2, s2^2), byrow = TRUE, nrow = 2)
n <- 50
# Multivariate normal sampling
X1 <- mvrnorm(n, mu = mu1, Sigma = Sigma)
X2 <- mvrnorm(n, mu = mu2, Sigma = Sigma)
X <- rbind(X1, X2)
# Center data
Z <- scale(X, scale = FALSE)
# Class variable
y <- rep(c(0, 1), each = n)

# Scatter matrices
B <- betweenCov(variables = X, group = y)
W <- withinCov(variables = X, group = y)

# Eigenvectors
ev <- eigen(solve(W) %*% B)$vectors
slope <- - ev[1,1] / ev[2,1]
intercept <- ev[2,1]

# Create projections on 1st discriminant
P <- Z %*% ev[,1] %*% t(ev[,1])

# ggplo2 requires data frame
my.df <- data.frame(Z1 = Z[, 1], Z2 = Z[, 2], P1 = P[, 1], P2 = P[, 2])

plt <- ggplot(data = my.df, aes(Z1, Z2))
plt <- plt + geom_segment(aes(xend = P1, yend = P2), size = 0.2, color = "gray")
plt <- plt + geom_point(aes(color = factor(y)))
plt <- plt + geom_point(aes(x = P1, y = P2, colour = factor(y)))
plt <- plt + scale_colour_brewer(palette = "Set1")
plt <- plt + geom_abline(intercept = intercept, slope = slope, size = 0.2)
plt <- plt + coord_fixed()
plt <- plt + xlab(expression(X[1])) + ylab(expression(X[2]))
plt <- plt + theme_bw()
plt <- plt + theme(axis.title.x = element_text(size = 8),
                   axis.text.x  = element_text(size = 8),
                   axis.title.y = element_text(size = 8),
                   axis.text.y  = element_text(size = 8),
                   legend.position = "none")
plt

ここに画像の説明を入力してください


1
(+1)素敵なプロット!読みやすさを向上させるために、質問からコードの抜粋の少なくとも一部を削除しますか?もちろんそれはあなた次第です。
amoeba 14

このコードは再現できません。あなたは、変数を導入することができxinterceptおよびslope
RomanLuštrik2014年

修繕; それは今動作します。
Andrej 2014年

こんにちは、なぜ2次判別式を使用しないのですか?
2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.