Birliktelik kuralları, mevcut veri seti içerisinde birbirini tekrarlayan ilginç veya ilginç olmayan örüntüleri inceleyen bir veri madenciliği tekniğidir. Bu teknikte en çok kullanılan algoritmalardan biri Apriori ve en sık görülen örneği sepet analizidir. Müşterilerin geçmişte yapmış olduğu alışverişlerden yola çıkarak hangi ürünlerin birlikte satıldıklarını bazı metrikler ile bulmayı amaçlar ve böylece müşterilerin satın alma alışkanlıkları tespit edilmiş olup pazarlama stratejilerinin belirlenmesinde rol oynar.

Temel olarak kullanılan metrikler;
Destek değeri; A ve B ürünlerinin birlikte görülme olasılığıdır.
Destek = (Frekans(A,B))/N
Güven değeri; A ürünün satın alınması durumunda A ve B’nin birlikte satın alınma olasılığıdır.
Güven = (Frekans(A,B))/(Frekans(A))
Kaldıraç değeri; değişkenler arasındaki ilişkileri ifade eder. Bu değerin 1’den büyük olması istenir.
Kaldıraç = (Frekans(A,B))/(Frekans(A)*Frekans(B))
Uygulamada Online Retail veri seti, R’da Apriori algoritması için arules paketini ve görselleştirmeler için arulesViz paketini kullanılmıştır.
#Kütüphaneler
library(readxl)
library(tidyverse)
library(arules)
library(arulesViz)
library(ggalluvial)
#Veri setinin yüklenmesi
ham <- read_excel("…/Online Retail.xlsx")
Veri setinden iadeler, hediyeler ve faturaya konu olan posta ücretleri gibi kalemleri çıkarılmıştır. Apriori algoritması için bize lazım olacak değişkenler fatura numaraları (sepetler) ve ürün isimleri olacak. Algoritmayı çalıştırmadan önce her bir faturanın satırında alınan ürün isimleri olacak şekilde transactions formatına dönüştürülmüştür.
df <- ham %>%
filter(!str_detect(InvoiceNo,"^C"),UnitPrice > 0,!str_sub(StockCode,1,1) %in% LETTERS) %>%
rename(
FaturaNo = InvoiceNo,
UrunAdı = Description) %>%
mutate(
FaturaNo = as.factor(FaturaNo),
UrunAdı = str_to_title(UrunAdı),
UrunAdı = str_trim(UrunAdı,side = "both"),
UrunAdı = str_replace_all(UrunAdı,"[[:punct:]]"," "),
) %>%
select(FaturaNo,UrunAdı) %>%
group_by(FaturaNo) %>%
summarise(UrunAdı = paste0(UrunAdı,collapse = "_")) %>%
select(UrunAdı)
write.csv(df,"… /sepetler.csv",
quote = FALSE, row.names = FALSE)
#Transactions formatına çevir
sepet <- read.transactions("…/sepetler.csv",
format = "basket", sep = "_",header = TRUE)
#İlk 3 sepete bakalım
inspect(sepet[1:3])
#Sepet ve ürün sayısı
sepet

Veri setinde 19.773 adet sepet ve 3.997 farklı ürün bulunmaktadır. İlk 10 ürün için frekanslarını görselleştirecek olursak;
itemFrequencyPlot(sepet, topN = 10, type = "absolute",col = rainbow(10))

En yüksek frekansa sahip olan ürün White Hanging Heart T-Light Holder ürünü olmuş. Sepetlerdeki ürün sayısı dağılımını göstermek için arules paketindeki size() fonksiyonunu kullanabiliriz;
ggplot()+
geom_density(aes(x= size(sepet)),fill = "orange", color = "black")+
scale_x_continuous(breaks = seq(0,1200,50))+
theme_minimal()+
labs(x = NULL, y = "Yoğunluk")

Sepetlere konu olan ürün sayıları genellikle 1 ile 25 arasında yoğunlaştığını görüyoruz. Veri seti hakkında ön bilgileri aldık artık kuralları oluşturabiliriz. Ürün genişliği maksimum 2, destek değeri 0.01 ve üzeri, güven değeri 0.8 ve üzeri için;
rules <- apriori(sepet, parameter = list(supp=0.01,
conf=0.80,
maxlen=2,
target= "rules"))
#Destek değerine göre sırala
rules <- sort(rules, by = "support", decreasing = TRUE)
#İlk 5 kuralı göster
inspect(rules[1:5])

Toplamda 28 adet kural elde ettik. Oluşan ilk kural için;
- Mint ve Thyme ürünlerinin beraber bulunma olasılığı 0.01041825
- Mint ürününü alan müşterilerin Thyme ürününü de alma olasılığı 0.8583333
- Mint satın alınması Thyme satın alınmasını 71.61108 kat artırır yorumlarını yapabiliriz.
Oluşturduğumuz kuralları ürün matrisi yardımıyla görselleştirelim;
plot(rules, method = "grouped matrix")

Önceki yazımda en yüksek gelir getiren ürün Regency Cakestand 3 Tier isimli ürünüydü. Bu ürünü satın alan müşteriler hangi ürünleri birlikte almış inceleyelim. Ürün genişliği maksimum 2, destek değeri 0.01 ve üzeri, güven değeri 0.15 ve üzeri için;
rules_2 <- apriori(sepet, parameter = list(supp=0.01,
conf=0.15,
maxlen=2,
target= "rules"),
appearance = list(default = "rhs",
lhs = "Regency Cakestand 3 Tier"))
#Güven değerine göre sırala
rules_2 <- sort(rules_2, by = "confidence", decreasing = TRUE)
#İlk 5 kuralı göster
inspect(rules_2[1:5])

Toplamda 8 adet kural elde ettik. Oluşan ilk kural için;
- Regency Cakestand 3 Tier ve Roses Regency Teacup And Saucer ürünlerinin beraber bulunma olasılığı 0.02655136
- Regency Cakestand 3 Tier ürününü alan müşterilerin Roses Regency Teacup And Saucer ürününü de alma olasılığı 0.2640845
- Regency Cakestand 3 Tier satın alınması Roses Regency Teacup And Saucer satın alınmasını 4.903045 kat artırır yorumlarını yapabiliriz.
Oluşturduğumuz kuralları ağ grafiğiyle görselleştirelim;
plot(rules_2,method="graph")

Son olarak destek değeri 0.02 ve üzeri, güven değeri 0.8 ve üzeri için;
rules_3 <- apriori(sepet, parameter = list(supp=0.02,
conf=0.80,
target= "rules"))
#Kaldıraç değerine göre sırala
rules_3 <- sort(rules_3, by = "lift", decreasing = TRUE)
#İlk 5 kuralı göster
inspect(rules_3[1:5])

Toplamda 5 adet kural elde ettik. Oluşan ilk kural için;
- Pink, Roses ve Green Regency Teacup And Saucer ürünlerinin beraber bulunma olasılığı 0.02736054
- Pink, Roses Regency Teacup And Saucer ürününü alan müşterilerin Green Regency Teacup And Saucer ürününü de alma olasılığı 0.9046823
- Pink, Roses Regency Teacup And Saucer satın alınması Green Regency Teacup And Saucer satın alınmasını 17.658719 kat artırır yorumlarını yapabiliriz.
Parallel Coordinates grafiği ile kuralları görselleştirelim. Çizgilerin büyüklüğü destek değerini, renk koyuluğu ise güven değerini temsil eder.
plot(rules_3,method="paracoord")

Elde ettiğimiz kuralları veri çerçevesine aktaralım ve kaldıraç değerlerine göre alluvial grafik ile görselleştirelim.
df2 <- data.frame(left = gsub("[{}]", "",labels(lhs(rules_3))),
right = gsub("[{}]", "",labels(rhs(rules_3))),
lift = rules_3@quality$lift)
ggplot(data = df2, aes(y=lift, axis1 = left, axis2 = right))+
geom_alluvium(aes(fill = right),color = "black")+
geom_stratum(fill= "grey",color ="black")+
geom_text(stat = "stratum", infer.label = TRUE,size = 3.3)+
theme_void()+
scale_fill_viridis_d(option = "C")+
theme(legend.position = "bottom",
legend.title = element_blank(),
plot.title = element_text(hjust = 0.5))+
labs(title = "Destek: 0.02 ve Güven = 0.80")

Neler Yapabiliriz?
Elde ettiğimiz sonuçları incelediğimizde genelde aynı ürünün farklı renkleri ya da farklı biçiminin kuralları oluşturduğunu görüyoruz. Bunun sebebi Online Retail veri setindeki müşterilerin çoğunluğunun toptancı olmasından kaynaklanıyor olabilir. Müşteri davranışlarının önceden tespiti ile birtakım kampanyalar sunulabilir, tavsiye sistemleri geliştirilebilir.
Okuduğunuz için teşekkür ederim 😊
Veri Seti:
https://archive.ics.uci.edu/ml/datasets/online+retail
Kaynaklar:
https://mhahsler.github.io/Introduction_to_Data_Mining_R_Examples/book/index.html
https://www.datacamp.com/community/tutorials/market-basket-analysis-r
https://www.datasciencearth.com/r-ile-birliktelik-kurallari-uygulamasi/
https://tevfikbulut.com/2021/02/07/apriori-algoritmasi-uzerine-bir-vaka-calismasi-a-case-study-on-apriori-algorithm/