โดย: Kan Ouivirach
| Machine Learning
ลด Dimension ด้วย Principal Component Analysis (PCA)
บทความนี้จะมาดูวิธีลด Dimension กันด้วย Principal Component Analysis หรือ PCA กันครับ ออกตัวก่อนว่าบทความนี้ไม่ได้ตั้งใจจะมาอธิบาย PCA นะครับ แต่อยากจะมาให้เห็นว่ามันสามารถเอาไปลด Dimension ได้นะ ลดแล้วข้อมูลจะหน้าตาประมาณไหน 😚ทำไมต้องลด? บาง Dimension อาจจะไม่จำเป็นในการสร้างโมเดลก็เป็นได้ครับ แต่เราไม่แน่ใจว่าจะตัดออกดีไหมอะไรแบบนี้ แล้วก็ถ้ายิ่งมี Dimension เยอะๆ เราอาจจะเจอปัญหา Curse of Dimensionality ก็เป็นได้ คือยิ่งถ้าเรามี Dimension ที่เยอะขึ้น สิ่งที่จะเกิดตามมาคือข้อมูลของเราจะ Sparse มันจะแหว่งๆ ขาดๆ หายๆ ทำให้ส่งผลต่อโมเดลของเราวิธีลด Dimension ก็มีหลายวิธีครับ วิธีที่ใช้กันเยอะก็คงจะไม่พ้น PCA นั่นเอง เรามาเขียนโค้ดไปทำความเข้าใจกันไปดีกว่าครับในบทความนี้จะขอใช้ข้อมูล 2D นะครับ เพื่อความง่าย และเราสามารถพลอตกราฟได้ จะทำให้เข้าใจได้มากขึ้น เรามาเริ่มด้วยการ Import สิ่งที่จำเป็นต้องใช้กันก่อน%matplotlib inlineimport numpy as npimport matplotlib.pyplot as pltเราจะใช้ Numpy สร้างข้อมูลขึ้นมาดู และใช้ Matplotlib เพื่อพลอตกราฟ ส่วน %matplotlib inline เอาไว้สำหรับคนที่ใช้ Jupyter Notebook แล้วอยากให้กราฟขึ้นมาแสดงผลที่ Notebook ของเราครับผมจะสร้างข้อมูล 2 มิติขึ้นมาแบบสุ่มตามนี้mean = [0, 0]cov = [[1, 0], [10, 10]]X = np.random.multivariate_normal(mean, cov, 100)plt.plot(X[:, 0], X[:, 1], 'o', alpha=0.5)plt.axis('equal')กราฟข้อมูล 2 มิติสิ่งที่ PCA นั้นจะพยายามทำ คือมันจะพยายามหาแกนที่สำคัญในข้อมูลของเราที่สามารถอธิบายการกระจายตัวของข้อมูลของเราได้from sklearn.decomposition import PCApca = PCA(n_components=2)pca.fit(X)print(pca.explained_variance_)print(pca.components_)ได้ผลตามนี้ผลที่ได้จากการรัน PCAค่าพวกนี้บอกอะไร? ลองเอามาพลอตดูครับplt.plot(X[:, 0], X[:, 1], 'o', alpha=0.5)for length, vector in zip(pca.explained_variance_, pca.components_): v = vector * 3 * np.sqrt(length) plt.plot([0, v[0]], [0, v[1]], '-k', linewidth=3)plt.axis('equal');จะได้ผลตามนี้กราฟที่นำเอาค่า explained variance กับ components ที่ได้จาก PCA มาพลอตจากรูปข้างต้นจะเห็นได้ว่ามี 2 เวคเตอร์ ทั้ง 2 เวคเตอร์นี้กำลังบอกถึง Direction ของข้อมูล และเวคเตอร์ที่ยาวกว่าจะบอกถึง “ความสำคัญ” ของ Direction ของข้อมูลนั้นๆ ตรงนี้หมายความว่า จริงๆ แล้วเราสามารถเลือกเฉพาะ Direction ที่สำคัญๆ ได้ครับ เราจะตัด Direction ของข้อมูลที่ไม่สำคัญทิ้งไปก็ได้ ข้อมูลที่ไม่สำคัญอาจจะหมายถึงข้อมูลนั้นมี Information ที่น้อย และอาจจะไม่จำเป็นสำหรับการนำเอาไปใช้งานต่อวิธีตัดทิ้งล่ะ? เราตัดโดยการเลือกเก็บข้อมูลส่วนใหญ่ไว้ได้ครับ เช่น เราเลือกเก็บข้อมูล 95% ไว้ จะเขียนโค้ดได้ตามนี้pca = PCA(0.95)X_trans = pca.fit_transform(X)หรือเราจะเลือกเป็นจำนวน Component ก็ได้ ในที่นี้ทั้งหมดมี 2 Components เราอาจจะเลือกแค่ 1pca = PCA(n_components=1)X_trans = pca.fit_transform(X)ค่า X_trans ในที่นี้คือข้อมูลที่สำคัญ 95% ครับ ซึ่งจะมีอยู่ 1 มิติ (จากเดิมมี 2 มิติ) บางคนอาจจะสงสัยว่าจริงๆ เอาตัด Column ทิ้งไปหรือเปล่า คำตอบคือไม่ใช่ครับ จริงๆ แล้วเรา Transform ข้อมูลให้เหลือ 1 มิติ ลองดูโค้ดกับรูปประกอบด้านล่างX_new = pca.inverse_transform(X_trans)plt.plot(X[:, 0], X[:, 1], 'o', alpha=0.2)plt.plot(X_new[:, 0], X_new[:, 1], 'bo', alpha=0.8)plt.axis('equal');ผลที่ได้คือกราฟที่เรา Transform ข้อมูลลงไปบนแกนสำคัญที่เราเลือกจะเห็นได้ว่าเรา Transform ข้อมูล หรือ Project ข้อมูลลงไปบนแกนสำคัญที่เราเลือกนั่นเองก็จะประมาณนี้ครับ การใช้งาน PCA เพื่อลด Dimension ของข้อมูล ลองไปศึกษากันต่อดูนะครับ ทำงานด้านนี้ไม่ช้าก็เร็ว ยังไงก็ได้เจอกับ PCA แน่นอน 😎