Ders notu linki: Bayes’ Rule
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.
Diyagram1: Makalenin sahte olup olmadığına ilişkin
Bayes bilgi oluşturma diyagramı.
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.
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ı;

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.
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(45,55) olasılık yoğunluk fonksiyonu;
plot_beta(45, 55)
f(π)=(Γ(100)/ Γ(45)Γ(55))*π44(1−π)54 for π∈[0,1].
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.
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.