Ders notu linki: Bayes’ Rule

Bayes Kuralı

Collins Dictionary, yılın 2017 dönemini “sahte haberler” olarak adlandırdı. Ve iyi bir sebepten dolayı. Sahte, yanıltıcı ve önyargılı haberler, çevrimiçi haberler ve kullanıcıların çok az kalite kontrolüyle makaleler yayınlamasına olanak tanıyan sosyal medya platformlarıyla birlikte çoğaldı. O zaman okuyucuların makaleleri “gerçek” veya “sahte” olarak işaretlemesine yardımcı olmak giderek daha önemli hale gelmiştir.

Bu amaçla, Facebook’ta yayınlanan ve beş BuzzFeed gazetecisi tarafından doğrulanan 150 makaleden oluşan bir örneği inceleyeceğiz (Shu vd., 2017). Her makaleyle ilgili bilgiler “bayesrules” paketindeki “fake_news” veri kümesinde saklanır. Bu veri kümesi hakkında daha fazla bilgi edinmek için konsolunuza ?fake_news yazın.

#install.packages(c("tidyverse", "bayesrules", "janitor"))

library(bayesrules)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(janitor)
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
# Import article data
data(fake_news)

fake_news” verileri, hem gerçek hem de sahte olan gerçek haber makalelerinin tam metnini içerir. Bu nedenle, bu makalelerin bazıları rahatsız edici dil veya konular içeriyor. Meta veri yerine orijinal kaynaklarımızı sağlamanın önemli olduğuna inansak da, ileride analiz yapmak için makaleleri okumanıza gerek yok.

fake_news %>% 
  tabyl(type) %>% 
  adorn_totals("row")
##   type   n percent
##   fake  60     0.4
##   real  90     0.6
##  Total 150     1.0

tably() paketinde janitor kullanarak oluşturulan yukarıdaki tablo, bu özel koleksiyondaki makalelerin %40’ ının sahte ve %60’ nın gerçek olduğunu göstermektedir.

Sadece bu bilgiyi kullanarak, aşağıdaki kuralı kullanan çok basit bir haber filtresi oluşturabiliriz: çoğu makale gerçek olduğundan, tüm makaleleri okumalı ve inanmalıyız. Bu sonuç, gerçek makaleleri yanlışlıkla göz ardı etme sorununu kesinlikle çözecektir, ancak çok sayıda sahte haber okuma pahasına. Ayrıca bu sonuç, gerçek ve yalan haberlerin tipik özelliklerini değil, yalnızca genel oranlarını dikkate alır.

Örneğin, bir sosyal medya platformunda yayınlanan en son makalenin başlığının “Başkanın komik bir sırrı var!” başlığı olduğunu varsayalım. Bu başlıkta ünlem işaretinin kullanılması, gerçek bir haber makalesi için garip bir seçim gibi görünebilir.

#ünlem kullanımını ve makale türünü tablo hale getirme

fake_news %>% 
  tabyl(title_has_excl, type) %>% 
  adorn_totals("row")
##  title_has_excl fake real
##           FALSE   44   88
##            TRUE   16    2
##           Total   60   90

Verilerimiz bu içgüdüyü destekliyor – makale koleksiyonumuzda sahte haber başlıklarının %26,67’si (16/60) ancak gerçek haber başlıklarının, yalnızca %2,22’si (2/90) bir ünlem işareti kullanıyor.

Böylece, iki adet çelişkili bilgimiz var. Önceki bilgilerimiz, gelen makalelerin büyük olasılıkla gerçek olduğunu ileri sürdü. Ancak ünlem işareti verileri yalan haberlerle daha tutarlıdır. Bayesçiler gibi düşünerek, makalenin sahte olup olmadığına dair sonradan bir anlayış geliştirmede her iki bilgiyi dengelemenin önemli olduğunu biliyoruz.

Makalenin sahte olup olmadığına ilişkin Bayes bilgi oluşturma diyagramı. Diyagram1: Makalenin sahte olup olmadığına ilişkin Bayes bilgi oluşturma diyagramı.

Bayesci Model Oluşturma

Sahte haber analizimiz iki değişkenin incelenmesine dayanır: bir makalenin sahte & gerçek durumu ve ünlem işareti kullanımı. Bu özellikler makaleden makaleye değişebilir. Bazıları sahte, bazıları değil. Bazıları ünlem işareti kullanır, bazıları kullanmaz. Olasılık modellerini kullanarak bu değişkenlerdeki rastgeleliği temsil edebiliriz. En son makalenin sahte olup olmadığını önceden anlamamız için bir ön olasılık modeli oluşturacağız; ünlem işareti verilerini yorumlamak için bir model; ve son olarak, makalenin sahte olduğuna dair sonsal olasılığı özetleyen bir sonsal olasılık modeli.

Önsel olasılık modeli

Yazıların %40’ının sahte, %60’ının gerçek olduğunu daha önce tespit etmiştik. Sahte haberlerin önsel model olasılıkları;

Koşullu olasılık & likelihood

Başlıkta ünlem işareti kullanma ihtimali %26.67 bulmuştuk. Buna karşılık, bir makale gerçekse, ünlem işareti kullanma olasılığı yalnızca yaklaşık %2.22’dir. Sahte haberin koşullu olasılık ve likelihood olasılıkları;

Sonsal simülasyon

# Olası makaleleri tanımlayalım.
article <- data.frame(type = c("real", "fake"))

# Önsel bilgiyi tanımlayalım.
prior <- c(0.6, 0.4)

Sosyal medyanıza gönderilebilecek makaleleri simüle etmek için, makale veri çerçevesinden rastgele satırları örneklemek için “dplyr” paketindeki (Wickham vd.,2021) “sample_n()” işlevini kullanabiliriz.

#3 makaleyi simüle edelim.

set.seed(84735)
sample_n(article, size = 3, weight = prior, replace = TRUE)
##   type
## 1 fake
## 2 fake
## 3 real

3 makaleyi simüle ettik. Artık birkaç makaleyi nasıl simüle edeceğimizi anladığımıza göre, daha büyük hayal edelim: 10.000 makaleyi simüle edin ve sonuçları article_sim’de saklayın.

#10.000 makaleyi simüle edelim.

set.seed(84735)
article_sim <- sample_n(article, size = 10000, 
                        weight = prior, replace = TRUE)

Aşağıdaki tablo daha kapsamlı bir özet sunmaktadır. Bu 10.000 makalenin üretildiği modeli yansıtan, %40’ı sahte olduğuna dair:

ggplot(article_sim, aes(x = type)) + 
  geom_bar()

article_sim %>% 
  tabyl(type) %>% 
  adorn_totals("row")
##   type     n percent
##   fake  4031  0.4031
##   real  5969  0.5969
##  Total 10000  1.0000

Şimdi bu 10.000 makale arasında ünlem işareti kullanımını simüle edelim. “data_model” değişkeni, herhangi bir sahte makalenin %26.67 ve herhangi bir gerçek makalenin ünlem işareti kullanma olasılığının %2.22 olduğunu belirtir:

article_sim <- article_sim %>% 
  mutate(data_model = case_when(type == "fake" ~ 0.2667,
                                type == "real" ~ 0.0222))

glimpse(article_sim)
## Rows: 10,000
## Columns: 2
## $ type       <chr> "fake", "fake", "real", "fake", "fake", "real", "real", "re…
## $ data_model <dbl> 0.2667, 0.2667, 0.0222, 0.2667, 0.2667, 0.0222, 0.0222, 0.0…

Bu data_modelinden, her makalenin bir ünlem işareti içerip içermediğini simüle edebiliriz. İlk olarak, group_by() ifadesi, ünlem işareti simülasyonunun 10.000 makalenin her biri için ayrı ayrı gerçekleştirileceğini belirtir. İkinci olarak, data_modeline bağlı olarak ünlem işareti verilerini (hayır veya evet) simüle etmek için sample() kullanırız ve sonuçları usage olarak saklarız. sample() öğesinin sample_n() öğesine benzer olduğunu ancak veri çerçevelerindeki satırlar yerine vektörlerden değerleri örneklediğini unutmayın.

#ünlem işareti olup - olmadığını tanımlayalım.
data <- c("no", "yes")

#ünlem işareti kullanımını simüle edelim.
set.seed(3)
article_sim <- article_sim %>%
  group_by(1:n()) %>% 
  mutate(usage = sample(data, size = 1, 
                        prob = c(1 - data_model, data_model)))

Article_sim veri çerçevesi artık aşağıdaki tabloda özetlenen farklı özelliklere sahip 10.000 simüle edilmiş makale içermektedir. Buradaki kalıplar, sahte makalelerin yaklaşık %28’inin (1070/4031) ve gerçek makalelerin %2’sinin (136/5969) ünlem işareti kullanmasının altında yatan olasılıkları yansıtmaktadır.

article_sim %>% 
  tabyl(usage, type) %>% 
  adorn_totals(c("col","row"))
##  usage fake real Total
##     no 2961 5833  8794
##    yes 1070  136  1206
##  Total 4031 5969 10000

10.000 simüle edilmiş makalemiz artık önceki sahte haber modelini ve ayrıca sahte & gerçek haberler arasında ünlem işareti kullanım olasılığını yansıtıyor. Sırasıyla, son makalenin sahte olma olasılığını tahmin etmek için bunları kullanabiliriz. Bu amaçla, verilerimizle eşleşen benzetilmiş makaleleri (yani ünlem işareti kullananları) filtreleyebilir ve sahte makalelerin yüzdesini inceleyebiliriz:

article_sim %>% 
  filter(usage == "yes") %>% 
  tabyl(type) %>% 
  adorn_totals("row")
##   type    n   percent
##   fake 1070 0.8872305
##   real  136 0.1127695
##  Total 1206 1.0000000

Ünlem işareti kullanan 1206 simüle edilmiş makalenin kabaca %88,7’si sahtedir. Bu yaklaşım, 0.889’luk gerçek sonsal olasılığa oldukça yakındır.

ggplot(article_sim, aes(x = type)) + 
  geom_bar() + 
  facet_wrap(~ usage)

Elbette, farklı veriler görmüş olsaydık, yani başlıkta ünlem işareti olmasaydı, bu makaleye ilişkin son değerlendirmemiz değişecekti. Bir makale ünlem işareti kullanıyorsa, büyük olasılıkla sahtedir.Aksi takdirde, büyük olasılıkla gerçektir.

Beta - Binom Bayesci Model

Her dört yılda bir Amerikalılar, Amerika Birleşik Devletleri Başkanı oylarını kullanmak için sandık başına gidiyor. Aşağıdaki senaryoyu düşünün. “Michelle” başkanlığa aday olmaya karar verdi ve siz onun Minnesota eyaleti kampanya yöneticisisiniz. Bu nedenle, seçim sezonu boyunca 30 farklı anket gerçekleştirdiniz. Michelle’in desteği %45 civarında seyrediyor olsa da, kampanya yolundaki en kasvetli günlerde yaklaşık %35 ve en iyi günlerde yaklaşık %55’e çıkmıştır.

Seçimler dinamiktir, bu nedenle Michelle’in desteği her zaman değişkendir. Yine de bu geçmiş anketler hakkında önsel bilgi sağlar. π, şu anda Michelle’i destekleyen Minnesotalıların oranı. Aslında, bu bilgiyi resmi bir önsel olasılık modeline göre yeniden düzenleyebiliriz. Bununla birlikte, Michelle’in seçim desteği gerçeğinde, π 0 ile 1 arasında herhangi bir değer olabilir. Bu gerçeği yansıtabilir ve sürekli bir önsel olasılık modeli oluşturarak bir Bayes analizi yapabiliriz. π Michelle’in desteği π 0 ile 1 arasında herhangi bir yerde olabilir, ancak büyük olasılıkla 0.45 civarındadır.

Beta önseli ayarlamaları

π∼Beta(45,55) olasılık yoğunluk fonksiyonu;

plot_beta(45, 55)

f(π)=(Γ(100)/ Γ(45)Γ(55))*π44(1−π)54 for π∈[0,1].

Beta sonsal model

Artık Bayes modelimizin iki parçasına sahibiz – Michelle’in desteği için önsel Beta modeli π ve yoklama verilerinin bağımlılığı için Binom modeli

Y üzerinde π:

Michelle’in seçim desteğine ilişkin Bayes analizimizin ikinci adımında π, biraz veri toplamaya hazırsınız. Yeni bir anket yapmayı planlıyorsunuz.

n=50 Minnesotalılar ve rekor Y , Michelle’i destekleyen sayı.

Y|π∼Bin(50,π) π∼Beta(45,55)

plot_beta_binomial(alpha = 45, beta = 55, y = 30, n = 50)

Bayesrules” paketindeki “plot_beta_binomial()”işlevini kullanarak, önceki hiperparametreleri takarak bu doğru posterior yeniden oluşturabilirsiniz.

summarize_beta_binomial(alpha = 45, beta = 55, y = 30, n = 50)
##       model alpha beta mean      mode         var         sd
## 1     prior    45   55 0.45 0.4489796 0.002450495 0.04950248
## 2 posterior    75   75 0.50 0.5000000 0.001655629 0.04068942

Michelle’in π desteğinin sonsal modelini simüle edelim. rbeta() kullanmadan önce Beta(45,55)’ten 10.000 π değerini simüle ederek başlıyoruz ve ardından potansiyel bir Bin(50,π) rbinom() kullanarak her π’den Y için:

set.seed(84735)
sim <- data.frame(pi = rbeta(10000, 45, 55)) %>% 
  mutate(y = rbinom(10000, size = 50, prob = pi))


ggplot(sim, aes(x = pi, y = y)) + 
  geom_point(aes(color = (y == 30)), size = 0.1)

Yalnızca Y=30 anket sonuçlarımızla eşleşen çiftleri yakınlaştırdığımızda, kalan π değerleri kümesindeki davranış, π’nin Beta(45,55) sonsal modeline oldukça yakındır.

# Verilerimizle eşleşen simüle edilmiş çiftleri saklayalım.
sim_posterior <- sim %>% 
  filter(y == 30)

# Pi değerlerini çizdirelim.
ggplot(sim_posterior, aes(x = pi)) + 
  geom_density()

sim_posterior %>% 
  summarize(mean(pi), sd(pi))
##    mean(pi)     sd(pi)
## 1 0.5054909 0.03732097
nrow(sim_posterior)
## [1] 211

Michelle’in desteğinin %35 ile %55 arasında bir yerde olduğundan oldukça emin olabiliriz.

Bayesçi Basit Doğrusal Regresyon

Bu bölümde basit doğrusal regresyonlarda Bayes çıkarımına bakacağız. Sık kullanılan çözümler ve Bayes cevapları arasında bir bağlantı sağlayacak olan katsayılar üzerinde referans önsel dağılımını kullanacağız. Bu, daha bilgilendirici önsel dağılımlarla karşılaştırmalar için bir temel analiz sağlar. Fikirleri açıklamak için vücut yağını tahmin etme örneğini kullanacağız.

Vücut yağının doğru ölçümlerini elde etmek pahalıdır ve yapılması kolay değildir. Bunun yerine, karın çevresi gibi kolayca elde edilebilen ölçümleri kullanan vücut yağ yüzdesini tahmin eden tahmine dayalı modellerin kullanımı kolay ve ucuzdur. Bayesçi lineer regresyon yaklaşımını göstermek için bir örnek olarak karın çevresini kullanarak vücut yağını tahmin etmek için basit bir lineer regresyon uygulayacağız. Veri seti bodyfat, BAS kütüphanesinden bulunabilir.

library(BAS)
data(bodyfat)
summary(bodyfat)
##     Density         Bodyfat           Age            Weight     
##  Min.   :0.995   Min.   : 0.00   Min.   :22.00   Min.   :118.5  
##  1st Qu.:1.041   1st Qu.:12.47   1st Qu.:35.75   1st Qu.:159.0  
##  Median :1.055   Median :19.20   Median :43.00   Median :176.5  
##  Mean   :1.056   Mean   :19.15   Mean   :44.88   Mean   :178.9  
##  3rd Qu.:1.070   3rd Qu.:25.30   3rd Qu.:54.00   3rd Qu.:197.0  
##  Max.   :1.109   Max.   :47.50   Max.   :81.00   Max.   :363.1  
##      Height           Neck           Chest           Abdomen      
##  Min.   :29.50   Min.   :31.10   Min.   : 79.30   Min.   : 69.40  
##  1st Qu.:68.25   1st Qu.:36.40   1st Qu.: 94.35   1st Qu.: 84.58  
##  Median :70.00   Median :38.00   Median : 99.65   Median : 90.95  
##  Mean   :70.15   Mean   :37.99   Mean   :100.82   Mean   : 92.56  
##  3rd Qu.:72.25   3rd Qu.:39.42   3rd Qu.:105.38   3rd Qu.: 99.33  
##  Max.   :77.75   Max.   :51.20   Max.   :136.20   Max.   :148.10  
##       Hip            Thigh            Knee           Ankle          Biceps     
##  Min.   : 85.0   Min.   :47.20   Min.   :33.00   Min.   :19.1   Min.   :24.80  
##  1st Qu.: 95.5   1st Qu.:56.00   1st Qu.:36.98   1st Qu.:22.0   1st Qu.:30.20  
##  Median : 99.3   Median :59.00   Median :38.50   Median :22.8   Median :32.05  
##  Mean   : 99.9   Mean   :59.41   Mean   :38.59   Mean   :23.1   Mean   :32.27  
##  3rd Qu.:103.5   3rd Qu.:62.35   3rd Qu.:39.92   3rd Qu.:24.0   3rd Qu.:34.33  
##  Max.   :147.7   Max.   :87.30   Max.   :49.10   Max.   :33.9   Max.   :45.00  
##     Forearm          Wrist      
##  Min.   :21.00   Min.   :15.80  
##  1st Qu.:27.30   1st Qu.:17.60  
##  Median :28.70   Median :18.30  
##  Mean   :28.66   Mean   :18.23  
##  3rd Qu.:30.00   3rd Qu.:18.80  
##  Max.   :34.90   Max.   :21.40

Bu veri çerçevesi, erkeklerin vücut yağının ve bel çevresi (Karın) gibi diğer ölçümlerin 252 gözlemini içerir. Bodyfat yanıt değişkenini tahmin etmek için Abdomen kullanan basit bir lineer regresyon Bayes modeli oluşturacağız.

# Frekansçı en çok olabilirlik doğrusal regresyon

bodyfat.lm = lm(Bodyfat ~ Abdomen, data = bodyfat)

summary(bodyfat.lm)
## 
## Call:
## lm(formula = Bodyfat ~ Abdomen, data = bodyfat)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -19.0160  -3.7557   0.0554   3.4215  12.9007 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -39.28018    2.66034  -14.77   <2e-16 ***
## Abdomen       0.63130    0.02855   22.11   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.877 on 250 degrees of freedom
## Multiple R-squared:  0.6617, Adjusted R-squared:  0.6603 
## F-statistic: 488.9 on 1 and 250 DF,  p-value: < 2.2e-16
# Katsayıları belirlemek
beta = coef(bodyfat.lm)

# Dağılım grafiğinde regresyon eğrisini görselleştirelim.
library(ggplot2)
ggplot(data = bodyfat, aes(x = Abdomen, y = Bodyfat)) +
  geom_point(color = "blue") +
  geom_abline(intercept = beta[1], slope = beta[2], size = 1) +
  xlab("abdomen circumference (cm)") 
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Bu model doğruysa, artıklar ve tahmin değerler ilişkisiz olmalıdır ve artıkların beklenen değeri sıfırdır. Model yeterliliğinin ek bir görsel kontrolünü sağlayan, artıkların saçılım grafiğini görmekteyiz.

# n ve hataları elde etmek
resid = residuals(bodyfat.lm)
n = length(resid)

# MSE değeri
MSE = 1/ (n - 2) * sum((resid ^ 2))
MSE
## [1] 23.78985
# artıkları ve tahmin değerlerini bir data.frame ' de birleştirelim.

result = data.frame(fitted_values = fitted.values(bodyfat.lm),
                    residuals = residuals(bodyfat.lm))

# artıkları ve tahmin değerlerini birleştirelim.

library(ggplot2)

ggplot(data = result, aes(x = fitted_values, y = residuals)) +
  geom_point(pch = 1, size = 2) + 
  geom_abline(intercept = 0, slope = 0) + 
  xlab(expression(paste("fitted value ", widehat(Bodyfat)))) + 
  ylab("residuals")

# en büyük tahmine sahip gözlemi bulalım.

which.max(as.vector(fitted.values(bodyfat.lm)))
## [1] 39

Ayrıca, normal dağılmış hataların varsayımı için artıkların normal olasılık grafiğini kontrol edebiliriz. Sadece en geniş bel ölçüsüne sahip olan Case 39’un normalden uzak olduğunu görüyoruz.

which.max(bodyfat$Abdomen)
## [1] 39

Güvenilir aralıklar sayısal olarak güven aralıklarıyla aynı olduğundan, OLS tahminlerini elde etmek için lm fonksiyonunu kullanabilir ve güvenilir aralıkları oluşturabiliriz.

plot(bodyfat.lm, which = 2)

output = summary(bodyfat.lm)$coef[, 1:2]
output
##                Estimate Std. Error
## (Intercept) -39.2801847 2.66033696
## Abdomen       0.6313044 0.02855067
out = cbind(output, confint(bodyfat.lm))
colnames(out) = c("posterior mean", "posterior std", "2.5", "97.5")
round(out, 2)
##             posterior mean posterior std    2.5   97.5
## (Intercept)         -39.28          2.66 -44.52 -34.04
## Abdomen               0.63          0.03   0.58   0.69
# Mevcut tahmini oluşturalım.

alpha = bodyfat.lm$coefficients[1]
beta = bodyfat.lm$coefficients[2]
new_x = seq(min(bodyfat$Abdomen), max(bodyfat$Abdomen), 
            length.out = 100)
y_hat = alpha + beta * new_x
# Ortalama için alt ve üst sınırları belirleyelim.

ymean = data.frame(predict(bodyfat.lm,
                           newdata = data.frame(Abdomen = new_x),
                           interval = "confidence",
                           level = 0.95))
# tahminler için alt ve üst sınırları belirleyelim.
ypred = data.frame(predict(bodyfat.lm,
                           newdata = data.frame(Abdomen = new_x),
                           interval = "prediction",
                           level = 0.95))

output = data.frame(x = new_x, y_hat = y_hat, ymean_lwr = ymean$lwr, ymean_upr = ymean$upr, 
                    ypred_lwr = ypred$lwr, ypred_upr = ypred$upr)
# aykırı değeri ayıklayalım.

outlier = data.frame(x = bodyfat$Abdomen[39], y = bodyfat$Bodyfat[39])

pred.39 = predict(bodyfat.lm, newdata = bodyfat[39, ], interval = "prediction", level = 0.95)
out = cbind(bodyfat[39,]$Abdomen, pred.39)
colnames(out) = c("abdomen", "prediction", "lower", "upper")
out
##    abdomen prediction   lower    upper
## 39   148.1   54.21599 44.0967 64.33528
#
outliers = Bayes.outlier(bodyfat.lm, k=3)

# Aykırı değer Case39'un olasılığını bulalım.

prob.39 = outliers$prob.outlier[39]
prob.39
## [1] 0.9916833

Bu vakanın, 0.992’lik son derece yüksek bir aykırı değer olma olasılığına sahip olduğunu görüyoruz.