Principal Component Analysis (PCA) R ile nasıl yapılır?


Egzersiz

PCA ile ilgili olarak unuttuklarımızı gözden gözgen geçirmek için basit bir egzersiz tasarladım. Bu örnek hipotetik bir veri seti üzerinde tasarlanmıştır. Durumu tam kavradıktan sonra bunu gerçek veri seti üzerinde uygulayacağız.

Memleket ve Dil Örneği

Diyelim ki bir grup öğrencinin farazi bir okulda Türkçe, Farsça, Arapça ve Süryanice dillerinden aldıkları dil puanları ve memleket bilgileri yer alsın. Bu veri setinde özellikle Van’lı olanları Türkçe ve İngilizcelerinin iyi Farsçalarının da azıcık iyi olmasına özen gösterdik. Mardinlilerin ise Arapçalarının iyi, Türkçe e İngilizcelerinin ise Van’lılara göre kötü olacağını düşündük. Daha sonra Siirtlileri ise Türkçe ve İngilizcelerinin kötü ancak Arapça’da en az Mardinliler kadar iyi olmalarını sağladık. Son olarak Süryanice’de en usta olanların Siirt’liler, Mardinliler ise azıcık Süryaniceye hakim olsun.

Şimdi PCA yaparak bu 5 dil yerine tek bir gösterge ortaya çıkararak tüm veri setinde memleket değişkenini en yüksek ölçüde açıklamayaçalışacağız.

Veri setimiz şuydu:

data = read.csv("ornek2.csv")
rownames(data) <- data$student
data[2:7]
##       memleket turkce farsca arapca ingilizce suryanice
## suat       van     90     60     10        90         0
## garb       van     88     70     11        88         0
## vahi       van     89     71     13        93         0
## mahi       mrd     70     10     90        66        11
## meli       mrd     65     11     98        67         7
## fahro      srt     40     40     89        60        90
## abdo       srt     40     40     89        60        90
## hako       srt     40     40     89        60        90

PCA Uygulaması

data.pca <- prcomp(data[3:7])
data.pca
## Standard deviations (1, .., p=5):
## [1] 62.697451 32.779140  3.550695  1.399083  0.912195
## 
## Rotation (n x k) = (5 x 5):
##                  PC1         PC2        PC3        PC4        PC5
## turkce    -0.3574760  0.11677660 -0.2578622  0.1165373 -0.8823267
## farsca    -0.2328702 -0.56494423  0.7378478 -0.1834692 -0.2202935
## arapca     0.6056701  0.49571857  0.5167242  0.1554323 -0.3102639
## ingilizce -0.2295579 -0.07426912  0.1540874  0.9442049  0.1628538
## suryanice  0.6312284 -0.64494065 -0.3135936  0.1925512 -0.2240209

PC1 adlı komponentimizin %62 oranında tüm veri setini açıkladığını görüyoruz, PC2 adlı komponent ise %32 oranında açıklıyor. Sadece bu iki komponenti kullarak tüm veri setini 62+32 = %94 oranında açıklayabiliriz. Bunun için 5 dille ilgili parametrelere gerek kalmaz.

#library("devtools")
#install_github("vqv/ggbiplot")

Görselleştirme

data.pca adlı değişkenimize tanımladığımız komponentlerden en güçlü iki komponentimizi grafiğe yerleştiriyoruz. Görülen okun yönü ise her bir parametrenin (dil) ekseninde yer aldığı komponente hizmet ettiğini gösteriyor, ok ne kadar uzunsa o parametre o komponente o kadar hizmet ediyor (açıklıyor). Buna göre yatay eksende PCA1 komponentini en çok arapça ve süryanice açıklıyor. Aynı komponenti Türkçe, İngilize ve Farça bilgisi de açıklıyor ancak ters yönde.

Öte yandan Süryanic bilgisi ile Farsça bilgisi ise PCA2’yi açıklıyor bu bilgilerin aksi istikamete ise Arapça yer alıyor. Tüm bu ilişkiler yani hangi komponentin hangi parametre ile ne kadar ilgili olduğu zaten PCA tablosunda görülebiliyor.

library("ggbiplot")
ggbiplot::ggbiplot(data.pca,labels= rownames(data),groups = data$memleket)

Bu grafiğe isimleri de eklediğimizde memleketlerine göre de renklendirdiğimizde sağ alt köşede üç mardinli arkadaşın da aybı yerde yer aldığını ve bu arkadaşların da bir küme olma nedeninin Süryanice bilgisi olduğunu başka bir şeye bakmaksızın anlıyoruz. Yani memlekete bilgisi olmasaydı dahi PCA bize bu arkadaşların ortak bir özelliğinin var olduğunu söylemiş oluyor. Aynı durum grafiğin üstünde siirtiler kaar olmasa da yine ayrı bir grubun var olduğunu gösteriyor. Solda is Van’lılar yer alıyor onlar ise Türkçe, İngilizce ve Farsça bilgisi ile göz dolduruyor 🙂

Sonuçlar

  • PCA ile çok fazla sayıda parametre daha az parametreye indirgenebilir. (PCA1, PCA2 gibi)
  • Bu indiregeme işlemi görselleştirildiğinde birbiri ile ilgili (benzer ya da tam tersi) parametreler (örneğin Türkçe, İngilizce ve Farsça’nın grubun bir kısmı için birbiri ile ilgili parametreler olması yani öğrencilerin memleketindeki şu veya bu nedenden ötürü Farsçası iyi olan kişinin İngilizcesinin de iyi olması gibi) ortaya çıkarılabilir.
  • GGBiplot aracı yardımı ile gözlemlerin (öğrencilerimiz) de grafiğe eklenmesi ile veri seti içinde gizli gruplar da ortaya çıkarılabilir. Örneğimizde memleket kolonu yer almasa bile biz bu öğrencilerinin bazılarının adını koymadığımız bir nedenden ötürü (memleket) grup olduklarını anlamış oluyoruz.
Reklamlar

K-Means ve TF.IDF ile gözetimsiz makine öğrenme algoritması örneği


Metin madenciliğinde sınıflandırma için kullanılacak algoritmalarda eğer gözetimli algoritma (supervised) kullanırsak dışarıdan eğitim verisine ihtiyaç duyarız. Dışarıdan gözetim gerektirmeyen (unsupervized) algoritmalarda ise metin içinde yapılar “cluster” adı verilen yapılara göre otomatik olarak algılanabilir.

Aşağıdaki kodlarla TF.IDF metriği üzerinden K-Means algoritması kullanılarak basit 6 cümleden oluşan bir korpus içinde 2 sınıf otomatik olarak ortaya çıkarılmıştır.

In [19]:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
all_text  =  """
 Ekonomik kriz insanları etkiledi
 Ekonomik krizde çözüm aranıyor
 Ekonominin patronlarından parasal çözümler
 Mide ağrısı nasıl geçirilir
 Mide ağrısı için hangi ilaçlar iyidir
 Mideniz ağrıdığında ne yapmalısınız?
""".split("\n")[1:-1]
# Preprocessing and tokenizing
def preprocessing(line):
    line = line.lower()
    line = re.sub(r"[{}]".format(string.punctuation), " ", line)
    return line

In [20]:

all_text

Out[20]:

[' Ekonomik kriz insanları etkiledi',
 ' Ekonomik krizde çözüm aranıyor',
 ' Ekonominin patronlarından parasal çözümler',
 ' Mide ağrısı nasıl geçirilir',
 ' Mide ağrısı için hangi ilaçlar iyidir',
 ' Mideniz ağrıdığında ne yapmalısınız?']

In [21]:

import re
import string
tfidf_vectorizer = TfidfVectorizer(preprocessor=preprocessing)
tfidf = tfidf_vectorizer.fit_transform(all_text)
sinif_sayisi =2
kmeans = KMeans(n_clusters=sinif_sayisi).fit(tfidf)

In [23]:

suat_order_centroids = kmeans.cluster_centers_.argsort()[:, ::-1]
suat_terms = tfidf_vectorizer.get_feature_names()

In [24]:

for i in range(sinif_sayisi):
     print("Cluster %d:" % i),
     for ind in suat_order_centroids[i, :10]:
         print(" %s" % suat_terms[ind])
Cluster 0:
 ekonomik
 aranıyor
 krizde
 etkiledi
 insanları
 çözüm
 kriz
 ağrıdığında
 ekonominin
 çözümler
Cluster 1:
 ağrısı
 mide
 nasıl
 geçirilir
 için
 hangi
 ilaçlar
 iyidir
 insanları
 ağrıdığında

Tahmin Denemesi

In [25]:

#hangi metin hangi cluster'da
# mide ağrısı Cluster'i 1 olduğundan aşağıda ilk sonuç 1 döner
lines_for_predicting = ["mide ağrısı", "ekonomi","kriz"]
kmeans.predict(tfidf_vectorizer.transform(lines_for_predicting))

# array([0, 1], dtype=int32)

Out[25]:

array([1, 0, 0], dtype=int32)

Drawing Semantic Networks with Python and NetworkX library


import networkx as nx
G = nx.Graph()
G.add_node("kids",repeat=2)
G.add_node("netflix",repeat=4)
G.add_node("strategy",repeat=1)
G.add_node("app",repeat=1,)
G.add_node("chinese",repeat=2)
G.add_node("movie",repeat=1)
G.add_node("language",repeat=2)
G.add_node("alibaba",repeat=1)
G.add_edges_from([
                  ('kids','netflix'),
                  ('kids','suat'),
                  ('kids','app'),
                  ('netflix','app'),
                  ('netflix','movie'),
                  ('netflix','strategy'),
                  ('strategy','movie'),
                  ('chinese','language'),
                  ('netflix','language'),
                  ('strategy','chinese'),
                  ('netflix','alibaba')
                 ])

#colorizing according to the frequency
#https://stackoverflow.com/questions/27030473/how-to-set-colors-for-nodes-in-networkx-python
color_map = []
for node in G:
    #https://stackoverflow.com/questions/13698352/storing-and-accessing-node-attributes-python-networkx
    node_repeat = G.node[node]['repeat']
    if node_repeat > 2:
        color_map.append('red')
    else: color_map.append('orange')
    

import matplotlib.pyplot as plt
pos=nx.circular_layout(G)
nx.draw(G,node_color = color_map,with_labels = True , pos = pos)
plt.show()

Data Wrangling Cases: Case #1: Emre’s Language Score Problem


userscore_typescore
jimmytoefl80
catherineielts33
fitzwilliamtoefl90
emreielts100
emretoefl99

Let’s contemplate a data set like above. Any user can have TOEFL or IELTS score. Some of them like ‘Emre’ has two score together. Let’s think we want to convert this dataset like below:

userieltstoefl
jimmyNone80
catherine33None
fitzwilliam90None
emre100None
emreNone99

What we did? We just converted two factor type of score_type as a column and get the corresponding values from to the newly generated score columns. During this conversation if person has not given type of exam we put ‘None’ and if any person has more than one exam we put each score within a new row.

How can we perform this conversion? Manually? Perfect for a few row! What we do when there is 40.000 of row? The GG should answer this question? 🙂

Use Python Language:

import pandas as pd
df = pd.read_csv("/home/satan/Masaüstü/data.csv",sep="|")
# you can either use a function disctincts kind of factors from score_type column by df['colname'].unique().tolist()
score_factors = ['toefl','ielts']
for factor in score_factors:
    df[factor] = None
# distribute the values to added columns
j = 3 # due to additional columns should start from 3'th column
score_type_column_nr = 1 # locate where is score_type column
for factor in score_factors:
    for index,row in df.iterrows():
        stype = df.iloc[index,score_type_column_nr]
        corresponding_column_no = j
        if (factor in stype):
            df.iloc[index,corresponding_column_no] = df.iloc[index,2]
        else:
            pass
    j = j+1 

That’s all. Can you solve this problem with your veteran Excel? I think no 🙂 If you can write, please explain how, to below. Don’t forget, to add how much time you spend to solve the problem including goggling.

For me I didn’t open the browser and wrote it within 15 minutes! Huh ?

Note: This scenario and its answer is original and firstly published from Dr. Suat ATAN’s blog

Firebase Kullanmaya Giriş


Firebase Google’ın sunduğu sunucu tarafı olmasına ihtiyaç bırakmayan bir hosting, veritabanı ve barındırma hizmetidir. Firebase ile hızla site hazırlayıp yayınlayabilirsiniz. PHP, Java, Python, C# veya başka bir dil kullanmaya gerek yoktur. Veri tabanı işlemleri dahi Javascript ile yapılır. Veritabanı olarak da Firebase Collections adlı bulut sisteminde veriler JSON benzeri yapıda tutulur.

Aşağıdaki komutlarla Firebase üzerinde çalışmaya hazır ve veritabanı bağlantısı yapan (Firebase Collection ile) ve Vue gibi herhangi bir araçla bağlantısı olmayan düz bir web uygulaması hazırlanır. Vue kullanarak Vue SPA tarzı bir uygulama için yazının devamındaki başlığa bakın:

Firebase sitesine giderek yeni bir proje oluşturun.

Aşağıdaki Komutları Çalıştın

#Eğer yoksa şu komutla kurun (windoesta sudo kullanmayın)
sudo npm install -g firebase-tools
#Başlatın
firebase init
#Lokalde çalıştırın
firebase serve --only hosting

Daha sonra index.html dosyasını şöyle dizayn edin

<!DOCTYPE html&gt;
<html&gt;
  <head&gt;
    <meta charset="utf-8"&gt;
    <meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    <title&gt;Atan Finans</title&gt;

  <!-- Insert these scripts at the bottom of the HTML, but before you use any Firebase services --&gt;

  <!-- Firebase App (the core Firebase SDK) is always required and must be listed first --&gt;
  <script src="https://www.gstatic.com/firebasejs/5.9.4/firebase-app.js"&gt;</script&gt;

  <!-- Add Firebase products that you want to use --&gt;
  <script src="https://www.gstatic.com/firebasejs/5.9.4/firebase-auth.js"&gt;</script&gt;
  <script src="https://www.gstatic.com/firebasejs/5.9.4/firebase-database.js"&gt;</script&gt;


  <script src="https://www.gstatic.com/firebasejs/5.9.4/firebase.js"&gt;</script&gt;
  <script&gt;
    // Initialize Firebase
    var config = {
      apiKey: "Bu Kodu firebase konsolundan alın webden",
      authDomain: "siteadiniz.firebaseapp.com",
      databaseURL: "https://atanfinans.firebaseio.com",
      projectId: "siteadiniz",
      storageBucket: "siteadiniz.appspot.com",
      messagingSenderId: "Bu kodu fireabse konsolunda alın webden"
    };
    # Veritabanına veri ekleme
    firebase.initializeApp(config);
    var db = firebase.firestore();
    db.collection("users").add({
    first: "Ada",
    last: "Lovelace",
    born: 1815
    })
    .then(function(docRef) {
        console.log("Document written with ID: ", docRef.id);
    })
    .catch(function(error) {
        console.error("Error adding document: ", error);
    });


  </script&gt;

  <style media="screen"&gt;

  </style&gt;
  </head&gt;
  <body&gt;
    <div class="ana"&gt;
      <h1&gt;Atan Finans</h1&gt;

    </div&gt;
  </body&gt;
</html&gt;


Firebase Üzerinde Vue Uygulaması

Vue Uygulaması kendi içinde özel bir dosya yapısı ve modüller barınıdırır. Bunun için özel bir kurulum gerektir:

vue create vue-app

Vue Uygulamasında Vuex ve Sass kullanmak için (kullanmanız önerilir) modülleri şöyle eklemelisiniz:

vue init webpack vue-app
npm i vuex
npm i node-sass sass-loader --save-dev

Projeyi lokale çalıştırmak için:

npm run dev

Projeyi sunucuya yüklemek için:

firebase deploy

Market Sepeti Analizi Nedir?


Bir markette herkes sepetine farklı ürünler doldurur. Ancak her sepette genellikle bir arada bulunan ürünler vardır. Bu ürünlerden örneğin kola ile cipsin bir arada alınması beklenebilir ancak beklenmediği halde bir arada olan ürünler olabilir mi? Örneğin bira ile çocuk bezi bir arada sıkça görülür mü? Bir şehir efsanesine göre evet. İşte buna benzer kalıpları görebilmek için “market sepeti analizi” adı verilen bir analiz yapılır. Bu bir veri madenciliği yöntemidir.Bunu R ile yapmak için şurayıPython ile yapmak için şurayı okuyabilirsiniz.

R ve Regex Yardımıyla düzensiz bir metin içinden yılı yakalamak


Bir projemde aşağıdaki gibi iki tür metin vardı:

> a="Volume 29, Issue 3, July 2007, Pages 357-374"
> b="Published: 1999, Start page: 117"

a ve b değerleri içinden 2007 ve 1999 gibi sayıları çıkarmak istiyordum. Regex’te buna uygun bir patternin var olduğunu düşündüm. Şuradan test ettim: https://www.regextester.com/93651

Daha sonra R’da bulunan stringr paketindeki str_extract fonksiyonunu kullandım:

> str_extract(a,"(19|20)\\d{2}")
[1] "2007"
> str_extract(b,"(19|20)\\d{2}")
[1] "1999"

Özetle (19|20)\d{2} şeklinde yazdığım regex kodu şöyle söyler: Git o metnin içinden 19 veya 20 ile başlayan ve devamında iki sayısal karakter(d) olan veriyi yani yılı getir.

Getirdi de! Büyük veri zorlu veridir. Ama aşmak için her zaman yollar vardır.