R'de GLM: Genelleştirilmiş Doğrusal Model ve Lojistik Regresyon
⚡ Akıllı Özet
R'deki Genelleştirilmiş Doğrusal Model (GLM), sıradan regresyonu ikili, sayım tabanlı veya normal dağılıma uymayan sonuçlara genişletir. Bu kılavuz, yetişkin gelir veri kümesi üzerinde lojistik bir GLM oluşturur ve bunu doğruluk, hassasiyet, geri çağırma ve ROC ile değerlendirir.

R programlama dilinde Genelleştirilmiş Doğrusal Model (GLM) nedir?
A Genelleştirilmiş Doğrusal Model (GLM) Bu yöntem, yanıt değişkeninin normal dağılımdan farklı bir dağılımı izleyebilmesi için sıradan doğrusal regresyonu genişletir. Rİçine dahili bir parça takarsınız. glm() stats paketindeki fonksiyon.
Her GLM üç bileşenle tanımlanır:
- Rastgele bileşen: Yanıt değişkeninin olasılık dağılımı, üstel dağılım ailesinden (binom, Poisson, Gamma, Gauss ve diğerleri) alınmıştır.
- Sistematik bileşen: Doğrusal tahminleyici, yani açıklayıcı değişkenlerinizin ağırlıklı kombinasyonu.
- Bağlantı işlevi: Yanıt değişkeninin ortalamasını doğrusal tahmin ediciye bağlayan fonksiyon; örneğin, ikili veriler için logit bağlantısı veya sayılar için log bağlantısı.
Bu yapı, modeli "genelleştirilmiş" kılan şeydir. Normal dağılımlı bir sonucu zorlamak yerine, doğru dağılımı şu şekilde belirtirsiniz: aile Bu argüman ve R, katsayıları maksimum olasılık yöntemiyle tahmin eder. Lojistik regresyon, basitçe bir binom ailesi ve logit bağlantısı içeren bir GLM'dir, bu nedenle doğal bir başlangıç noktasıdır.
R programlama dilinde Lojistik Regresyon nedir?
Lojistik regresyon bir sınıfı, yani bir olasılığı tahmin etmek için kullanılır. Lojistik regresyon ikili bir sonucu doğru bir şekilde tahmin edebilir.
Birçok özelliğe dayanarak bir kredinin reddedilip kabul edilmeyeceğini tahmin etmek istediğinizi düşünün. Lojistik regresyon 0/1 formundadır. Bir kredi reddedilirse y = 0, kabul edilirse y = 1.
Lojistik regresyon modeli doğrusal regresyon modelinden iki açıdan farklılık gösterir.
- Her şeyden önce, lojistik regresyon bağımlı değişken (yani 0 ve 1 vektörü) olarak yalnızca ikili (ikili) girdiyi kabul eder.
- İkinci olarak, sonuç, olasılıksal bir bağlantı fonksiyonu adı verilen bir fonksiyon aracılığıyla haritalandırılır. sigmoid (S şeklinden dolayı lojistik işlevi görür):
Fonksiyonun çıkışı her zaman 0 ile 1 arasındadır. Aşağıdaki Resmi Kontrol Edin
Sigmoid işlevi 0'dan 1'e kadar değerler döndürür. Sınıflandırma görevi için 0 veya 1 şeklinde ayrık bir çıktıya ihtiyacımız var.
Sürekli bir akışı ayrık değere dönüştürmek için 0.5 sınırını belirleyebiliriz. Bu eşiğin üzerindeki tüm değerler 1 olarak sınıflandırılır
Bağlantı fonksiyonu artık netleştiğine göre, genelleştirilmiş modeli daha önce bildiğiniz sıradan doğrusal modelle karşılaştırın.
GLM ve Doğrusal Regresyon: R'deki Temel Farklar
Herhangi bir kod yazmadan önce, standardın tam olarak ne zaman geçerli olduğunu bilmek faydalıdır. doğrusal regresyon lm() fonksiyonu artık uygun değil ve onun yerine glm() fonksiyonu kullanılmalıdır.
| Kriterler | Doğrusal Regresyon (lm) | Genelleştirilmiş Doğrusal Model (glm) |
|---|---|---|
| Yanıt değişkeni | Sürekli ve sınırsız | İkili, sayım, oran veya pozitif sürekli |
| Hata dağılımı | Sadece normal | Üstel aile üyelerinden herhangi biri |
| Bağlantı işlevi | Kimlik (örtük) | Açıkça belirtilenler: logit, log, ters, probit |
| Tahmin yöntemi | Sıradan en küçük kareler | Maksimum olasılık (IRLS) |
| Varyans varsayımı | Gözlemler boyunca sabittir. | Ortalamaya bağlı olmasına izin verilir. |
| Uygunluk ölçüsü | R-kare | AIC ve artık sapma |
| R işlevi | lm(formül, veri) | glm(formül, veri, aile) |
Özetle, sonuç normal dağılımlı bir ölçüm olduğunda lm() fonksiyonunu, sonuç evet/hayır kararı olduğunda ise glm() fonksiyonunu seçin; bu görevi başka birine de devredebilirsiniz. karar ağacı Sınıflandırıcı, olay sayısı veya yayılımı ortalamasıyla birlikte artan kesinlikle pozitif bir nicelik.
R'de Genelleştirilmiş Doğrusal Model (GLM) Nasıl Oluşturulur?
Teorik temeller oturtulduktan sonra, bu eğitimin geri kalanında gerçek bir veri kümesi üzerinde uçtan uca bir binom GLM uygulanacaktır.
Kullanalım yetişkin Lojistik regresyonu göstermek için kullanılan veri seti. "Yetişkin" veri seti, sınıflandırma görevi için harika bir örnektir. Amaç, bir bireyin yıllık gelirinin ABD doları cinsinden 50,000'i aşıp aşmayacağını tahmin etmektir. Veri seti 48,842 gözlem ve on değişken içermektedir:
- yaş: bireyin yaşı. Sayısal
- eğitim: Bireyin eğitim düzeyi. Faktör.
- medeni.durum: Maribireyin tal durumu. Faktör yani Hiç evlenmemiş, Evli-vatandaş-eş,…
- cinsiyet: Bireyin cinsiyeti. Faktör, yani Erkek veya Kadın
- Gelir: Target değişken. Gelir 50'in üstünde veya altında. Faktör yani >50K, <=50K
diğerleri arasında
library(dplyr) data_adult <-read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult.csv") glimpse(data_adult)
Çıktı:
Observations: 48,842 Variables: 10 $ x <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,... $ age <int> 25, 38, 28, 44, 18, 34, 29, 63, 24, 55, 65, 36, 26... $ workclass <fctr> Private, Private, Local-gov, Private, ?, Private,... $ education <fctr> 11th, HS-grad, Assoc-acdm, Some-college, Some-col... $ educational.num <int> 7, 9, 12, 10, 10, 6, 9, 15, 10, 4, 9, 13, 9, 9, 9,... $ marital.status <fctr> Never-married, Married-civ-spouse, Married-civ-sp... $ race <fctr> Black, White, White, Black, White, White, Black, ... $ gender <fctr> Male, Male, Male, Male, Female, Male, Male, Male,... $ hours.per.week <int> 40, 50, 40, 40, 30, 30, 40, 32, 40, 10, 40, 40, 39... $ income <fctr> <=50K, <=50K, >50K, >50K, <=50K, <=50K, <=50K, >5...
Aşağıdaki gibi ilerleyeceğiz:
- Adım 1: Sürekli değişkenleri kontrol edin
- Adım 2: Faktör değişkenlerini kontrol edin
- 3. Adım: Özellik mühendisliği
- Adım 4: Özet istatistik
- Adım 5: Eğitim/test seti
- 6. Adım: Modeli oluşturun
- Adım 7: Modelin performansını değerlendirin
- Adım 8: Modeli geliştirin
Göreviniz hangi bireyin 50'den yüksek gelire sahip olacağını tahmin etmektir.
Bu eğitimde, gerçek bir veri kümesi üzerinde analiz gerçekleştirmek için her adım ayrıntılı olarak anlatılacaktır.
Adım 1) Sürekli değişkenleri kontrol edin
İlk adımda sürekli değişkenlerin dağılımını görebilirsiniz.
continuous <-select_if(data_adult, is.numeric) summary(continuous)
Code açıklama
- sürekli <- select_if(data_adult, is.numeric): Yalnızca sayısal sütunları seçmek için dplyr kitaplığından select_if() işlevini kullanın
- özet(sürekli): Özet istatistiğini yazdır
Çıktı:
## X age educational.num hours.per.week ## Min. : 1 Min. :17.00 Min. : 1.00 Min. : 1.00 ## 1st Qu.:11509 1st Qu.:28.00 1st Qu.: 9.00 1st Qu.:40.00 ## Median :23017 Median :37.00 Median :10.00 Median :40.00 ## Mean :23017 Mean :38.56 Mean :10.13 Mean :40.95 ## 3rd Qu.:34525 3rd Qu.:47.00 3rd Qu.:13.00 3rd Qu.:45.00 ## Max. :46033 Max. :90.00 Max. :16.00 Max. :99.00
Yukarıdaki tablodan, verilerin tamamen farklı ölçeklere sahip olduğunu ve hafta başına saat sayısının büyük aykırı değerlere sahip olduğunu görebilirsiniz (örn. son çeyreğe ve maksimum değere bakın).
Bunu iki adımda halledebilirsiniz:
- Haftalık çalışma saatlerinin dağılımını grafikte gösterin.
- Sürekli değişkenleri standartlaştırın
- Dağıtımın grafiğini çizin
Hafta başına saat dağılımına daha yakından bakalım
# Histogram with kernel density curve library(ggplot2) ggplot(continuous, aes(x = hours.per.week)) + geom_density(alpha = .2, fill = "#FF6666")
Çıktı:
Değişken çok sayıda aykırı değere sahiptir ve iyi tanımlanmış bir dağılıma sahip değildir. Haftalık saatlerin en üst yüzde 0.01'ini silerek bu sorunu kısmen çözebilirsiniz.
Niceliğin temel sözdizimi:
quantile(variable, percentile) arguments: -variable: Select the variable in the data frame to compute the percentile -percentile: Can be a single value between 0 and 1 or multiple value. If multiple, use this format: `c(A,B,C, ...) - `A`,`B`,`C` and `...` are all integer from 0 to 1.
Haftalık çalışma saatlerinin 99. yüzdelik dilimini hesaplıyoruz.
top_one_percent <- quantile(data_adult$hours.per.week, .99)
top_one_percent
Code açıklama
- quantile(data_adult$hours.per.week, .99): Haftalık çalışma süresinin 99. yüzdelik dilimini hesaplar.
Çıktı:
## 99% ## 80
Nüfusun yüzde 99'i haftada 80 saatin altında çalışıyor.
Gözlemleri bu eşiğin üzerine bırakabilirsiniz. Filtreyi şuradan kullanabilirsiniz: dplyr kütüphane.
data_adult_drop <-data_adult %>% filter(hours.per.week<top_one_percent) dim(data_adult_drop)
Çıktı:
## [1] 45537 10
- Sürekli değişkenleri standartlaştırın
Verileriniz aynı ölçeğe sahip olmadığından performansı artırmak için her sütunu standartlaştırabilirsiniz. Dplyr kütüphanesindeki mutate_if fonksiyonunu kullanabilirsiniz. Temel sözdizimi şöyledir:
mutate_if(df, condition, funs(function)) arguments: -`df`: Data frame used to compute the function - `condition`: Statement used. Do not use parenthesis - funs(function): Return the function to apply. Do not use parenthesis for the function
Sayısal sütunları aşağıdaki gibi standartlaştırabilirsiniz:
data_adult_rescale <- data_adult_drop %>% mutate_if(is.numeric, funs(as.numeric(scale(.)))) head(data_adult_rescale)
Code açıklama
- mutate_if(is.numeric, funs(scale)): Koşul yalnızca sayısal sütundur ve işlev ölçektir
Çıktı:
## X age workclass education educational.num ## 1 -1.732680 -1.02325949 Private 11th -1.22106443 ## 2 -1.732605 -0.03969284 Private HS-grad -0.43998868 ## 3 -1.732530 -0.79628257 Local-gov Assoc-acdm 0.73162494 ## 4 -1.732455 0.41426100 Private Some-college -0.04945081 ## 5 -1.732379 -0.34232873 Private 10th -1.61160231 ## 6 -1.732304 1.85178149 Self-emp-not-inc Prof-school 1.90323857 ## marital.status race gender hours.per.week income ## 1 Never-married Black Male -0.03995944 <=50K ## 2 Married-civ-spouse White Male 0.86863037 <=50K ## 3 Married-civ-spouse White Male -0.03995944 >50K ## 4 Married-civ-spouse Black Male -0.03995944 >50K ## 5 Never-married White Male -0.94854924 <=50K ## 6 Married-civ-spouse White Male -0.76683128 >50K
Adım 2) Faktör değişkenlerini kontrol edin
Bu adımın iki amacı vardır:
- Her kategorik sütundaki seviyeyi kontrol edin
- Yeni seviyeleri tanımlayın
Bu adımı üç bölüme ayıracağız:
- Kategorik sütunları seçin
- Her sütunun çubuk grafiğini bir listede saklayın
- Grafikleri yazdır
Faktör sütunlarını aşağıdaki kodla seçebiliriz:
# Select categorical column factor <- data.frame(select_if(data_adult_rescale, is.factor)) ncol(factor)
Code açıklama
- data.frame(select_if(data_adult, is.factor)): Faktör sütunlarını bir veri çerçevesi tipinde faktörde saklıyoruz. ggplot2 kütüphanesi bir veri çerçevesi nesnesi gerektirir.
Çıktı:
## [1] 6
Veri seti 6 kategorik değişken içeriyor
İkinci adım daha zahmetli. Veri çerçevesindeki her sütun için bir çubuk grafik çizmek istiyorsunuz. Özellikle çok sayıda sütun olduğunda, bu süreci otomatikleştirmek daha uygun olacaktır.
library(ggplot2) # Create graph for each column graph <- lapply(names(factor), function(x) ggplot(factor, aes(get(x))) + geom_bar() + theme(axis.text.x = element_text(angle = 90)))
Code açıklama
- lapply(): Veri kümesinin tüm sütunlarına bir işlev iletmek için lapply() işlevini kullanın. Çıktıyı bir listede saklarsınız
- fonksiyon(x): Fonksiyon her x için işlenecektir. Burada x sütunlardır
- ggplot(factor, aes(get(x))) + geom_bar()+ theme(axis.text.x = element_text(angle = 90))): Her x öğesi için bir çubuk karakter grafiği oluşturun. X'i bir sütun olarak döndürmek için onu get() içine eklemeniz gerektiğini unutmayın.
Son adım nispeten kolaydır. 6 grafiği yazdırmak istiyorsunuz.
# Print the graph
graph
Çıktı:
## [[1]]
## ## [[2]]
## ## [[3]]
## ## [[4]]
## ## [[5]]
## ## [[6]]
Not: Sonraki grafiğe gitmek için sonraki düğmesini kullanın
Adım 3) Özellik mühendisliği
İki kategorik değişken, modelin ihtiyaç duyduğundan daha fazla seviye içeriyor. Bunları daha geniş ve daha fazla sayıda alt öğe içeren kategoriler halinde yeniden gruplandıracaksınız.
Eğitimi yeniden şekillendirin
Yukarıdaki grafikten eğitim değişkeninin 16 seviyeye sahip olduğunu görebilirsiniz. Bu oldukça önemlidir ve bazı düzeylerde gözlem sayısı nispeten düşüktür. Bu değişkenden alabileceğiniz bilgi miktarını artırmak istiyorsanız onu daha yüksek bir seviyeye yeniden düzenleyebilirsiniz. Yani benzer eğitim seviyesinde daha büyük gruplar oluşturuyorsunuz. Örneğin düşük eğitim seviyesi okulu bırakmaya dönüşecek. Daha yüksek eğitim seviyeleri yüksek lisansa dönüştürülecek.
İşte ayrıntı:
| Eski seviye | Yeni seviye |
|---|---|
| Okul öncesi | bırakmak |
| 10th | Bırakmak |
| 11th | Bırakmak |
| 12th | Bırakmak |
| 1-4 | Bırakmak |
| 5th-6th | Bırakmak |
| 7th-8th | Bırakmak |
| 9th | Bırakmak |
| HS-Grad | Yüksek Grad |
| Bazı üniversite | Topluluk |
| Assoc-acdm | Topluluk |
| Doç-voc | Topluluk |
| Lisans | Lisans |
| Masters | Masters |
| Prof-okul | Masters |
| Doktora | Doktora |
recast_data <- data_adult_rescale %>% select(-X) %>% mutate(education = factor(ifelse(education == "Preschool" | education == "10th" | education == "11th" | education == "12th" | education == "1st-4th" | education == "5th-6th" | education == "7th-8th" | education == "9th", "dropout", ifelse(education == "HS-grad", "HighGrad", ifelse(education == "Some-college" | education == "Assoc-acdm" | education == "Assoc-voc", "Community", ifelse(education == "Bachelors", "Bachelors", ifelse(education == "Masters" | education == "Prof-school", "Master", "PhD")))))))
Code açıklama
- Dplyr kütüphanesindeki mutate fiilini kullanıyoruz. ifelse cümlesi ile eğitimin değerlerini değiştiriyoruz
Aşağıdaki tabloda, Lisans, Yüksek Lisans veya Doktora derecesine ulaşmak için ortalama kaç yıllık eğitim (z değeri) gerektiğini görmek için bir özet istatistik oluşturacaksınız.
recast_data %>% group_by(education) %>% summarize(average_educ_year = mean(educational.num), count = n()) %>% arrange(average_educ_year)
Çıktı:
## # A tibble: 6 x 3 ## education average_educ_year count ## <fctr> <dbl> <int> ## 1 dropout -1.76147258 5712 ## 2 HighGrad -0.43998868 14803 ## 3 Community 0.09561361 13407 ## 4 Bachelors 1.12216282 7720 ## 5 Master 1.60337381 3338 ## 6 PhD 2.29377644 557
Değişiklik Maritoplam durum
Medeni durum için daha düşük seviyeler oluşturmak da mümkündür. Aşağıdaki kodda seviyeyi şu şekilde değiştirirsiniz:
| Eski seviye | Yeni seviye |
|---|---|
| Hiç evlenmemiş | Bekar |
| Evli-eş-yok | Bekar |
| Evli-AF-eş | Evli |
| evli-vatandaş-eş | |
| Ayrık | Ayrık |
| Boşanmış | |
| dullar | Dul |
# Change level marry recast_data <- recast_data %>% mutate(marital.status = factor(ifelse(marital.status == "Never-married" | marital.status == "Married-spouse-absent", "Not_married", ifelse(marital.status == "Married-AF-spouse" | marital.status == "Married-civ-spouse", "Married", ifelse(marital.status == "Separated" | marital.status == "Divorced", "Separated", "Widow")))))
Her gruptaki birey sayısını kontrol edebilirsiniz.
table(recast_data$marital.status)
Çıktı:
## ## Married Not_married Separated Widow ## 21165 15359 7727 1286
Adım 4) Özet İstatistik
Hedef değişkenlerimizle ilgili bazı istatistikleri kontrol etmenin zamanı geldi. Aşağıdaki grafikte cinsiyetlerine göre 50'den fazla kazanan bireylerin yüzdesini sayıyorsunuz.
# Plot gender income ggplot(recast_data, aes(x = gender, fill = income)) + geom_bar(position = "fill") + theme_classic()
Çıktı:
Daha sonra bireyin kökeninin kazancını etkileyip etkilemediğini kontrol edin.
# Plot origin income ggplot(recast_data, aes(x = race, fill = income)) + geom_bar(position = "fill") + theme_classic() + theme(axis.text.x = element_text(angle = 90))
Çıktı:
Cinsiyete göre çalışma saatleri.
# box plot gender working time ggplot(recast_data, aes(x = gender, y = hours.per.week)) + geom_boxplot() + stat_summary(fun.y = mean, geom = "point", size = 3, color = "steelblue") + theme_classic()
Çıktı:
Kutu grafiği, çalışma süresinin dağılımının farklı gruplara uyduğunu doğrular. Kutu grafiğinde, her iki cinsiyetin de homojen gözlemleri yoktur.
Eğitim türüne göre haftalık çalışma süresinin yoğunluğunu kontrol edebilirsiniz. Dağılımlarda birçok farklı nokta bulunmaktadır. Bu durum muhtemelen eğitim türüyle açıklanabilir.tracABD'de.
# Plot distribution working time by education ggplot(recast_data, aes(x = hours.per.week)) + geom_density(aes(color = education), alpha = 0.5) + theme_classic()
Code açıklama
- ggplot(recast_data, aes( x=hour.per.week))): Yoğunluk grafiği yalnızca bir değişken gerektirir
- geom_density(aes(renk = eğitim), alpha =0.5): Yoğunluğu kontrol eden geometrik nesne
Çıktı:
Düşüncelerinizi doğrulamak için tek yönlü bir işlem gerçekleştirebilirsiniz. ANOVA testi:
anova <- aov(hours.per.week~education, recast_data) summary(anova)
Çıktı:
## Df Sum Sq Mean Sq F value Pr(>F) ## education 5 1552 310.31 321.2 <2e-16 *** ## Residuals 45531 43984 0.97 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
ANOVA testi gruplar arasındaki ortalama farkını doğrular.
Sigara doğrusallık
Modeli çalıştırmadan önce çalışılan saat sayısının yaşla ilişkili olup olmadığını görebilirsiniz.
library(ggplot2) ggplot(recast_data, aes(x = age, y = hours.per.week)) + geom_point(aes(color = income), size = 0.5) + stat_smooth(method = 'lm', formula = y~poly(x, 2), se = TRUE, aes(color = income)) + theme_classic()
Code açıklama
- ggplot(recast_data, aes(x = yaş, y = saat.per.hafta))): Grafiğin estetiğini ayarlayın
- geom_point(aes(renk=gelir), boyut =0.5): Nokta grafiğini oluşturun
- stat_smooth(): Aşağıdaki argümanlarla trend çizgisini ekleyin:
- method='lm': Eğer uygunsa, uygun değeri çizin doğrusal regresyon
- formül = y~poli(x,2): Bir polinom regresyonunu uydurun
- se = DOĞRU: Standart hatayı ekleyin
- aes(renk= gelir): Modeli gelire göre ayırın
Çıktı:
Özetle, haftalık çalışma süresi ile diğer özellikler arasındaki doğrusal olmama etkisini tespit etmek için modeldeki etkileşim terimlerini test edebilirsiniz. Çalışma süresinin hangi koşullar altında farklılık gösterdiğinin tespiti önemlidir.
Ilişki
Bir sonraki kontrol değişkenler arasındaki korelasyonun görselleştirilmesidir. Spearman yöntemiyle hesaplanan korelasyon katsayısını içeren bir ısı haritası çizebilmek için faktör düzeyi türünü sayısala dönüştürürsünüz.
library(GGally) # Convert data to numeric corr <- data.frame(lapply(recast_data, as.integer)) # Plot the graphggcorr(corr, method = c("pairwise", "spearman"), nbreaks = 6, hjust = 0.8, label = TRUE, label_size = 3, color = "grey50")
Code açıklama
- data.frame(lapply(recast_data,as.integer)): Verileri sayısala dönüştür
- ggcorr() ısı haritasını aşağıdaki argümanlarla çizer:
- yöntem: Korelasyonu hesaplama yöntemi
- nbreaks = 6: Mola sayısı
- hjust = 0.8: Grafikteki değişken adının kontrol konumu
- etiket = TRUE: Pencerelerin ortasına etiketler ekle
- label_size = 3: Boyut etiketleri
- color = “gri50”): Etiketin rengi
Çıktı:
Adım 5) Eğitim/test seti
Denetlenen herhangi biri makine öğrenme Bu görev, verileri bir eğitim seti ve bir test seti arasında bölmenizi gerektirir. Eğitim/test seti oluşturmak için diğer denetimli öğrenme eğitimlerinde oluşturduğunuz "fonksiyonu" kullanabilirsiniz.
set.seed(1234) create_train_test <- function(data, size = 0.8, train = TRUE) { n_row = nrow(data) total_row = size * n_row train_sample <- 1: total_row if (train == TRUE) { return (data[train_sample, ]) } else { return (data[-train_sample, ]) } } data_train <- create_train_test(recast_data, 0.8, train = TRUE) data_test <- create_train_test(recast_data, 0.8, train = FALSE) dim(data_train)
Çıktı:
## [1] 36429 9
dim(data_test)
Çıktı:
## [1] 9108 9
Adım 6) Modeli oluşturun
Algoritmanın performansını görmek için stats paketindeki glm() fonksiyonunu kullanabilirsiniz. Genelleştirilmiş Doğrusal Model modellerden oluşan bir koleksiyondur. Temel sözdizimi şöyledir:
glm(formula, data=data, family=linkfunction() Argument: - formula: Equation used to fit the model- data: dataset used - Family: - binomial: (link = "logit") - gaussian: (link = "identity") - Gamma: (link = "inverse") - inverse.gaussian: (link = "1/mu^2") - poisson: (link = "log") - quasi: (link = "identity", variance = "constant") - quasibinomial: (link = "logit") - quasipoisson: (link = "log")
Gelir düzeyini bir dizi özellik arasında bölmek için lojistik modeli tahmin etmeye hazırsınız.
formula <- income~. logit <- glm(formula, data = data_train, family = 'binomial') summary(logit)
Code açıklama
- formül <- gelir ~.: Uygun modeli oluşturun
- logit <- glm(formula, data = data_train, family = 'binom'): Data_train verileriyle bir lojistik modeli (aile = 'binom') yerleştirin.
- Summary(logit): Modelin özetini yazdırır
Çıktı:
## ## Call: ## glm(formula = formula, family = "binomial", data = data_train) ## ## Deviance Residuals: ## Min 1Q Median 3Q Max ## -2.6456 -0.5858 -0.2609 -0.0651 3.1982 ## ## Coefficients: ## Estimate Std. Error z value Pr(>|z|) ## (Intercept) 0.07882 0.21726 0.363 0.71675 ## age 0.41119 0.01857 22.146 < 2e-16 *** ## workclassLocal-gov -0.64018 0.09396 -6.813 9.54e-12 *** ## workclassPrivate -0.53542 0.07886 -6.789 1.13e-11 *** ## workclassSelf-emp-inc -0.07733 0.10350 -0.747 0.45499 ## workclassSelf-emp-not-inc -1.09052 0.09140 -11.931 < 2e-16 *** ## workclassState-gov -0.80562 0.10617 -7.588 3.25e-14 *** ## workclassWithout-pay -1.09765 0.86787 -1.265 0.20596 ## educationCommunity -0.44436 0.08267 -5.375 7.66e-08 *** ## educationHighGrad -0.67613 0.11827 -5.717 1.08e-08 *** ## educationMaster 0.35651 0.06780 5.258 1.46e-07 *** ## educationPhD 0.46995 0.15772 2.980 0.00289 ** ## educationdropout -1.04974 0.21280 -4.933 8.10e-07 *** ## educational.num 0.56908 0.07063 8.057 7.84e-16 *** ## marital.statusNot_married -2.50346 0.05113 -48.966 < 2e-16 *** ## marital.statusSeparated -2.16177 0.05425 -39.846 < 2e-16 *** ## marital.statusWidow -2.22707 0.12522 -17.785 < 2e-16 *** ## raceAsian-Pac-Islander 0.08359 0.20344 0.411 0.68117 ## raceBlack 0.07188 0.19330 0.372 0.71001 ## raceOther 0.01370 0.27695 0.049 0.96054 ## raceWhite 0.34830 0.18441 1.889 0.05894 . ## genderMale 0.08596 0.04289 2.004 0.04506 * ## hours.per.week 0.41942 0.01748 23.998 < 2e-16 *** ## ---## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## (Dispersion parameter for binomial family taken to be 1) ## ## Null deviance: 40601 on 36428 degrees of freedom ## Residual deviance: 27041 on 36406 degrees of freedom ## AIC: 27087 ## ## Number of Fisher Scoring iterations: 6
Modelimizin özeti ilginç bilgileri ortaya koyuyor. Lojistik regresyonun performansı belirli temel ölçümlerle değerlendirilir.
- AIC (Akaike Bilgi Kriterleri): Bu, şuna eşdeğerdir: R2 lojistik regresyonda. Parametre sayısına bir ceza uygulandığında uyumu ölçer. Daha küçük AIC değerler modelin gerçeğe daha yakın olduğunu göstermektedir.
- Boş sapma: Modele yalnızca kesişme noktasıyla uyar. Serbestlik derecesi n-1'dir. Bunu bir Ki-kare değeri (gerçek değer hipotez testinden farklı olan uygun değer) olarak yorumlayabiliriz.
- Artık Sapma: Tüm değişkenleri içeren model. Aynı zamanda Ki-kare hipotez testi olarak da yorumlanır.
- Fisher Puanlaması yinelemelerinin sayısı: Yakınsamadan önceki yinelemelerin sayısı.
glm() fonksiyonunun çıktısı bir listede saklanır. Aşağıdaki kod, lojistik regresyonu değerlendirmek için oluşturduğumuz logit değişkeninde bulunan tüm öğeleri gösterir.
# Liste çok uzun, yalnızca ilk üç öğeyi yazdır
lapply(logit, class)[1:3]
Çıktı:
## $coefficients ## [1] "numeric" ## ## $residuals ## [1] "numeric" ## ## $fitted.values ## [1] "numeric"
Her değer şu şekilde olabilir:trac$ işaretiyle birlikte metriklerin adı yazılır. Örneğin, modeli logit olarak kaydettiniz.tracAIC kriterlerine göre şunları kullanırsınız:
logit$aic
Çıktı:
## [1] 27086.65
Adım 7) Modelin performansını değerlendirin
Karışıklık Matrisi
MKS karışıklık matrisi sınıflandırma performansını değerlendirmek için daha önce gördüğünüz farklı metriklerle karşılaştırıldığında daha iyi bir seçimdir. Genel fikir, True örneklerinin kaç kez Yanlış olarak sınıflandırıldığını saymaktır.
Karışıklık matrisini hesaplamak için öncelikle gerçek hedeflerle karşılaştırılabilecek bir dizi tahmine sahip olmanız gerekir.
predict <- predict(logit, data_test, type = 'response') # confusion matrix table_mat <- table(data_test$income, predict > 0.5) table_mat
Code açıklama
- tahmin(logit,data_test, type = 'response'): Test kümesindeki tahmini hesaplayın. Yanıt olasılığını hesaplamak için type = 'response' değerini ayarlayın.
- table(data_test$income, tahmin > 0.5): Karışıklık matrisini hesaplayın. tahmin > 0.5, tahmin edilen olasılıklar 1'in üzerindeyse 0.5, aksi halde 0 döndürdüğü anlamına gelir.
Çıktı:
## ## FALSE TRUE ## <=50K 6310 495 ## >50K 1074 1229
Karmaşıklık matrisindeki her satır gerçek bir hedefi, her sütun ise tahmin edilen bir hedefi temsil eder. Bu matrisin ilk satırı 50'den düşük geliri (negatif sınıf) dikkate alır: 6,310 gözlem, geliri 50'den düşük bireyler olarak doğru şekilde sınıflandırılmıştır (Gerçek negatif495'i ise yanlışlıkla 50'in üzerinde olarak sınıflandırılmıştı (Yanlış pozitifİkinci satırda 50'in üzerindeki gelirler dikkate alınmıştır: 1,229'u doğru şekilde belirlenmiştir (gerçek pozitif), 1,074'ü ise gözden kaçırıldı (Yanlış negatif).
Modeli hesaplayabilirsiniz doğruluk toplam gözlem üzerinden gerçek pozitif + gerçek negatifin toplanmasıyla
accuracy_Test <- sum(diag(table_mat)) / sum(table_mat) accuracy_Test
Code açıklama
- toplam(diag(table_mat))): Köşegenin toplamı
- sum(table_mat): Matrisin toplamı.
Çıktı:
## [1] 0.8277339
Modelin bir sorunu var gibi görünüyor: çok fazla yanlış negatif üretiyor. Buna yanlış negatif denir. doğruluk testi paradoksuDoğruluk oranının, doğru tahminlerin toplam vaka sayısına oranı olduğunu belirtmiştik. Nispeten yüksek bir doğruluk oranına sahip olabiliriz, ancak model işe yaramaz olabilir. Bu, baskın bir sınıf olduğunda olur. Karışıklık matrisine geri dönersek, vakaların çoğunun gerçek negatif olarak sınıflandırıldığını görebiliriz. Şimdi, modelin her gözlemi negatif (yani 50'den düşük) olarak sınıflandırdığını hayal edin. Yine de yaklaşık %75'lik bir doğruluk oranı elde edersiniz (6,805 / 9,108). Modeliniz daha iyi performans gösterir, ancak gerçek pozitif ile gerçek negatifi ayırt etmekte zorlanır.
Böyle bir durumda daha kısa bir ölçütün kullanılması tercih edilir. Şuna bakabiliriz:
- Hassasiyet=TP/(TP+FP)
- Geri Çağırma=TP/(TP+FN)
Hassasiyet ve Geri Çağırma
Hassas Olumlu tahminin doğruluğuna bakar. Geri çağırmak sınıflandırıcı tarafından doğru şekilde tespit edilen pozitif örneklerin oranıdır;
Bu iki ölçümü hesaplamak için iki fonksiyon oluşturabilirsiniz
- Hassasiyet oluşturun
precision <- function(matrix) { # True positive tp <- matrix[2, 2] # false positive fp <- matrix[1, 2] return (tp / (tp + fp)) }
Code açıklama
- mat[1,1]: Veri çerçevesinin ilk sütununun ilk hücresini, yani gerçek pozitifi döndürür
- mat[1,2]; Veri çerçevesinin ikinci sütununun ilk hücresini, yani yanlış pozitifi döndür
recall <- function(matrix) { # true positive tp <- matrix[2, 2]# false positive fn <- matrix[2, 1] return (tp / (tp + fn)) }
Code açıklama
- mat[1,1]: Veri çerçevesinin ilk sütununun ilk hücresini, yani gerçek pozitifi döndürür
- mat[2,1]; Veri çerçevesinin ilk sütununun ikinci hücresini, yani yanlış negatifi döndür
Fonksiyonlarınızı test edebilirsiniz
prec <- precision(table_mat) prec rec <- recall(table_mat) rec
Çıktı:
## [1] 0.712877 ## [2] 0.5336518
Bu iki rakamı dikkatlice okuyun. Hassasiyet (Precision) 0.71'dir, yani model bir kişinin 50 doların üzerinde kazandığını söylediğinde, vakaların %71'inde doğrudur. Geri çağırma (Recall) 0.53'tür, yani model gerçekten 50 doların üzerinde kazanan kişilerin yalnızca %53'ünü tespit eder.
Sen yaratabilirsin
kesinlik ve hatırlamaya dayalı puan.
bu iki ölçümün harmonik ortalamasıdır, yani daha düşük değerlere daha fazla ağırlık verir.
f1 <- 2 * ((prec * rec) / (prec + rec)) f1
Çıktı:
## [1] 0.6103799
Hassasiyet ve Geri Çağırma ödünleşimi
Hem yüksek hassasiyete hem de yüksek geri çağırmaya sahip olmak imkansızdır.
Kesinliği arttırırsak, doğru birey daha iyi tahmin edilecek, ancak çoğunu kaçıracağız (düşük hatırlama). Bazı durumlarda geri çağırmadan daha yüksek kesinliği tercih ederiz. Kesinlik ve hatırlama arasında içbükey bir ilişki vardır.
- Düşünün, bir hastanın hastalığı olup olmadığını tahmin etmeniz gerekiyor. Mümkün olduğu kadar kesin olmak istiyorsunuz.
- Yüz tanıma yoluyla sokaktaki potansiyel dolandırıcı kişileri tespit etmeniz gerekiyorsa, hassasiyet düşük olsa da dolandırıcı olarak etiketlenen birçok kişiyi yakalamak daha iyi olacaktır. Polis dolandırıcı olmayan kişiyi serbest bırakabilecek.
ROC eğrisi
MKS Alıcı Operakarakteristik Eğri, ikili sınıflandırmada kullanılan başka bir yaygın araçtır. Kesinlik/geri çağırma eğrisine çok benzemektedir ancak ROC eğrisi, kesinlik ve geri çağırmanın grafiğini çizmek yerine, yanlış pozitif oranına karşı gerçek pozitif oranı (yani geri çağırma) gösterir. Yanlış pozitif oranı, yanlışlıkla pozitif olarak sınıflandırılan negatif örneklerin oranıdır. Bir eksi gerçek negatif orana eşittir. Gerçek negatif oran da denir özgüllük. Dolayısıyla ROC eğrisi grafikleri duyarlılık (hatırlama) ve 1 özgüllüğe karşı
ROC eğrisini çizmek için ROCR adlı bir paket kurmamız gerekiyor. Bu paketi conda'da bulabiliriz. kütüphane. Kodu yazabilirsiniz:
conda install -c r r-rocr --yes
ROC'yi tahmin() ve performans() fonksiyonlarıyla çizebiliriz.
library(ROCR) ROCRpred <- prediction(predict, data_test$income) ROCRperf <- performance(ROCRpred, 'tpr', 'fpr') plot(ROCRperf, colorize = TRUE, text.adj = c(-0.2, 1.7))
Code açıklama
- tahmin(tahmin, data_test$income): ROCR kitaplığının giriş verilerini dönüştürmek için bir tahmin nesnesi oluşturması gerekir
- performans(ROCRpred, 'tpr','fpr'): Grafikte üretilecek iki kombinasyonu döndürün. Burada tpr ve fpr oluşturulur. Hassasiyeti çizmek ve geri çağırmayı bir arada yapmak için "prec", "rec" kullanın.
Çıktı:
Adım 8) Modeli geliştirin
Arasındaki etkileşimle modele doğrusal olmama özelliği eklemeyi deneyebilirsiniz.
- yaş ve haftalık saat
- cinsiyet ve haftalık saat.
Ardından her iki modelin F1 puanını karşılaştırırsınız.
formula_2 <- income~age: hours.per.week + gender: hours.per.week + . logit_2 <- glm(formula_2, data = data_train, family = 'binomial') predict_2 <- predict(logit_2, data_test, type = 'response') table_mat_2 <- table(data_test$income, predict_2 > 0.5) precision_2 <- precision(table_mat_2) recall_2 <- recall(table_mat_2) f1_2 <- 2 * ((precision_2 * recall_2) / (precision_2 + recall_2)) f1_2
Çıktı:
## [1] 0.6109181
F1 puanı bir önceki puandan biraz daha yüksek. Veriler üzerinde çalışmaya devam edip bu puanı geçmeyi deneyebilirsiniz.
R'de GLM Katsayıları ve Oran Oranları Nasıl Yorumlanır?
6. adımda yazdırılan özet tablo, katsayıları rapor eder. log-oran Ölçeklendirme, teknik olmayan bir kitleye açıklanması zor bir kavramdır. Bunları olasılık oranlarına dönüştürmek, modeli iletmeyi çok daha kolay hale getirir.
Şu dört adımı izleyin.
- Katsayıları üslü hale getirin. Her tahmine exp() fonksiyonunu uygulayın, böylece log-olasılıklar çarpımsal olasılık oranlarına dönüşür.
- Güven aralığı ekleyin. Aynı olasılık ölçeğinde %95 aralığını elde etmek için `confint()` fonksiyonunu `exp()` fonksiyonu içine alın.
- Her bir değeri 1 ile karşılaştırın. 1'in üzerindeki olasılık oranı pozitif sınıfın olasılığını artırır, 1'in altındaki bir değer azaltır ve 1'e yakın bir değer ise tahmin edicinin çok az katkı sağladığı anlamına gelir.
- İstatistiksel anlamlılığı kontrol edin. Yalnızca özet çıktıdaki p-değeri seçtiğiniz eşik değerin (genellikle 0.05) altında olan tahmincileri yorumlayın.
# Convert log-odds coefficients into odds ratios odds_ratio <- exp(coef(logit)) round(odds_ratio, 3) # Odds ratios with 95% confidence intervals exp(cbind(OddsRatio = coef(logit), confint(logit)))
Çıktıyı okuma. Modelimizdeki haftalık çalışma saatlerinin katsayısı 0.41942'dir. Bunu üssel hale getirdiğimizde exp(0.41942) = 1.52 elde ederiz; bu da haftalık çalışma saatlerindeki bir standart sapma artışının, diğer tüm değişkenler sabit tutulduğunda, 50'in üzerinde kazanma olasılığını yaklaşık 1.5 katına çıkardığı anlamına gelir.
Negatif katsayılar da aynı şekilde çalışır. marital.statusNot_married değeri -2.50346 olduğundan exp(-2.50346) = 0.08'dir: bekar bireylerin evli bir bireyin olasılığının yaklaşık %8'ine sahip olduğu söylenebilir. Sürekli tahminciler 1. adımda standartlaştırıldığı için, değişiklikleri ham saatler yerine standart sapma birimleri cinsinden tanımlayın.
Diğer aileler için not: Üstel katsayılar, yalnızca logit bağlantılı binom ailesi altında olasılık oranlarıdır. Family = “poisson” ve log bağlantısı kullanıldığında, aynı exp() değerleri oran oranları olarak okunur.
R'de GLM: Hızlı Fonksiyon Referansı
Kod yazarken bu tabloyu yanınızda bulundurun. Yukarıdaki sekiz adımda kullanılan her fonksiyonu, onu sağlayan paket ve beklediği argümanlarla birlikte listeler.
| paket | Hedef | İşlev | Tartışma |
|---|---|---|---|
| - | Eğitim/test veri kümesi oluşturun | create_train_set() | veri, boyut, tren |
| gösteriş | Genelleştirilmiş Doğrusal Model Eğitin | glm() | formül, veriler, aile* |
| gösteriş | Modeli özetleyin | özet() | takılı model |
| baz | Tahmin etmek | ) (Tahmin | uygun model, veri kümesi, tür = 'yanıt' |
| baz | Bir karışıklık matrisi oluşturun | masa() | tahmin et() |
| baz | Doğruluk puanı oluştur | toplam(diag(tablo())/toplam(tablo()) | |
| ROCR | ROC Oluşturun: 1. Adım Tahmin oluşturun | tahmin() | tahmin(), y |
| ROCR | ROC Oluşturun: Adım 2 Performans oluşturun | verim() | tahmin(), 'tpr', 'fpr' |
| ROCR | ROC Oluşturun: Adım 3 Grafiği çizin | komplo() | verim() |
Öteki GLM Aile içi tartışma yoluyla ulaşılabilen aileler şunlardır:
- ikili: (bağlantı = “logit”)
- Gauss: (bağlantı = “kimlik”)
- Gamma: (bağlantı = “ters”)
- ters.gauss: (bağlantı = “1/mu^2”)
- Poisson: (bağlantı = “log”)
- quasi: (bağlantı = “kimlik”, varyans = “sabit”)
- yarı-binomiyal: (bağlantı = “logit”)
- quasipoisson: (link = “log”)





















