PCA ile ilgili iki soru, iki cevap
Sitede ödevlere cevap vermiyorum. Fakat site içeriği ile ilgili anlaşılamayan konuları aydınlatmayı seviyorum. Değerli okurumuz F. Gökçimen'in sorduğu iki soruya ilişkin cevapları altta bulabilirsiniz. İsterseniz siz de yorum kısmından düşüncelerinizi ekleyebilirsiniz.
Soru 1: PCA'de kullandığınız matlab kodlarına, princomp komutu alternatif olabilir mi? Farkı nedir?
Cevap: Sonuç olarak aralarında pozitif/negatif işareti dışında bir fark yok. princomp
fonksiyonu daha okunabilir, anlaşılabilir bir fonksiyon. Eğer MATLAB'ınızda yoksa svd
ile aynısını kolaylıkla yapabilirsiniz. Örnek üstünden bakalım:
load hald; X = ingredients; % Veri X olsun. Her satırda bir örnek var. X
X = 7 26 6 60 1 29 15 52 11 56 8 20 11 31 8 47 7 52 6 33 11 55 9 22 3 71 17 6 1 31 22 44 2 54 18 22 21 47 4 26 1 40 23 34 11 66 9 12 10 68 8 12
Öncelikle halihazırdaki fonksiyonu kullanalım:
[pc1,score1] = princomp(X)
pc1 = -0.0678 -0.6460 0.5673 0.5062 -0.6785 -0.0200 -0.5440 0.4933 0.0290 0.7553 0.4036 0.5156 0.7309 -0.1085 -0.4684 0.4844 score1 = 36.8218 -6.8709 -4.5909 0.3967 29.6073 4.6109 -2.2476 -0.3958 -12.9818 -4.2049 0.9022 -1.1261 23.7147 -6.6341 1.8547 -0.3786 -0.5532 -4.4617 -6.0874 0.1424 -10.8125 -3.6466 0.9130 -0.1350 -32.5882 8.9798 -1.6063 0.0818 22.6064 10.7259 3.2365 0.3243 -9.2626 8.9854 -0.0169 -0.5437 -3.2840 -14.1573 7.0465 0.3405 9.2200 12.3861 3.4283 0.4352 -25.5849 -2.7817 -0.3867 0.4468 -26.9032 -2.9310 -2.4455 0.4116
Şimdi kendimiz yazalım. Önce her satırdan ortalamayı çıkaralım. Ardından svd
yapalım. Dikkat, burada pc2
değişkeni aslında V
'ye denk gelen yerde, çünkü örnekler satırlarda. Eğer örnekler sütunlarda olsaydı, [pc2, ~, ~]
biçiminde olacaktı.
X = X - repmat(mean(X,1), size(X,1), 1); [~, ~, pc2] = svd(X, 'econ'); score2 = X * pc2
pc2 = 0.0678 0.6460 -0.5673 0.5062 0.6785 0.0200 0.5440 0.4933 -0.0290 -0.7553 -0.4036 0.5156 -0.7309 0.1085 0.4684 0.4844 score2 = -36.8218 6.8709 4.5909 0.3967 -29.6073 -4.6109 2.2476 -0.3958 12.9818 4.2049 -0.9022 -1.1261 -23.7147 6.6341 -1.8547 -0.3786 0.5532 4.4617 6.0874 0.1424 10.8125 3.6466 -0.9130 -0.1350 32.5882 -8.9798 1.6063 0.0818 -22.6064 -10.7259 -3.2365 0.3243 9.2626 -8.9854 0.0169 -0.5437 3.2840 14.1573 -7.0465 0.3405 -9.2200 -12.3861 -3.4283 0.4352 25.5849 2.7817 0.3867 0.4468 26.9032 2.9310 2.4455 0.4116
Dikkat ederseniz işaretler dışında sonuçlar aynı. Bu durum uygulamanız için sorun teşkil etmez.
Soru 2: PCA ile örüntü analizi nasıl yapılıyor? Yani elimizde bir veri seti var diyelim ki. Örüntü analizi için kullanılacak. Verinin bir kısmını PCA, bir kısmını da test için mi kullanmak gerekiyor. Test ve sınıflandırma işlemi nasıl gerçekleştiriliyor?
Cevap: PCA boyut indirgemeye yarar. Bu bağlamda, diğer uygulamalar için genellikle önişlem olarak kullanılıyor. Örneğin bağlanım (regression) yapacaksanız çok fazla boyutla uğraşmak yerine öncelikle PCA uygulayıp verinin boyutunu düşürüyorsunuz. Aynı durum sınıflama için de geçerli. Yukarıdaki örnek üstünden bakacak olursak X
'teki her örnek normalde 4 boyutlu. score1
'in ilk iki sütununu alır, gerisini atarsak her örneğin yeni uzaydaki boyutu 2'ye düşer. Yarı yarıya kâr! Yani sizin yeni örnekleriniz score1
ile ifade edilen koordinatlara sahip örnekler. Peki yeni boyut sayısı kaç olmalı. Literatürde genel olarak özdeğerlerin birikimsel olarak %95'ini alacak şekilde boyut sayısı seçiliyor:
[pc1,score1, eigvalues] = princomp(X); cumsum(eigvalues)./sum(eigvalues)
ans = 0.8660 0.9789 0.9996 1.0000
Görüldüğü üzere, 2 tane koordinatı seçtiğimizde verinin %97.89'unu ifade edebiliyoruz. Bunun yeterli olacağını, gerisinin gürültü olduğunu varsayabiliriz. İllâ ki böyle yapacaksınız diye bir şart yok, isterseniz limiti %98 seçebilirsiniz.
Şimdi eğitim ve test aşamalarında ne yapacağımıza bakalım. PCA'i ifade etmek için temel bileşenlere ve ortalama vektöre ihtiyaç var. Bunları eğitim kümesini kullanarak elde edeceksiniz. Ardından test kümesindeki her örnekten bu ortalama değeri çıkarıp temel bileşenler ile çarpacak ve bu örneklerin indirgenmiş uzaydaki hallerini bulacaksınız. Sonra bağlanım mı yaparsınız, sınıflandırma mı, kullanacağınız hep bu yeni değerler olacak.
Alıştırma:
Burada okura bir sınıflandırma alıştırması vereyim. PCA ile temel bir uygulama alıştırması:
- MNIST elle yazılmış rakam veritabanını indirin.
- Normalde eğitim kümesinde 50000, test kümesinde ise 10000 adet örnek var. Her örneği düzleştirin ve yeni örnekler 20x20 boyutlu yerine 400x1 boyutlu olsun.
- 50000 örnek ek teknik kullanmadan işlem yapabilmek için çok fazla. Her bir rakam için 500 adet rastgele örneği alın ve böylece 5000 elemanlık bir eğitim kümesi oluşturun.
- PCA uygulayın ve temel bileşenler ile ortalama vektörleri bulun. Sadece %95 birikimsel özdeğeri saklayacak kadar temel bileşeni tutun, gerisini atın.
- Eğitim kümesindeki her örneğin indirgenmiş boyutlarını hesaplayın ve saklayın.
- 10000 test örneğinden her biri için
- Eğitim kümesindeki örneklere yaptığınız gibi ortalamayı çıkarın ve temel bileşenler ile çarparak boyut indirgeyin.
- Eğitim kümesindeki her örneğe olan Öklit uzaklığını hesaplayın. Vektörler 400x1 boyuttan daha az olacağı için işlemler hızlı olacak.
- En yakın vektörü tespit edin ve bu test örneğinin etiketini o vektörün etiketine atayın. Yani en yakın vektör 5 rakamına ait ise sizin gözlemlediğiniz vektör de 5 rakamı olacak.
- 10000 vektörün kaç tanesinin doğru hesaplandığını bulun.
- Aynı işlemi PCA uygulamadan deneyin, farkı görün.
5 yorum
Hocam sınıflandırma işlemi için 2.sorunun cevabında son cümlede belirttiğiniz "bulunan yeni değerler" test verisi olarak mı kullanılacak? eğitim verilerinde herhangi bir değişiklik yapılmıyor mu ? Bu kısım da bir karmaşa yaşadım.
@ayşefatma Eğitim kümesi ile test kümesinin aynı boyutlu vektörlere dönüştürülmesi lazım. Bunun için de eğitim kümesinden de test kümesinden de öncelikle ortalamayı çıkarmalısın. Ardından benim verdiğim örnekteki gibi
pc2
ile çarpmalısın. Yani eğitim kümelerinde de aynı değişiklik olacak.Hocam merhaba kolay gelsin. Vermiş olduğunuz alıştırma ile uğraşıyorum. Mümkünse alıştırmanın kodlarını paylaşır mısınız ?
Hocam tekrar merhaba alıştırmadaki euclid uzaklıklarını tek tek hesaplatmak bayağı vakit alıyor onun yerine önerebileceğiniz bir şey var mı ???
@Özgün Öklit uzaklıkları için pdist2 fonksiyonunu kullanabilirsiniz. Kodları paylaşmayayım, alıştırma olarak kalsın ;)