Mereproduksi plot proyeksi analisis diskriminan linier

9

Saya berjuang dengan poin proyeksi dalam analisis diskriminan linier (LDA). Banyak buku tentang metode statistik multivariat menggambarkan gagasan LDA dengan gambar di bawah ini.

Gambar 1

Deskripsi masalahnya adalah sebagai berikut. Pertama, kita perlu menggambar batas keputusan, menambahkan garis tegak lurus dan kemudian memplot proyeksi titik data di atasnya. Saya ingin tahu bagaimana cara menambahkan titik proyeksi ke garis tegak lurus.

Ada saran / petunjuk?

Andrej
sumber
2
Meskipun dalam kasus 2-kelas layak untuk mengambil keputusan boudary pertama dan sumbu diskriminan kedua, logika LDA sebenarnya berlawanan. Anda pertama-tama harus menarik garis diskriminan. Lihat pertanyaan (+ tautan penting dalam komentar di dalamnya) cara menggambar diskriminan. Dan tentang batasan: 1 , 2 .
ttnphns
1
Andrej. Ekstrak vektor eigen. Kita tahu bahwa nilai-nilai diskriminan (skor diskriminan) bergantung padanya. Poin kuncinya sekarang adalah bahwa karena Anda ingin menunjukkan skor diskriminan dalam ruang variabel asli (terpusat), Anda harus membuat konsep diskriminan ketika variabel asli diputar di ruang itu (persis seperti yang kita konsepkan komponen utama). Rotasi adalah penggandaan data terpusat asli dengan matriks rotasi ...
ttnphns
1
(Lanj.) Matriks yang kolomnya adalah vektor eigen dapat dilihat sebagai matriks rotasi jika jumlah kuadrat dari masing-masing kolomnya (yaitu masing-masing vektor eigen) dinormalisasi-satuan. Jadi normalkan vektor eigen dan hitung skor komponen sebagai data terpusat dikalikan dengan vektor eigen ini.
ttnphns
1
(Lanj.) Yang tersisa adalah menunjukkan sumbu diskriminan sebagai garis lurus berujung titik yang mewakili skor diskriminan. Jadi, untuk memplot garis ubin, kita harus menemukan koordinat dari setiap titik ubin ke sumbu asli (variabel). Koordinatnya mudah dihitung: masing-masing koordinat adalah katetus, skor diskriminan adalah hypotenuze, dan cos sudut di antara mereka adalah elemen yang sesuai dari matriks vektor eigen: katet = hipotesis * cos.
ttnphns
1
Andrej, sehingga sumbu diskriminan (yang ke mana titik-titik tersebut diproyeksikan pada Gambar Anda 1) diberikan oleh vektor eigen pertama . Dalam hal hanya dua kelas vektor eigen ini sama dengan , di mana adalah centroid kelas. Normalisasi vektor ini (atau vektor eigen yang diperoleh) untuk mendapatkan vektor sumbu satuan . Ini cukup untuk menggambar sumbu. Untuk memproyeksikan titik (terpusat) ke sumbu ini, Anda cukup menghitung . Di sini adalah proyektor linier ke . Sepertinya Anda hampir sampai, jadi mungkin Anda dapat mengedit posting untuk menjelaskan di mana tepatnya Anda terjebak. W1BW1(m1m2)mivXvvvvv
amoeba

Jawaban:

6

Sumbu diskriminan (titik yang diproyeksikan pada Gambar 1 Anda) diberikan oleh vektor eigen pertama dari . Dalam hal hanya dua kelas vektor eigen ini sebanding dengan , di mana adalah centroid kelas. Normalisasi vektor ini (atau vektor eigen yang diperoleh) untuk mendapatkan vektor sumbu satuan . Ini cukup untuk menggambar sumbu.W1BW1(m1m2)miv

Untuk memproyeksikan titik (terpusat) ke sumbu ini, Anda cukup menghitung . Di sini adalah proyektor linear ke .Xvvvvv

Berikut adalah contoh data dari dropbox Anda dan proyeksi LDA:

Proyeksi LDA

Berikut adalah kode MATLAB untuk menghasilkan gambar ini (seperti yang diminta):

% # 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')
amuba
sumber
Luar biasa! Sangat membantu, satu pertanyaan: mengapa kita hanya tertarik pada vektor eigen pertama?
berkacamata
5

Dan solusi "saya". Banyak terima kasih kepada @ttnphns dan @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

masukkan deskripsi gambar di sini

Andrej
sumber
1
(+1) Plot yang bagus! Apakah Anda mungkin ingin menghapus setidaknya beberapa kutipan kode dari pertanyaan Anda untuk meningkatkan keterbacaan? Terserah Anda, tentu saja.
amoeba
Kode ini tidak dapat direproduksi. Bisakah Anda memperkenalkan variabel x, interceptdan slope?
Roman Luštrik
Tetap; itu berfungsi sekarang.
Andrej
hai, mengapa kita tidak menggunakan 2nd diskriminan?
berkacamata