PCA (Prin­ci­pal Com­po­nent Analy­sis), veri anal­izi esnasında verise­tinin boyut­larını küçült­mek (dimen­sion reduc­tion) için kul­lanılır. Örneğin n adet özel­liğe (fea­ture) sahip bir verise­tini k (k<n) boyutlu bir verise­tine dönüştür­erek bazı işlem­lerin daha hızlı sonuçlan­ması (örneğin sınıflandırma algo­rit­masının öğrenme (train­ing) süreci) sağlan­abilir. Tabi ki bu işlem­ler esnasında verinin bazı özel­lik­leri kay­bo­la­cak­tır, fakat burada asıl amaç varyansı yük­sek tutarak min­i­mum dere­cede kayı­pla çalışma yapa­bilmek­tir. Ayrıca PCA’in çok boyutlu ver­i­leri küçült­tüğü için, kolay görselleştirme için de kullanılır.

Iris Veriseti ile Basit Bir Örnek

Örneğin iris verise­tini python kul­la­narak 2 boyutlu bir verise­tine dönüştüre­lim. İlk önce verise­tini indirip dataframe oluşturalım.

In [1]:
import pandas as pd

df = pd.read_csv(
    filepath_or_buffer='https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',
    header=None,
    sep=',')

df.columns=['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid', 'class']
df.dropna(how="all", inplace=True)

X = df.ix[:,0:4].values
y = df.ix[:,4].values

df.head()
Out[1]:
sepal_len sepal_wid petal_len petal_wid class
0 5.1 3.5 1.4 0.2 Iris-setosa
1 4.9 3.0 1.4 0.2 Iris-setosa
2 4.7 3.2 1.3 0.2 Iris-setosa
3 4.6 3.1 1.5 0.2 Iris-setosa
4 5.0 3.6 1.4 0.2 Iris-setosa

Şimdi de PCA kul­la­narak iki boyutlu hale getirelim.

In [2]:
from sklearn.preprocessing import StandardScaler
X_std = StandardScaler().fit_transform(X) #burada normalizasyon yapıyoruz

from sklearn.decomposition import PCA
sklearn_pca = PCA(n_components=2)
X_pca = sklearn_pca.fit_transform(X_std)

Python ile işte bu kadar. Az önce iris verise­tinin 4 adet kolo­nun PCA ile işley­erek kul­la­narak 2 adet yeni prin­ci­pal com­po­nent oluş­tu­ruk, yani boyut küçültme yap­tık. Az önce yap­tığımız gibi bunu da bir tablo ile gösterelim.

In [3]:
newDF = pd.DataFrame(X_pca, columns=['pc1', 'pc2'])
newDF['class']=y
newDF.head()
Out[3]:
pc1 pc2 class
0 –2.264542 –0.505704 Iris-setosa
1 –2.086426 0.655405 Iris-setosa
2 –2.367950 0.318477 Iris-setosa
3 –2.304197 0.575368 Iris-setosa
4 –2.388777 –0.674767 Iris-setosa

Iris verise­tini biraz daha yakın­dan tanı­mak için kaç adet farklı class olduğuna da göz atalım.

In [4]:
print newDF['class'].unique()
['Iris-setosa' 'Iris-versicolor' 'Iris-virginica']

Verise­tini 2 boyutlu düzlemde pc1 x eks­eninde, pc2 y eks­eninde ola­cak şek­ilde görselleştire­lim. Ayrıca class değeri ‘Iris-setosa’ olan nok­ta­lara sarı, ‘Iris-versicolor’ olan­lara kır­mızı ve de ‘Iris-virginica’ olan nok­ta­lara da mavi renk verelim.

In [5]:
import numpy as np
import matplotlib.pyplot as plt


N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors=newDF['class'].tolist()
colors = ["yellow" if x=="Iris-setosa" else x for x in colors]
colors = ["red" if x=="Iris-versicolor" else x for x in colors]
colors = ["blue" if x=="Iris-virginica" else x for x in colors]
plt.scatter(newDF['pc1'], newDF['pc2'], c=colors)
plt.show()

Yukarı­daki görselden şunu anlıy­oruz ki ‘Iris-versicolor’ ve ‘Iris-virginica’ sınıfına ait (mavi ve kır­mızı nok­ta­lar) iris çiçek­lerinin özel­lik­leri, diğer sınıf­taki (sarı renk­teki) iris çiçek­lerinin özel­lik­ler­ine göre bir­bir­ler­ine daha fazla benziyorlar.

Kaç adet prin­ci­pal com­po­nent kul­lanacağımızı nasıl belirleyeceğiz?

4 boyutlu bir verise­tini 2 boyut­luya çevir­ince pek de veri kay­bet­mek gibi gözüküyor, peki daha fazla 1000 boyutlu olunca ne ola­cak? Yine 2 prin­ci­pal com­po­nent bize yete­cek mi? Bu soru­lar bize aslında şunu sor­du­ruyor: Kaç adet prin­ci­pal com­po­nent seçe­ceğiz? Sonuçta amacımız veriyi (çok da bir şey kay­betmeden) küçült­mek. Az önce PCA sınıfını kul­la­narak sklearn_pca nes­nesini oluş­tur­muş­tuk ve bununla iki adet prin­ci­pal com­po­nent kul­la­narak ver­im­izi görselleştir­miştik. PCA sınıfı aslında oluşan tüm prin­ci­pal component’lerin her birinin ne kadar varyansı (çeşitlil­iği) içerdiği söyleyebilir.

In [6]:
print sum(sklearn_pca.explained_variance_ratio_)
0.958009753615

Bu sonuca göre verinin %95’ini 2 adet prin­ci­pal com­po­nent kul­la­narak açıklayabiliyoruz.

Eğer henüz kaç tane adet prin­ci­pal com­po­nent kul­lan­mamız gerek­tiğini bilme­sey­dik, PCA sınıfına hep­sini hesaplata­bilirdik ve ardın­dan da bun­ların görselleştir­erek kaç tane prin­ci­pal com­po­nent kul­lanacağımıza karar verebilirdik.

In [7]:
pca = PCA().fit(X_std)
print pca.explained_variance_ratio_
[ 0.72770452  0.23030523  0.03683832  0.00515193]

4 adet prin­ci­pal com­po­nent oluştu, şimdi de cumu­la­tive toplamına bakarak kaç tane prin­ci­pal com­po­nent kul­lanacağımıza karar verelim.

In [8]:
cumVar = np.cumsum(pca.explained_variance_ratio_)
plt.plot([1,2,3,4], cumVar, c='blue')
print cumVar
[ 0.72770452  0.95800975  0.99484807  1.        ]

Bu grafiğin açıkl­ması şudur:

  • 1 prin­ci­pal com­po­nent kul­lanılarak toplam verinin %72.7’sini açıklanabilir
  • 2 prin­ci­pal com­po­nent kul­lanılarak toplam verinin %95.8’i açıklanabilir
  • 3 prin­ci­pal com­po­nent kul­lanılarak toplam verinin %99.4’ü açıklanabilir
  • 4 prin­ci­pal com­po­nent kul­lanılarak toplam verinin %100’ü açıklanabilir

Haf­talık olarak hazır­ladığım veri bil­imi bül­tenler­ine göz attınız mı?