Principal Components Analysis (PCA) ต่างจาก Factor Analysis (FA) ยังไง ??? (ตอนที่ 1)

Pop Phiphat
5 min readJun 23, 2018

--

ความรู้เบื้องต้นที่ใช้ในการทำ PCA กับ FA

  1. พื้นฐานสถิติ อย่างเช่น Variance , Covariance
  2. พื้นฐานเกี่ยวกับการคำนวณ Matrix

จริงๆทั้ง 2 วิธีเป็นเทคนิคในการทำ dimension reduction ประเภท Feature Extraction เหมือนกันทำให้เราได้ จำนวนตัวแปรใหม่ที่มีขนาดลดลง แต่สิ่งที่แตกต่างกัน คือ PCA เป็นการสร้าง component ใหม่ โดยการหา linear combination จากตัวแปรตั้งต้น เพื่ออธิบาย information ให้ได้มากที่สุด ส่วน FA เป็นการค้นหา latent factor (factor ที่ซ่อนเร้น) จากตัวแปรที่มีความสัมพันธ์ร่วมกัน (co-variance ระหว่าง ตัวแปร) พูดให้ฟังดูง่ายขึ้นก็คือจับตัวแปรที่มีความสัมพันธ์กันสูงๆให้อยู่ใน factor เดียวกันนั่นเอง เรามาดูในรายละเอียดของแต่ละตัวกันดีกว่าครับ

มาดู Principal Components Analysis (PCA) กันก่อน

จุดประสงค์ในการทำ PCA

  1. แก้ปัญหา high-dimensional data ข้อมูลที่มีจำนวนตัวแปร เยอะกว่าจำนวนตัวอย่าง (n น้อยกว่า p) จะเจอปัญหานี้เยอะในงานพวก image processing งานวิเคราะห์ทางการแพทย์ เช่น วิเคราะห์ Gene Expression ของผู้ป่วยโรคมะเร็ง
  2. เพื่อลดจำนวนของตัวแปรลง โดยที่ไม่อยากจะตัดตัวแปรที่เราได้ทิ้ง (ไม่อยากจะเสีย information) แต่อาจจะทำให้อธิบายหรือตีความผลการวิเคราะห์ได้ยากขึ้นหน่อยนึง
  3. ลดปัญหาตัวแปรมีความสัมพันธ์กัน (Multicollinearity) เพราะ component แต่ละตัวจะไม่มีความสัมพันธ์กัน

PCA จะทำการสร้างตัวแปรขึ้นมาใหม่เรียกว่า component โดยแต่ละ component จะไม่มีความสัมพันธ์กัน โดย component ตัวแรกจะมีค่า variance สูงที่สุด ซึ่งจะอธิบาย information ได้มากที่สุด และตัวถัดๆ ไปก็จะมี variance ลดหลั่นกันไปตามลำดับ โดยปกติจำนวน component ที่เหมาะสมที่ถูกเลือกมาใช้จะครอบคลุม variance ประมาณ 80–90%

แล้วทำไม variance ต่อ total population variance ของตัวแปรใหม่ (component) ยิ่งเยอะยิ่งให้ information เยอะ?

ผมจะลองยกตัวอย่างเพื่อให้เข้าใจได้ง่ายขึ้น สมมติ เราจะทำการศึกษาพฤติกรรมการซื้อสิ้นค้าของคน โดยสุ่มตัวอย่าง มาทำการวิเคราะห์ กรณีแรก เราศึกษาพฤติกรรมการซื้อสิ้นค้าจากตัวอย่างของคนที่มีเงินเดือนในช่วง 20,000 ถึง 30,000 บาท กับกรณีที่ 2 ศึกษาจากตัวอย่างของคนที่มีเงินเดือนในช่วงตั้งแต่ 5,000 ถึง 100,000 บาท ในกรณีแรกจะเห็นว่า variance ของตัวแปรเงินเดือนนั้นต่ำกว่ากรณีที่ 2 มาก ซึ่งในกรณีแรกเราอาจจะพบว่า การซื้อสินค้าของคนกลุ่มนี้ก็จะมีลักษณะคล้ายๆ กัน ส่วนกรณีที่ 2 จะได้พฤติกรรมการซื้อสินค้าที่หลากหลายกว่า ซึ่งก็คือ information ที่มีเยอะมากกว่านั่นเอง

ผมไม่ได้บอกว่าการมี variance เยอะจะดีเสมอไปนะครับ มันดีในกรณีของการทำ PCA เพราะเราต้องการสร้าง component ที่สามารถจะอธิบายข้อมูลได้มากๆ แต่ถ้า variance ดันมีอยู่เยอะในตัวแปรที่เราจะ predict ละก็ ผลการ predict ของเราก็จะมี error พุ่งปรี๊ดกันเลยที่เดียว

ถามว่าเราสนใจใช้เพียงแค่ variance ของตัวแปรในการวัดปริมาณของ information ที่เราจะได้ใช่มั้ย ?

ตอบเลยครับว่าไม่ใช่อย่างแน่นอน ลองนึกดูว่า สมมติเรามีตัวแปร 2 ตัว ทั้งคู่มี variance เยอะโคตรๆ แต่ตัวแปร 2 ตัวนี้คล้ายกันแบบสุดๆ Correlation เกือบจะเป็น 1 เรียกได้ว่าเหมือนกันอย่างกับแกะ ถ้ามันเป็นแบบนี้ information ที่เราจะได้จากตัวแปรทั้ง 2 ตัวจะต่างกับ ที่เราได้จากตัวเดียวมั้ย? เรียกได้ว่าอาจจะหาความแตกต่างของ information ไม่เจอ แสดงว่าใช้แค่ตัวแปรตัวแรกก็เพียงพอแล้ว เอาตัวแปรตัวที่ 2 เข้ามาก็ไม่ได้ให้ information อะไรเพิ่มขี้น

ดังนั้นการทำ PCA เพื่อสร้าง component ใหม่ขึ้นมานั้นเราไม่ได้ดูแค่เฉพาะ variance เท่านั้น เรายังต้องทำให้ component แต่ละ component ของเราไม่มีความสัมพันธ์กันด้วย (Co-variance Matrix ของ component จะเป็น Diagonal Matrix)

Source: http://slideplayer.com/slide/10391622

มาดูหลักการทางคณิตศาสตร์และสถิติกันบ้าง

การหา component จะหาได้จากสมการ Y=WX

Y คือ Matrix ของ component ขนาด p x 1
W คือ Matrix ค่าสัมประสิทธ์ของตัวแปร X ขนาด p x p และ
X ก็คือ Matrix ของตัวแปรตั้งต้น ขนาด p x 1

กระจายออกมาเป็น linear combination ได้รูปนี้

จากรูปนี้เราจะเห็นว่าการทำ PCA จะเป็นการสร้าง Component ใหม่ขึ้นมาโดยทำการรวม information ของ ตัวแปร X ทั้งหมดที่เรามีอยู่โดยไม่ได้ตัดตัวแปรทิ้งไปสักตัว ทำให้เราไม่เสีย information ไม่เหมือนกับการทำ Feature Selection หรือ Feature Elimination ที่เสีย information (ตัวแปร) ที่เราเก็บมาไปบางส่วน

เนื่องจากเราต้องการสร้าง component ใหม่ที่ไม่มีความสัมพันธ์กัน ตามทฤษฎี Diagonalization (https://en.wikipedia.org/wiki/Diagonalizable_matrix) บอกว่า Matrix ที่สมมาตร (Symmetry Matrix) สามารถเขียนให้อยู่ในรูปมการด้านล่าง ในกรณีของเราคือ Co-variance Matrix ของตัวแปร X (S มีขนาด p x p)

Matrix W จะเป็น Orthogonal Matrix ขนาด p x p

D เป็น Diagonal Matrix ขนาด pxp

Source: http://slideplayer.com/slide/10391622

Matrix D นี่แหละคือ Co-variance Matrix ของ component Cov(Y) = D
ตอนนี้เรายังไม่รู้ค่า P จากแต่สมการ S=WDWˉ¹ ลองย้ายข้างดูจะได้เป็น SWˉ¹=DWˉ¹ พบว่า Pˉ¹(หรือ Pᵀ ) มันก็คือ Eigenvector นั่นเอง (ใช้เป็นค่าสัมประสิทธ๋ของตัวแปร X แต่เวลาใช้ก็ transpose ก่อน เพราะในสมการมัน คือ Y=WX แต่ Eigenvector ที่เราได้มามันคือ Pᵀ) ส่วน D ก็เป็น Eigenvalue

พอเรารู้หลักการแล้ว เราก็มาลองทำกันเลยดีกว่า

ผมใช้ข้อมูลรูปหน้าคนมาลองทำ PCA ซึ่งข้อมูลเอามาจาก Kaggle ตามลิ๊งนี้เลยครับ

Source : https://www.kaggle.com/c/facial-keypoints-detection/data

เริ่มแรกเราต้องทำการอ่าน data ที่เราจะวิเคราะห์

file <- “D:/Ingenio/Dataset/training/facetraining.csv”
pictures <- read.csv(file)
# ผมจะใช้แค่ 100 รูปในการทำ PCA
data = pictures[1:100,]
im.train <- as.character(data$Image)
library(doParallel)
registerDoParallel(cores=4)
im.train <- foreach(im = im.train, .combine=rbind) %dopar% {
as.integer(unlist(strsplit(im, " ")))
}
# แสดงผลข้อมูล
options(repr.plot.width=8, repr.plot.height=2)
par(mfrow=c(2,8),mar=c(0,0,0,0) )
for(i in 1:16){
im2 <- matrix(data=rev(im.train[i,]), nrow=96, ncol=96)
plot2 <- image(1:96, 1:96, im2, col=gray((0:255)/255),xaxt='n'
,yaxt='n', ann=FALSE)
}
X <- t(t(im.train))

แล้วทำการหา Co-variance (หรือจะหา Correlation) ของตัวแปร X กันก่อน เพื่อดูความคล้ายคลึงกันของตัวแปร กรณีที่จะใช้ Co-variance ตัวแปรต้องมีหน่วยเดียวกัน หรือเมื่อ variance ของตัวแปร X มีความสำคัญหรือใช้สื่อความหมายอะไรบางอย่าง ส่วนถ้าตัวแปรเรามีหน่วยต่างกัน (เช่น ตัวแปร น้ำหนัก หน่วยเป็น กิโลกรัม กับ ตัวแปร ระยาทาง หน่วยเป็น เมตร) ก็ให้ทำ Standardized ก่อนแล้วใช้ Correlation แทน (Correlation น่าจะปลอดภัยกว่า)

#ทำการหา Co-variance ของตัวแปรจาก data
S <- cov(X)

หลังจากที่ได้ Covariance Matrix (หรือ Correlation Matrix) มาแล้วเราก็มาหา Eigenvector กับ Eigenvalue ของ Covariance Matrix กัน ซึ่ง Eigenvalue ก็คือค่า variance ของ component ส่วน Eigenvector ก็คือค่าสัมประสิทธิ์ของตัวแปร X ตามที่อธิบายไว้ข้างบน

#ทำการหา Eigenvector กับ Eigenvalue ของ Co-variance Matrix
Eigen <- eigen(S)
eigenvalue <- Eigen$values
eigenvector <- Eigen$vectors

สุดท้ายเราก็มาดูว่า component ที่สร้างมาแต่ละตัวใช้อธิบาย variance ของ population ได้กี่เปอร์เซ็นต์ ส่วนว่าจะใช้กี่ตัวก็เอา เปอร์เซ็นต์ที่หามาได้ บวกกัน ถ้าได้เกิน 80–90 % ก็ถือว่าใช้ได้แล้วครับ

#สร้างกราฟ Scree plot กับ Cumulative plot
options(repr.plot.width=8, repr.plot.height=4)
par(mfrow=c(1,2),mar=c(3,3,3,3) )
per_var <- eigenvalue/sum(eigenvalue)*100
cum_var <- cumsum(per_var)
plot(per_var[1:150], xlab = “Component number”,
ylab = “Component variance”, type = “l”, main = “Scree diagram”)
plot(cum_var[1:150], xlab = “Component number”,
ylab = “Component variance”, type = “l”, main = “cumulative diagram”)

จาก Scree plot กับ Cumulative plot ถ้าเราใช้ component จำนวน 100 ก็จะสามารถอธิบาย information ของข้อมูลเราเกือบ 100% มาลอง plot Eigenvector ที่เราได้ดีกว่าว่าจะมีหน้าตาออกมาประมาณไหน

options(repr.plot.width=8, repr.plot.height=8)
par(mfrow=c(10,10),mar=c(0,0,0,0) )
for (i in 1:100) {
t1 <- matrix(data=rev(t(eigenvector[,i])), nrow=96, ncol=96)
plot1 <- image(1:96, 1:96, t1, col=gray((0:255)/255),xaxt=’n’,yaxt=’n’, ann=FALSE)
}

ซึ่งปกติ Eigenvector พวกนี้จะถูกเรียกว่า EigenFace ในการทำ face recognition

เราลองเอา component ที่เราได้มาสร้างกลับเป็นหน้าดูว่าจะได้เหมือนต้นฉบับมั้ย

# ลองใช้ component 20, 50, 100 ตัวมาสร้างกลับเป็นหน้าคน
library(matlib)
PCA20 <- X%*%eigenvector[,1:20]
PCA50 <- X%*%eigenvector[,1:50]
PCA100 <- X%*%eigenvector[,1:100]
options(repr.plot.width=8, repr.plot.height=6)
par(mfrow=c(3,4),mar=c(2,2,2,2) )
# ลอง plot ดูสัก 2 หน้า
for (i in 1:2){
t1 <- matrix(data=rev(im.train[i,]), nrow=96, ncol=96)
plot1 <- image(1:96, 1:96, t1, col=gray((0:255)/255))
title(main = "Original")
pca20 <- matrix(data=rev(PCA20[i,]%*%t(eigenvector[,1:20])), nrow=96, ncol=96)
pcaplot1 <- image(1:96, 1:96, pca20, col=gray((0:255)/255))
title(main = "PCA20")
pca50 <- matrix(data=rev(PCA50[i,]%*%t(eigenvector[,1:50])), nrow=96, ncol=96)
pcaplot2 <- image(1:96, 1:96, pca50, col=gray((0:255)/255))
title(main = "PCA50")
pca100 <- matrix(data=rev(PCA[i,]%*%t(eigenvector[,1:100])), nrow=96, ncol=96)
pcaplot4 <- image(1:96, 1:96, pca100, col=gray((0:255)/255))
title(main = "PCA100")
}

พอ reconstruct กลับมาแล้วยังดูไม่เนียนเท่าไหร่ เรามาลอง process data เพิ่มขึ้นหน่อยโดยการเอารูปแต่ละรูปมาลบกับค่าเฉลี่ย

#หาค่าเฉลี่ยก่อน
options(repr.plot.width=3, repr.plot.height=3)
par(mfrow=c(1,1),mar=c(2,2,2,2) )
average_face <- colMeans(im.train)
t1 <- matrix(data=rev(average_face), nrow=96, ncol=96)
plot1 <- image(1:96, 1:96, t1, col=gray((0:255)/255))
title(main = “Average Face”)
substract_face <- apply(im.train,1,’-’,average_face)
S2 <- cov(t(substract_face))
dim(S2)
s_Eigen <- eigen(S2)
s_eigenvalue <- s_Eigen$values
s_eigenvector <- s_Eigen$vectors
S_PCA20 <- t(substract_face)%*%s_eigenvector[,1:20]
S_PCA50 <- t(substract_face)%*%s_eigenvector[,1:50]
S_PCA100 <- t(substract_face)%*%s_eigenvector[,1:100]
options(repr.plot.width=8, repr.plot.height=6)
par(mfrow=c(3,4),mar=c(2,2,2,2) )
for (i in 1:2){
# ตอน reconstruct เราต้องบวกค่า average ที่เราลบออกไปตอนแรกกลับมาด้วย
t1 <- matrix(data=rev(t(substract_face[,i])+t(average_face)), nrow=96, ncol=96)
# t1 <- matrix(data=rev(apply(t(substract_face[,i]),1,'+',t(average_face))), nrow=96, ncol=96)
plot1 <- image(1:96, 1:96, t1, col=gray((0:255)/255))
title(main = "Original")

s_pca20 <- matrix(data=rev((S_PCA20[i,]%*%t(s_eigenvector[,1:20]))+t(average_face)), nrow=96, ncol=96)
pcaplot1 <- image(1:96, 1:96, s_pca20, col=gray((0:255)/255))
title(main = "PCA20")
s_pca50 <- matrix(data=rev((S_PCA50[i,]%*%t(s_eigenvector[,1:50]))+t(average_face)), nrow=96, ncol=96)
pcaplot2 <- image(1:96, 1:96, s_pca50, col=gray((0:255)/255))
title(main = "PCA50")
s_pca100 <- matrix(data=rev((S_PCA100[i,]%*%t(s_eigenvector[,1:100]))+t(average_face)), nrow=96, ncol=96)
pcaplot4 <- image(1:96, 1:96, s_pca100, col=gray((0:255)/255))
title(main = "PCA100")
}

ดูเนียนขึ้นมาละ ตอนนี้เอาไว้แค่นี้ก่อน หวังว่า story นี้จะช่วยให้ทุกท่านเข้าใจ PCA มากขึ้น โดยในตอนหน้า ผมจะมาต่อเรื่อง Factor Analysis โดยจะแสดงให้เห็นถึงความแตกต่างระหว่าง Factor Analysis กับ Principal Component Analysis

--

--

Pop Phiphat

Do what you need to do and enjoy life as it happens… “John Scalzi”