Python ile Birliktelik Kuralları Analizi (Association Rules Analysis with Python)

Merhabalar,

Bu gün sizlerde birlikte Python üzerinde Birliktelik Kuralları Analizi çalışmasını gerçekleştireceğiz. Çok daha evvel olması yazılması planlanan bu yazı için lütfen kusuruma bakmayınız. ☹ Birliktelik Kuralları Analizi (Association Rules Analysis) hakkındaki daha önceki yazılara aşağıdaki linklerden ulaşabilirsiniz.

  1. Birliktelik Kuralları Analizi (Association Rules Analysis) https://www.veribilimiokulu.com/associationrulesanalysis/
  1. R ile Birliktelik Kuralları Analizi (Association Rules Analysis with R Project) https://www.veribilimiokulu.com/association-rules-analysis-with-r/
  1. IBM SPSS Modeler ile Birliktelik Kuralları Analizi (Association Rules Analysis with IBM SPSS Modeler) https://www.veribilimiokulu.com/association-rules-analysis-with-ibm-spss-modeler/

Şimdi sıra Python’da 😊

Python üzerinde Birliktelik Kuralları Analizi için kullanacağım kütüphaneler başlıca kütüphaneler: mlxtend, pandas ve numpy

MLXTEND (Machine Learning Extensions)

MLXTEND modülü içerisinde; classifier, cluster, regressor, evaluate, feature extraction&selection, frequent_patterns, general concepts, image, preprocessing, , math, plotting vb. extension’lar yer almaktadır. Şuanki mevcut sürümü BSD lisansı altında 0.13.0’tür. Kendisi hakkında daha fazla bilgi elde etmek isterseniz resmi web sayfasını inceleyebilir ve yazarı Sebastian Raschka hakkında buradan bilgi edinebilirsiniz.

Numpy ve Pandas

Numpy ve Pandas paketleri ise, Matris İşlemleri ve Input&Output işlemleri için kullanmaktayım.

Not: Kullanmış olduğum; Python versiyonu 3.6.8 ve IDE(Integrated Development Environment) olarak Jupyter Notebook kullanmaktayım. Github repo’sunda .ipynb ve.py dosyasını paylaşacağım.

Gerekli Modüllerin Kurulması

Bu projeye ait Github reposu içerisinde requirements.txt dosyası yer alacaktır. Bu dosyayı ilgili dizinde iken komut istemi kısmında

pip install -r requirements.txt

ya da

conda install --file requirements.txt

olarak çalıştırmanız ve kurulumları yapmanız gerekmektedir. Ya da modülleri manuel olarak aşağıdaki gibi kurabilirsiniz.

pip install mlxtend
pip install pandas
pip install numpy

ya da Conda Package Manager ile

conda install mlxtend --channel conda-forge
conda install pandas
conda install numpy

Conda Forge mlxtend github reposu: https://github.com/conda-forge/mlxtend-feedstock

Modülleri Import Edelim

#Importing Modules
import pandas as pd
import numpy as np

from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import association_rules

import mlxtend as ml
#print(ml.__version__)

Veri Seti Oluşturma

Bu uygulama da daha öncekilerden farklı olarak veri setini kendimiz oluşturacağız. Hazır bir veri setinden ziyade kendimizin yazacağı ufak kodlar ile veri setini oluşturacağız. Burada oluşturacağımız veri seti gerçek dünya verisi olmadığı için birliktelik kuralları analizinde farklı çıktılar ile karşılaşmamız yüksek ile muhtemel 🙂

Veri setini oluştururken bazı kurallarımız olacak. Adımlar:

  1. Ürün listesinin belirlenmesi: 16 Adet (‘Apple’,’Corn’,’Dill’,’Eggs’, ‘Ice cream’,’Kidney Beans’,’Milk’,’Nutmeg’, ‘Onion’,’Unicorn’,’Yogurt’, ‘Bread’, ‘Cheese’, ‘Butter’, ‘Sugar’,’Chocolate’)
  1. Veri setinin içerisindeki gözlem sayısının belirlenmesi: 1000 Adet
dataset = []

import random

items = ['Apple','Corn','Dill','Eggs',
         'Ice cream','Kidney Beans','Milk','Nutmeg',
         'Onion','Unicorn','Yogurt', 'Bread', 
         'Cheese', 'Butter', 'Sugar','chocolate']

for i in range(1, 1000):
    k = random.randrange(1, len(items)+1)
    #print('K Values:', k)
    dataset.append(random.choices(items, k=k))
    #print(random.sample(items, k=k))
    
    #liste.append(random.sample(items, k=k))
    #print(random.sample(items, k=k))

    #random.sample
    #dataset.append(random.sample(items, k=k))
    #print(random.sample(items, k=k))

Ben 16 adet ürün belirleyerek bunları bir listeye yazdım. Devamında 1 ile bu ürünlerin sayısı olan 16 arasında rasgele bir üreterek random.choices fonksiyonu ile itemset listesi içerisinden ürünlerin seçilmesi sağlıyoruz. Bu veri seti içerisinde 1000 adet gözlem olması istediğim için de for döngüsü ile 2. adımı tekrarlıyoruz. Devamında veri setimiz oluşuyor.

Veri Seti Output: ./output/dataset.csv

df.to_csv('./output/dataset.csv', index=False)

Veri setinin boyutu: 1000 (0 – 999)

print(len(dataset))
999

İlk 5 Satırı Görelim:

print(dataset[1:5])
[['Onion', 'Cheese', 'Nutmeg', 'Corn', 'Sugar'], ['Corn', 'Unicorn', 'Chocolate', 'Apple', 'Apple', 'Corn'], ['Butter', 'Cheese', 'Bread', 'Sugar', 'Milk', 'Apple', 'Butter', 'Dill', 'Bread', 'Apple', 'Yogurt', 'Dill', 'Nutmeg', 'Kidney Beans'], ['Chocolate', 'Onion']]

Son 5 Satırı Görelim:

print(dataset[995:(len(dataset)+1)])
[['Apple', 'Unicorn', 'Kidney Beans', 'Cheese', 'Corn', 'Butter'], ['Onion'], ['Milk', 'Unicorn'], ['Butter', 'Yogurt'], ['Butter', 'Dill', 'Ice cream', 'Bread', 'Dill', 'Dill', 'Dill', 'Butter', 'Onion', 'Onion', 'Chocolate', 'Bread', 'Cheese', 'Bread', 'Ice cream', 'Bread']]

random.choices kullandığımız gibi random.sample fonksiyonunu da kullanabiliriz. Random.sample kullanmanız aynı satır içerisindeki ürünlerin benzersizliği sağlayacaktır. Yukarıda yorum satırı olarak bıraktığım (#random.sample) satırı çalıştırarak görebilirsiniz.

Veri setini oluşturduktan sonra nested list (iç içe liste) tipindeki verilerimizi tabular bir yapıya çevirmemiz gerekiyor. Bunun için mlxtend modülü içerisinde yer alan preprocessing sınıfı içerisinde TransactionEncoder fonksiyonunu kullanacağız.

Not: from mlxtend.preprocessing import TransactionEncoder

te = TransactionEncoder()
te_ary = te.fit(dataset).transform(dataset)
df = pd.DataFrame(te_ary, columns=te.columns_)

Not: TransactionEncoder hakkında daha fazla bilgi için: http://rasbt.github.io/mlxtend/user_guide/preprocessing/TransactionEncoder/

Şimdi de tabular formattaki verisetimizi görelim:

df.head()
AppleBreadButterCheeseChocolateCornDillEggsIce creamKidney BeansMilkNutmegOnionSugarUnicornYogurt
0FalseFalseFalseFalseTrueTrueFalseTrueFalseTrueFalseFalseFalseTrueTrueFalse
1FalseFalseFalseTrueFalseTrueFalseFalseFalseFalseFalseTrueTrueTrueFalseFalse
2TrueFalseFalseFalseTrueTrueFalseFalseFalseFalseFalseFalseFalseFalseTrueFalse
3TrueTrueTrueTrueFalseFalseTrueFalseFalseTrueTrueTrueFalseTrueFalseTrue
4FalseFalseFalseFalseTrueFalseFalseFalseFalseFalseFalseFalseTrueFalseFalseFalse

Model Oluşturma

Veri setimizi birliktelik kuralları analizi için uygun hale getirdikten sonra artık Apriori algoritmasını kullanabiliriz. mlxtend modülü içerisinde yer alan apriori() fonksiyonu yukarıda import etmiştik.

Not: from mlxtend.frequent_patterns import apriori

min_support değerini 0.1 yani %10 vererek apriori algoritması için başlangıç değerlerini set ediyoruz.

apriori(df, min_support=0.15).[1:26]

Not: Apriori hakkında daha fazla bilgi için : http://rasbt.github.io/mlxtend/user_guide/frequent_patterns/apriori/

supportitemsets
10.368368(1)
20.377377(2)
30.371371(3)
40.376376(4)
50.376376(5)
60.356356(6)
70.405405(7)
80.399399(8)
90.364364(9)
100.382382(10)
110.359359(11)
120.380380(12)
130.379379(13)
140.389389(14)
150.375375(15)
160.160160(0, 1)
170.164164(0, 2)
180.157157(0, 3)
190.171171(0, 4)
200.154154(0, 5)
210.150150(0, 6)
220.172172(0, 7)
230.176176(0, 8)
240.151151(0, 9)
250.165165(0, 10)
Not: Tablodaki itemset kolonu içerisinde yazan rakamları ürünleri (0-15) ifade etmektedir. 0 no’lu ürün Apple, 1 no’lu ürü Bread olarak 15 no’lu ürün ise Yogurt ifade etmektedir.
print("Kural Sayısı:", len(apriori(df, min_support=0.15)))
Kural Sayısı: 126
Şimdi de apriori algoritması içerisinde use_colnames=True parametresini kullanarak items(ürünler) numaralarından item(ürün) isimlerine geçiş yapıyoruz.
apriori(df, min_support=0.15, use_colnames=True)[1:26]
supportitemsets
10.368368(Bread)
20.377377(Butter)
30.371371(Cheese)
40.376376(Chocolate)
50.376376(Corn)
60.356356(Dill)
70.405405(Eggs)
80.399399(Ice cream)
90.364364(Kidney Beans)
100.382382(Milk)
110.359359(Nutmeg)
120.380380(Onion)
130.379379(Sugar)
140.389389(Unicorn)
150.375375(Yogurt)
160.160160(Bread, Apple)
170.164164(Butter, Apple)
180.157157(Cheese, Apple)
190.171171(Chocolate, Apple)
200.154154(Corn, Apple)
210.150150(Dill, Apple)
220.172172(Eggs, Apple)
230.176176(Ice cream, Apple)
240.151151(Kidney Beans, Apple)
250.165165(Milk, Apple)
Yukarıdaki tabloda tekli, ikili ve üçlü itemset’lerin oluştuğu görülmektedir. min_support değeri (0.15) değerini set edip kuralları rule setleri oluşturduktan sonra ilgilendiğimiz metriğe göre (confidence, lift, conviction ve vd.) Association Rules tablosunu oluşturuyoruz. Burada metric olarak Confidence ve değerini 0.3 (%30) seçtik.
frequent_itemsets = apriori(df, min_support=0.15, use_colnames=True)

# frequent_itemsets
# association_rules(frequent_itemsets, metric="confidence", min_threshold=0.30)

rules1 = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.30)
Not: from mlxtend.frequent_patterns import association_rules
Not: association_rules hakkında daha fazla bilgi için: http://rasbt.github.io/mlxtend/user_guide/frequent_patterns/association_rules/
Oluşan Kural Sayısı:
print("Oluşan Kural Sayısı:", len(rules1))
Oluşan Kural Sayısı: 220
Confidence metriğine göre (Z-A) 10 Kural:
rules1 = rules1.sort_values(['confidence'], ascending=False)

rules1[1:11]
antecedentsconsequentsantecedent supportconsequent supportsupportconfidenceliftleverageconviction
40(Bread)(Ice cream)0.3683680.3993990.1801800.4891301.2246650.0330541.175644
99(Chocolate)(Corn)0.3763760.3763760.1821820.4840431.2860600.0405231.208673
98(Corn)(Chocolate)0.3763760.3763760.1821820.4840431.2860600.0405231.208673
39(Bread)(Eggs)0.3683680.4054050.1771770.4809781.1864130.0278391.145606
121(Dill)(Corn)0.3563560.3763760.1711710.4803371.2762150.0370471.200054
178(Sugar)(Ice cream)0.3793790.3993990.1821820.4802111.2023330.0306581.155470
62(Butter)(Ice cream)0.3773770.3993990.1811810.4801061.2020700.0304571.155237
81(Cheese)(Eggs)0.3713710.4054050.1781780.4797841.1834680.0276221.142977
167(Unicorn)(Eggs)0.3893890.4054050.1851850.4755781.1730930.0273251.133810
170(Kidney Beans)(Ice cream)0.3643640.3993990.1731730.4752751.1899740.0276461.144600
Yorum 1: ID bilgisi 40 olan satırı inceleyecek olursak;
  • Bread ve Ice Cream item’larının birlikte görülme olasılığı (support) %18 (0.18) olduğunu,
  • Bread item’ının satın alan kişilerin (confidence)  %48’inin (0.489130) olasılıkla  Ice Cream item’ınıda satın aldığını,
  • Bread item’ının yer aldığı alışveriş sepetlerin de Ice Cream item’ının satışı (lift) 1,224 kat arttığı,
  • Bread ve Ice Cream item’larının birlikte satın alınmalarının ile birbirlerinden bağımsız olarak satın alınmalarından ne kadar fazla (leverage) 0.03 olduğunu,
  • Bread ve Ice Cream item’larının birbirleri ile ilişkili (conviction) 1.17 değeri ile olduğunu  söyleyebiliriz.

Daha önceki yazılarımızda tablo’da görülenler diğer değerlerin açıklamalarını ve hesaplamalarının nasıl yapıldığının üzerinden geçmiştik. Bu yüzden genel olarak önem atfedilen support, condifence, lift, leverage ve conviction metrikleri üzerinden yorumlar da bulundum. Diğer kısımlar için lütfen eski sayılara bakınız 🙂

Metrikler hakkında daha fazlasını görmek isterseniz Michael Hahsler sayfasına buradan ulaşabilirsiniz. Bu bağlantıya Dr. Tuğrul Taşçı bey’in ISE 302 sunumundan ulaştığımı belirtmek isterim.

Şimdi de antecedents ve consequents kısımlarında bulunan itemsleri sayılarını toplayalım ve ilk 5 satırı görelim:
rules1["antecedent_len"] = rules1["antecedents"].apply(lambda x: len(x))
rules1["consequents_len"] = rules1["consequents"].apply(lambda x: len(x))
rules1[1:6]
antecedentsconsequentsantecedent supportconsequent supportsupportconfidenceliftleverageconvictionantecedent_lenconsequents_len
40(Bread)(Ice cream)0.3683680.3993990.1801800.4891301.2246650.0330541.17564411
99(Chocolate)(Corn)0.3763760.3763760.1821820.4840431.2860600.0405231.20867311
98(Corn)(Chocolate)0.3763760.3763760.1821820.4840431.2860600.0405231.20867311
39(Bread)(Eggs)0.3683680.4054050.1771770.4809781.1864130.0278391.14560611
121(Dill)(Corn)0.3563560.3763760.1711710.4803371.2762150.0370471.20005411
Yukarıdaki confidence metriği için yaptıklarımızı diğer metrikler içinde yapabiliriz. Github reposunda diğer metrikler için olan kısımları ekleyeceğim. Örnek olması adına lift metriği için:
rules2 = association_rules(frequent_itemsets, metric="lift", min_threshold=1)

rules2 = rules2.sort_values(['lift'], ascending=False)

rules2[1:6]
rules2["antecedent_len"] = rules2["antecedents"].apply(lambda x: len(x))

rules2["consequents_len"] = rules2["consequents"].apply(lambda x: len(x))

rules2[1:6]
Not: Bu çıktıları github reposundaki .ipynb dosyasında görebilirsiniz.
Oluşan Kural Setleri için Filtreleme
Filtre 1: Antecedent item uzunluğu 1 olan ve Confidence değeri 0.20’ye büyük eşit olan ve Lift değeri 1‘den büyük olan ilk 10 kayıtı görelim.
rules1[(rules1['antecedent_len'] >= 1) &
       (rules1['confidence'] >= 0.20) &
       (rules1['lift'] > 1) ].sort_values(['confidence'], ascending=False)[1:10]
antecedentsconsequentsantecedent supportconsequent supportsupportconfidenceliftleverageconvictionantecedent_lenconsequents_len
40(Bread)(Ice cream)0.3683680.3993990.1801800.4891301.2246650.0330541.17564411
99(Chocolate)(Corn)0.3763760.3763760.1821820.4840431.2860600.0405231.20867311
98(Corn)(Chocolate)0.3763760.3763760.1821820.4840431.2860600.0405231.20867311
39(Bread)(Eggs)0.3683680.4054050.1771770.4809781.1864130.0278391.14560611
121(Dill)(Corn)0.3563560.3763760.1711710.4803371.2762150.0370471.20005411
178(Sugar)(Ice cream)0.3793790.3993990.1821820.4802111.2023330.0306581.15547011
62(Butter)(Ice cream)0.3773770.3993990.1811810.4801061.2020700.0304571.15523711
81(Cheese)(Eggs)0.3713710.4054050.1781780.4797841.1834680.0276221.14297711
167(Unicorn)(Eggs)0.3893890.4054050.1851850.4755781.1730930.0273251.13381011
Filtre 2: Benzer şekilde Antecedents item adı Bread olan ve Confidence metriğine göre [Z-A] sıralanmış ilk 10 kayıt:
rules1[rules1['antecedents'] == {'Bread'}].sort_values(['confidence'], ascending=False)[1:10]
antecedentsconsequentsantecedent supportconsequent supportsupportconfidenceliftleverageconvictionantecedent_lenconsequents_len
54(Bread)(Unicorn)0.3943940.3883880.1831830.4644671.1958830.0300051.14206111
43(Bread)(Ice cream)0.3943940.4094090.1811810.4593911.1220820.0197121.09245411
52(Bread)(Sugar)0.3943940.3933930.1801800.4568531.1613130.0250281.11683611
30(Bread)(Butter)0.3943940.4264260.1781780.4517771.0594480.0099981.04624111
57(Bread)(Yogurt)0.3943940.3943940.1781780.4517771.1454950.0226311.10466911
32(Bread)(Cheese)0.3943940.3983980.1771770.4492391.1276110.0200511.09230911
39(Bread)(Dill)0.3943940.4094090.1751750.4441621.0848860.0137061.06252411
40(Bread)(Eggs)0.3943940.3843840.1751750.4441621.1555160.0235761.10754611
36(Bread)(Corn)0.3943940.3903900.1721720.4365481.1182350.0182041.08192011
Verilen parametre değerlerine göre oluşan Birliktelik Kuralları Analizine ait oluşan kuralları .json olarak olarak export ediyoruz.
rules1.to_json('./output/rules1.json')

rules2.to_json('./output/rules2.json')

Not: PMML (Predictive Model Markup Language) gereksinimi doğrultusunda .xml olarak export edilmesi gerekmektedir.

Python üzerinden geçte olsa Birliktelik Kuralları Analizini gerçekleştirmiş bulunmaktayız. Malesef oluşan kurallar üzerinden görselleştirme yapamadık. Bu konuda mlxtend paketinin eksiklikleri olduğunu belirtebilirim. Burada başka bir şey kullanmalıyız. Bunu kendime görev addediyorum. Bulduğumda gerekli güncellemeleri geçeceğim.

Son olarak; Github üzerinde yer alan repository’e buradan (kod, input, output ve diğer dosyalara) ulaşabilirsiniz. Yazıyı beğenerek ve paylaşarak daha fazla kişiye ulaşmasına yardımcı olabilirsiniz. Görüş ve önerileriniz için uslumetin@gmail.com’dan bana ulaşabilirsiniz. Yeniden görüşmek üzere, Selamlar 🙂

Bağlantılı diğer yazılarım:

  1. Birliktelik Kuralları Analizi (Association Rules Analysis)
  2. R ile Birliktelik Kuralları Analizi (Association Rules Analysis with R Project)
  3. IBM SPSS Modeler ile Birliktelik Kuralları Analizi (Association Rules Analysis with IBM SPSS Modeler)

Kaynaklar:

Yazar Hakkında
Toplam 7 yazı
Metin USLU
Metin USLU
Veri Bilimci @ LC Waikiki#Programmer #Statistician #ComEngStudent
Yorumlar (Yorum yapılmamış)

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

×

Bir Şeyler Ara