หลังจากโพสต์ที่ยอดเยี่ยมโดย JD Long ในหัวข้อนี้ฉันมองหาตัวอย่างง่ายๆและรหัส R ที่จำเป็นในการผลิต PCA จากนั้นกลับไปที่ข้อมูลต้นฉบับ มันให้สัญชาตญาณทางเรขาคณิตด้วยมือแรกของฉันและฉันต้องการแบ่งปันสิ่งที่ฉันได้รับ ชุดข้อมูลและรหัสสามารถคัดลอกและวางโดยตรงในรูปแบบ R Github
ฉันใช้ชุดข้อมูลที่ฉันพบออนไลน์บนเซมิคอนดักเตอร์ที่นี่และฉันตัดมันเป็นสองมิติ - "เลขอะตอม" และ "จุดหลอมเหลว" - เพื่ออำนวยความสะดวกในการวางแผน
ในฐานะที่เป็นข้อแม้ความคิดล้วนเป็นตัวอย่างของกระบวนการคำนวณ: PCA ถูกนำมาใช้เพื่อลดตัวแปรมากกว่าสองตัวแปรที่ได้รับมาเป็นส่วนประกอบหลักหรือเพื่อระบุ collinearity ในกรณีของคุณสมบัติหลายอย่าง ดังนั้นมันจะไม่พบแอปพลิเคชั่นมากมายในกรณีที่มีตัวแปรสองตัวและไม่จำเป็นต้องคำนวณ eigenvectors ของเมทริกซ์สหสัมพันธ์ตามที่ @amoeba ชี้
นอกจากนี้ฉันตัดทอนข้อสังเกตจาก 44 เป็น 15 เพื่อลดภาระงานในการติดตามแต่ละจุด ผลลัพธ์สุดท้ายคือกรอบข้อมูลโครงกระดูก ( dat1
):
compounds atomic.no melting.point
AIN 10 498.0
AIP 14 625.0
AIAs 23 1011.5
... ... ...
คอลัมน์ "สารประกอบ" แสดงถึงส่วนประกอบทางเคมีของสารกึ่งตัวนำและมีบทบาทของชื่อแถว
สามารถทำซ้ำได้ดังนี้ (พร้อมที่จะคัดลอกและวางบนคอนโซล R):
dat <- read.csv(url("http://rinterested.github.io/datasets/semiconductors"))
colnames(dat)[2] <- "atomic.no"
dat1 <- subset(dat[1:15,1:3])
row.names(dat1) <- dat1$compounds
dat1 <- dat1[,-1]
ข้อมูลถูกปรับสัดส่วนแล้ว:
X <- apply(dat1, 2, function(x) (x - mean(x)) / sd(x))
# This centers data points around the mean and standardizes by dividing by SD.
# It is the equivalent to `X <- scale(dat1, center = T, scale = T)`
ขั้นตอนพีชคณิตเชิงเส้นตาม:
C <- cov(X) # Covariance matrix (centered data)
⎡⎣⎢at_nomelt_pat_no10.296melt_p0.2961⎤⎦⎥
ฟังก์ชั่นความสัมพันธ์cor(dat1)
ให้ผลลัพธ์เดียวกันกับข้อมูลที่ไม่ได้ปรับขนาดเช่นเดียวกับฟังก์ชั่นcov(X)
ในข้อมูลที่ปรับขนาด
lambda <- eigen(C)$values # Eigenvalues
lambda_matrix <- diag(2)*eigen(C)$values # Eigenvalues matrix
⎡⎣⎢λPC11.2964220λPC200.7035783⎤⎦⎥
e_vectors <- eigen(C)$vectors # Eigenvectors
12√⎡⎣⎢PC111PC21- 1⎤⎦⎥
∼ [ - 0.7 , - 0.7 ][ 0.7 , 0.7 ]
e_vectors[,1] = - e_vectors[,1]; colnames(e_vectors) <- c("PC1","PC2")
1.29642170.703578364.8 %eigen(C)$values[1]/sum(eigen(C)$values) * 100
∼ 65 %35.2 %
เราจะรวมทั้ง eigenvectors ที่มีขนาดเล็กของตัวอย่างชุดข้อมูลของเล่นนี้การทำความเข้าใจว่าการไม่รวมหนึ่งของ eigenvector จะส่งผลให้ลดมิติ - แนวคิดเบื้องหลัง PCA
เมทริกซ์คะแนนถูกกำหนดเป็นคูณเมทริกซ์ของข้อมูลที่ปรับขนาด ( X
) โดยเมทริกซ์ของ eigenvectors (หรือ "หมุน") :
score_matrix <- X %*% e_vectors
# Identical to the often found operation: t(t(e_vectors) %*% t(X))
X
[ 0.7 , 0.7 ]Tพีซี1[ 0.7 , - 0.7 ]Tพีซี2
[ 0.7 , - 0.7 ]
1
> apply(e_vectors, 2, function(x) sum(x^2))
PC1 PC2
1 1
ในขณะที่ ( โหลด ) เป็น eigenvectors ปรับขนาดโดยค่าลักษณะเฉพาะ (แม้จะมีคำศัพท์ที่สับสนในฟังก์ชั่น R ที่สร้างขึ้นแสดงด้านล่าง) ดังนั้นการคำนวณสามารถคำนวณได้ดังนี้:
> e_vectors %*% lambda_matrix
[,1] [,2]
[1,] 0.9167086 0.497505
[2,] 0.9167086 -0.497505
> prcomp(X)$rotation %*% diag(princomp(covmat = C)$sd^2)
[,1] [,2]
atomic.no 0.9167086 0.497505
melting.point 0.9167086 -0.497505
เป็นที่น่าสนใจที่จะทราบว่า cloud data ที่ถูกหมุน (พล็อตคะแนน) จะมีความแปรปรวนตามแต่ละองค์ประกอบ (PC) เท่ากับค่าลักษณะเฉพาะ:
> apply(score_matrix, 2, function(x) var(x))
PC1 PC2
53829.7896 110.8414
> lambda
[1] 53829.7896 110.8414
การใช้ฟังก์ชันในตัวผลลัพธ์สามารถทำซ้ำได้:
# For the SCORE MATRIX:
prcomp(X)$x
# or...
princomp(X)$scores # The signs of the PC 1 column will be reversed.
# and for EIGENVECTOR MATRIX:
prcomp(X)$rotation
# or...
princomp(X)$loadings
# and for EIGENVALUES:
prcomp(X)$sdev^2
# or...
princomp(covmat = C)$sd^2
U Σ VTprcomp()
svd_scaled_dat <-svd(scale(dat1))
eigen_vectors <- svd_scaled_dat$v
eigen_values <- (svd_scaled_dat$d/sqrt(nrow(dat1) - 1))^2
scores<-scale(dat1) %*% eigen_vectors
ผลลัพธ์จะแสดงอยู่ด้านล่างด้วยระยะทางแรกจากจุดแต่ละจุดไปยังไอเก็นเวกเตอร์ตัวแรกและบนพล็อตที่สอง
ถ้าเราพล็อตค่าของเมทริกซ์คะแนน (PC1 และ PC2) - ไม่ใช่ "จุดหลอมเหลว" และ "atomic.no" อีกต่อไป แต่เป็นการเปลี่ยนพื้นฐานของจุดพิกัดกับ eigenvectors เป็นระยะทางเหล่านี้จะเป็น ดอง แต่โดยธรรมชาติจะตั้งฉากกับแกน xy:
เคล็ดลับคือตอนนี้ที่จะกู้คืนข้อมูลเดิม คะแนนที่ได้รับการแปลงผ่านการคูณเมทริกซ์ง่ายโดย eigenvector ตอนนี้ข้อมูลถูกหมุนกลับโดยการคูณด้วยการผกผันของเมทริกซ์ของ eigenvector ที่มีการเปลี่ยนแปลงอย่างมีนัยสำคัญในตำแหน่งของจุดข้อมูล ตัวอย่างเช่นสังเกตการเปลี่ยนแปลงในจุดสีชมพู "GaN" ใน Quadrant ด้านซ้าย (วงกลมสีดำในพล็อตซ้ายด้านล่าง) กลับสู่ตำแหน่งเริ่มต้นใน Quadrant ด้านซ้ายล่าง (วงกลมสีดำในพล็อตขวาด้านล่าง)
ในที่สุดเราก็มีข้อมูลต้นฉบับคืนมาในเมทริกซ์ "ที่หมุนแล้ว" นี้:
นอกเหนือจากการเปลี่ยนพิกัดการหมุนของข้อมูลใน PCA แล้วผลลัพธ์จะต้องถูกตีความและกระบวนการนี้มีแนวโน้มที่จะเกี่ยวข้องกับ a biplot
ซึ่งจุดข้อมูลจะถูกพล็อตเกี่ยวกับพิกัด eigenvector ใหม่และตัวแปรดั้งเดิมถูกวางซ้อนเป็น เวกเตอร์ มันเป็นเรื่องที่น่าสนใจที่จะบันทึกความเท่าเทียมกันในตำแหน่งของจุดระหว่างแปลงในแถวที่สองของกราฟการหมุนด้านบน ("คะแนนด้วย xy Axis = Eigenvectors") (ไปทางซ้ายในแปลงที่ติดตาม) และbiplot
(ไปยัง ขวา):
การซ้อนทับของตัวแปรดั้งเดิมเมื่อลูกศรสีแดงนำเสนอเส้นทางไปสู่การตีความPC1
ว่าเป็นเวกเตอร์ในทิศทาง (หรือมีความสัมพันธ์เชิงบวก) กับทั้งสองatomic no
และmelting point
; และPC2
เป็นองค์ประกอบตามค่าที่เพิ่มขึ้นของatomic no
แต่มีความสัมพันธ์เชิงลบกับ melting point
สอดคล้องกับค่าของ eigenvector:
PCA$rotation
PC1 PC2
atomic.no 0.7071068 0.7071068
melting.point 0.7071068 -0.7071068
บทช่วยสอนแบบโต้ตอบนี้โดย Victor Powell ให้ข้อเสนอแนะทันทีเกี่ยวกับการเปลี่ยนแปลงใน eigenvector เมื่อมีการปรับเปลี่ยนคลาวด์ข้อมูล