Saya bekerja di R melalui tutorial PCA yang sangat baik oleh Lindsay I Smith dan saya terjebak di tahap terakhir. Script R di bawah ini membawa kita ke tahap (pada hal.19) di mana data asli sedang direkonstruksi dari Komponen Utama (tunggal dalam hal ini), yang akan menghasilkan plot garis lurus sepanjang sumbu PCA1 (mengingat bahwa data hanya memiliki 2 dimensi, yang kedua sedang sengaja dihapus).
d = data.frame(x=c(2.5,0.5,2.2,1.9,3.1,2.3,2.0,1.0,1.5,1.1),
y=c(2.4,0.7,2.9,2.2,3.0,2.7,1.6,1.1,1.6,0.9))
# mean-adjusted values
d$x_adj = d$x - mean(d$x)
d$y_adj = d$y - mean(d$y)
# calculate covariance matrix and eigenvectors/values
(cm = cov(d[,1:2]))
#### outputs #############
# x y
# x 0.6165556 0.6154444
# y 0.6154444 0.7165556
##########################
(e = eigen(cm))
##### outputs ##############
# $values
# [1] 1.2840277 0.0490834
#
# $vectors
# [,1] [,2]
# [1,] 0.6778734 -0.7351787
# [2,] 0.7351787 0.6778734
###########################
# principal component vector slopes
s1 = e$vectors[1,1] / e$vectors[2,1] # PC1
s2 = e$vectors[1,2] / e$vectors[2,2] # PC2
plot(d$x_adj, d$y_adj, asp=T, pch=16, xlab='x', ylab='y')
abline(a=0, b=s1, col='red')
abline(a=0, b=s2)
# PCA data = rowFeatureVector (transposed eigenvectors) * RowDataAdjust (mean adjusted, also transposed)
feat_vec = t(e$vectors)
row_data_adj = t(d[,3:4])
final_data = data.frame(t(feat_vec %*% row_data_adj)) # ?matmult for details
names(final_data) = c('x','y')
#### outputs ###############
# final_data
# x y
# 1 0.82797019 -0.17511531
# 2 -1.77758033 0.14285723
# 3 0.99219749 0.38437499
# 4 0.27421042 0.13041721
# 5 1.67580142 -0.20949846
# 6 0.91294910 0.17528244
# 7 -0.09910944 -0.34982470
# 8 -1.14457216 0.04641726
# 9 -0.43804614 0.01776463
# 10 -1.22382056 -0.16267529
############################
# final_data[[1]] = -final_data[[1]] # for some reason the x-axis data is negative the tutorial's result
plot(final_data, asp=T, xlab='PCA 1', ylab='PCA 2', pch=16)
Sejauh ini yang saya miliki, dan semuanya baik-baik saja sejauh ini. Tapi saya tidak tahu bagaimana data diperoleh untuk plot terakhir - varian yang dikaitkan dengan PCA 1 - yang oleh Smith diplot sebagai:
Inilah yang saya coba (yang mengabaikan menambahkan cara asli):
trans_data = final_data
trans_data[,2] = 0
row_orig_data = t(t(feat_vec[1,]) %*% t(trans_data))
plot(row_orig_data, asp=T, pch=16)
.. dan mendapat erron:
.. karena saya telah kehilangan dimensi data entah bagaimana dalam perkalian matriks. Saya akan sangat berterima kasih atas ide apa yang salah di sini.
* Edit *
Saya ingin tahu apakah ini formula yang tepat:
row_orig_data = t(t(feat_vec) %*% t(trans_data))
plot(row_orig_data, asp=T, pch=16, cex=.5)
abline(a=0, b=s1, col='red')
Tapi saya agak bingung jika demikian karena (a) Saya mengerti rowVectorFeature
kebutuhan harus direduksi ke dimensi yang diinginkan (vektor eigen untuk PCA1), dan (b) tidak sejalan dengan PCA1 abline:
Setiap pandangan sangat dihargai.
s1
kemiringan Anda dihitung dengan kesalahan (harus , bukan ), itu sebabnya garis merah tidak sangat selaras dengan data pada gambar pertama dan dengan rekonstruksi pada yang terakhir.Jawaban:
Anda hampir sangat di sana dan tertangkap oleh masalah halus dalam bekerja dengan matriks di R. Saya bekerja melalui Anda
final_data
dan mendapatkan hasil yang benar secara mandiri. Kemudian saya melihat lebih dekat kode Anda. Singkatnya, di mana Anda menulisAnda akan baik-baik saja jika Anda telah menulis
sebagai gantinya (karena Anda akan memusatkan perhatian pada bagian2 × 1 2 × 10 1 × 2
trans_data
yang diproyeksikan pada vektor eigen kedua). Karena Anda mencoba mengalikan matriks dengan matriks tetapi R tidak memberi Anda kesalahan. Masalahnya adalah bahwa diperlakukan sebagai . Mencoba akan memberi Anda kesalahan. Berikut ini, mungkin lebih sesuai dengan apa yang Anda maksudkan, juga akan berhasilt(feat_vec[1,])
row_orig_data = t(as.matrix(feat_vec[1,],ncol=1,nrow=2) %*% t(trans_data))
non-conformable arguments
karena mengalikan matriks dengan matriks (perhatikan bahwa Anda bisa menggunakan matriks asli di sini). Tidak perlu melakukannya dengan cara ini, tetapi lebih baik secara matematis karena ini menunjukkan bahwa Anda mendapatkan nilai dari nilai di sisi kanan.2 × 1 1 × 10 20 = 2 × 10 12 = 2 × 1 + 1 × 10
final_data
row_orig_data
Saya telah meninggalkan jawaban asli saya di bawah, karena seseorang mungkin menganggapnya berguna, dan itu menunjukkan mendapatkan plot yang diperlukan. Ini juga menunjukkan bahwa kode bisa sedikit lebih sederhana dengan menyingkirkan beberapa transpos yang tidak perlu: begitu .( XY)T= YTXT
t(t(p) %*% t(q)) = q %*% t
Re edit Anda, saya telah menambahkan garis komponen utama berwarna hijau ke plot saya di bawah ini. Dalam pertanyaan Anda, Anda memiliki kemiringan sebagai bukan .x / y y/ x
Menulis
kemudian untuk mendapatkan data Anda kembali ke basis aslinya yang Anda butuhkan
Anda dapat menghapus bagian-bagian dari data Anda yang diproyeksikan di sepanjang komponen kedua menggunakan
dan Anda kemudian dapat mengubah seperti sebelumnya
Memplot ini pada plot yang sama, bersama dengan garis komponen utama berwarna hijau, menunjukkan kepada Anda bagaimana perkiraannya bekerja.
Mari kita mundur ke apa yang Anda miliki. Baris ini ok
Bit penting di sini adalahY= STX S X Y Y X Y X
feat_vec %*% row_data_adj
yang setara dengan mana adalah matriks vektor eigen dan adalah matriks data Anda dengan data Anda di baris, dan adalah data dalam basis baru. Apa yang dikatakan ini adalah bahwa baris pertama adalah jumlah (baris ditimbang oleh vektor eigen pertama). Dan baris kedua adalah jumlah (deretan ditimbang oleh vektor eigen kedua).Lalu kamu punya
Ini tidak masalah: Anda hanya memusatkan perhatian pada bagian data Anda yang diproyeksikan di sepanjang komponen kedua. Di mana itu salah adalah
Menulis untuk matriks data di basis baru, dengan nol di baris kedua, dan menulis untuk vektor eigen pertama, bagian bisnis dari kode ini turun ke .Y^ Y e1 e1Y^
t(feat_vec[1,]) %*% t(trans_data)
Seperti dijelaskan di atas (ini adalah di mana saya menyadari masalah R halus dan menulis bagian pertama dari jawaban saya), secara matematis Anda mencoba untuk memperbanyak suatu vektor oleh matriks. Ini tidak berfungsi secara matematis. Yang harus Anda lakukan adalah mengambil baris pertama = baris pertama : panggil ini . Kemudian, gandakan dan bersamaan. The th kolom hasil adalah vektor eigen ditimbang dengan 1 koordinat hanya dari titik th di dasar baru, yang adalah apa yang Anda inginkan.2 × 1 2 × 10 Y^ Y y1 e1 y1 saya e1y1 e1 saya
sumber
Saya pikir Anda memiliki ide yang tepat tetapi tersandung fitur jahat R. Di sini sekali lagi potongan kode yang relevan seperti yang Anda nyatakan:
Pada dasarnya
final_data
berisi koordinat titik-titik asli sehubungan dengan sistem koordinat yang ditentukan oleh vektor eigen dari matriks kovarian. Untuk merekonstruksi titik-titik asli kita harus mengalikan masing-masing vektor eigen dengan koordinat transformasi yang terkait, misalnyayang akan menghasilkan koordinat asli dari titik pertama. Di pertanyaan Anda, Anda mengatur komponen kedua dengan benar ke nol
trans_data[,2] = 0
,. Jika Anda kemudian (seperti yang sudah diedit) menghitungAnda menghitung rumus (1) untuk semua poin secara bersamaan. Pendekatan pertama Anda
menghitung sesuatu yang berbeda dan hanya berfungsi karena R secara otomatis menjatuhkan atribut dimensi untuk
feat_vec[1,]
, jadi itu bukan vektor baris lagi tetapi diperlakukan sebagai vektor kolom. Transpos berikutnya membuatnya menjadi vektor baris lagi dan itulah alasan mengapa setidaknya perhitungan tidak menghasilkan kesalahan, tetapi jika Anda membaca matematika, Anda akan melihat bahwa itu adalah sesuatu yang berbeda dari (1). Secara umum itu adalah ide yang baik dalam perkalian matriks untuk menekan menjatuhkan atribut dimensi yang dapat dicapai olehdrop
parameter, misalnyafeat_vec[1,,drop=FALSE]
.Solusi Anda yang diedit tampaknya benar, tetapi Anda menghitung kemiringan jika PCA1 salah. Kemiringan diberikan oleh , karenanyaΔ y/ Δx
sumber
drop=F
argumen.Setelah menjelajahi latihan ini, Anda dapat mencoba cara-cara yang lebih mudah di R. Ada dua fungsi populer untuk melakukan PCA:
princomp
danprcomp
. Theprincomp
fungsi melakukan dekomposisi eigenvalue seperti yang dilakukan dalam latihan Anda. Theprcomp
Fungsi menggunakan dekomposisi nilai singular. Kedua metode akan memberikan hasil yang sama hampir sepanjang waktu: jawaban ini menjelaskan perbedaan R, sedangkan jawaban ini menjelaskan matematika . (Terima kasih kepada TooTone untuk komentar yang sekarang terintegrasi ke dalam posting ini.)Di sini kami menggunakan keduanya untuk mereproduksi latihan di R. Pertama menggunakan
princomp
:Kedua menggunakan
prcomp
:Jelas tanda-tanda dibalik tetapi penjelasan variasi sama.
sumber