GLM di R: Model Linier Umum & Regresi Logistik

⚡ Ringkasan Cerdas

Generalized Linear Model (GLM) di R memperluas regresi biasa ke hasil yang bersifat biner, berbasis hitungan, atau non-normal. Panduan ini membangun GLM logistik pada dataset pendapatan orang dewasa dan mengevaluasinya dengan akurasi, presisi, recall, dan ROC.

  • 📐 Definisi Inti: GLM menghubungkan prediktor linier dengan respons melalui fungsi penghubung dan distribusi keluarga eksponensial yang dipilih oleh argumen keluarga.
  • 🧮 Sintaks Model: Panggil glm(formula, data, family = 'binomial') agar tautan logit mengubah prediktor linier menjadi probabilitas antara 0 dan 1.
  • 🧹 Persiapan data: Standardisasikan kolom kontinu, pangkas persentil teratas jam kerja, dan susun ulang pendidikan dan status perkawinan menjadi lebih sedikit level.
  • 📊 Metrik Kinerja: Baca matriks kebingungan terlebih dahulu, kemudian presisi, recall, dan skor F1, karena akurasi mentah menyembunyikan kelas dominan.
  • 🔁 Pembacaan Koefisien: Pangkatkan setiap koefisien dengan exp() untuk mengubah log-odds menjadi rasio odds yang mudah dipahami oleh pembaca non-teknis.
  • 🔧 Peningkatan Model: Tambahkan istilah interaksi seperti usia:jam per minggu dan bandingkan skor F1 untuk mengkonfirmasi bahwa kompleksitas tambahan tersebut membuahkan hasil.

GLM di R: Model Linier Umum

Apa itu Model Linier Umum (Generalized Linear Model/GLM) di R?

A Model Linier Umum (GLM) memperluas regresi linier biasa sehingga variabel respons dapat mengikuti distribusi selain distribusi normal. Dalam RAnda memasangnya dengan yang terintegrasi. glm() fungsi dari paket statistik.

Setiap GLM didefinisikan oleh tiga komponen:

  • Komponen acak: Distribusi probabilitas variabel respons, diambil dari keluarga eksponensial (binomial, Poisson, Gamma, Gaussian, dan lainnya).
  • Komponen sistematis: Prediktor linier, yaitu kombinasi tertimbang dari variabel penjelas Anda.
  • Fungsi tautan: Fungsi yang menghubungkan nilai rata-rata respons dengan prediktor linier, misalnya tautan logit untuk data biner atau tautan log untuk data hitungan.

Struktur itulah yang membuat model tersebut "tergeneralisasi". Alih-alih memaksakan hasil yang terdistribusi normal, Anda menyatakan distribusi yang benar melalui keluarga Argumen dan R memperkirakan koefisien dengan metode kemungkinan maksimum. Regresi logistik hanyalah GLM dengan keluarga binomial dan tautan logit, jadi ini adalah titik awal yang alami.

Apa itu Regresi Logistik di R?

Regresi logistik digunakan untuk memprediksi suatu kelas, yaitu probabilitas. Regresi logistik dapat memprediksi hasil biner secara akurat.

Bayangkan Anda ingin memprediksi apakah suatu pinjaman ditolak/diterima berdasarkan banyak atribut. Regresi logistik berbentuk 0/1. y = 0 jika pinjaman ditolak, y = 1 jika diterima.

Model regresi logistik berbeda dari model regresi linier dalam dua hal.

  • Pertama-tama, regresi logistik hanya menerima masukan dikotomis (biner) sebagai variabel terikat (yaitu vektor 0 dan 1).
  • Kedua, hasilnya dipetakan melalui fungsi penghubung probabilistik yang disebut sigmoid.dll (fungsi logistik) karena bentuknya yang menyerupai huruf S:

Regresi logistik

Output dari fungsi selalu antara 0 dan 1. Periksa Gambar di bawah

Regresi logistik

Fungsi sigmoid mengembalikan nilai dari 0 hingga 1. Untuk tugas klasifikasi, kita memerlukan keluaran diskrit 0 atau 1.

Untuk mengubah aliran kontinu menjadi nilai diskrit, kita dapat menetapkan batas keputusan pada 0.5. Semua nilai di atas ambang batas ini diklasifikasikan sebagai 1

Regresi logistik

Setelah fungsi penghubung dipahami, bandingkan model umum dengan model linier biasa yang sudah Anda ketahui.

GLM vs Regresi Linier: Perbedaan Utama dalam R

Sebelum Anda menulis kode apa pun, ada baiknya mengetahui dengan tepat kapan standar tersebut berlaku. regresi linier Fungsi lm() sudah tidak sesuai lagi dan glm() harus menggantikannya.

Kriteria Regresi Linier (lm) Model Linier Umum (glm)
Variabel respons Kontinu dan tak terbatas Biner, hitungan, proporsi, atau kontinu positif
Distribusi kesalahan Hanya normal Anggota keluarga eksponensial apa pun
Fungsi tautan Identitas (implisit) Eksplisit: logit, log, invers, probit
Metode estimasi Kuadrat terkecil biasa Kemungkinan maksimum (IRLS)
Asumsi varians Konstan di seluruh pengamatan Diizinkan bergantung pada nilai rata-rata.
Ukuran kesesuaian R-squared AIC dan deviasi residual
fungsi R lm(rumus, data) glm(rumus, data, keluarga)

Singkatnya, pilih lm() ketika hasilnya adalah pengukuran yang terdistribusi normal dan glm() setiap kali hasilnya adalah keputusan ya/tidak, tugas yang biasanya dapat Anda serahkan kepada seorang pohon keputusan pengklasifikasi, penghitung kejadian, atau kuantitas yang bernilai positif yang sebarannya meningkat seiring dengan nilai rata-ratanya.

Cara Membuat Model Linear Umum (GLM) di R

Setelah teori dipahami, sisa tutorial ini menerapkan GLM binomial secara menyeluruh pada dataset nyata.

Mari gunakan dewasa Kumpulan data ini digunakan untuk mengilustrasikan regresi logistik. Dataset "dewasa" sangat cocok untuk tugas klasifikasi. Tujuannya adalah untuk memprediksi apakah pendapatan tahunan seseorang dalam dolar AS akan melebihi 50,000. Dataset ini berisi 48,842 observasi dan sepuluh variabel:

  • usia: usia individu. numerik
  • pendidikan: Tingkat pendidikan individu. Faktor.
  • status perkawinan: Maristatus tinggi individu. Faktor yaitu Belum Menikah, Menikah dengan WNI, …
  • gender : Jenis kelamin individu. Faktor yaitu Laki-laki atau Perempuan
  • penghasilan: Target variabel. Penghasilan di atas atau di bawah 50K. Faktor yaitu >50K, <=50K

di antara yang lain

library(dplyr)
data_adult <-read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult.csv")
glimpse(data_adult)

Keluaran:

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...

Kami akan melanjutkan sebagai berikut:

  • Langkah 1: Periksa variabel kontinu
  • Langkah 2: Periksa variabel faktor
  • Langkah 3: Rekayasa fitur
  • Langkah 4: Ringkasan statistik
  • Langkah 5: Latihan/set pengujian
  • Langkah 6: Bangun modelnya
  • Langkah 7: Menilai kinerja model
  • Langkah 8: Tingkatkan modelnya

Tugas Anda adalah memprediksi individu mana yang akan memiliki pendapatan lebih dari 50K.

Dalam tutorial ini, setiap langkah akan dirinci untuk melakukan analisis pada dataset nyata.

Langkah 1) Periksa variabel kontinu

Pada langkah pertama, Anda dapat melihat distribusi variabel kontinu.

continuous <-select_if(data_adult, is.numeric)
summary(continuous)

Code Penjelasan

  • continuous <- select_if(data_adult, is.numeric): Gunakan fungsi select_if() dari pustaka dplyr untuk memilih kolom numerik saja
  • ringkasan (berkelanjutan): Cetak statistik ringkasan

Keluaran:

##        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	

Dari tabel di atas, Anda dapat melihat bahwa data memiliki skala yang benar-benar berbeda dan jam per minggu memiliki outlier yang besar (yaitu lihat kuartil terakhir dan nilai maksimum).

Anda dapat mengatasinya dengan mengikuti dua langkah berikut:

  • Gambarkan distribusi jam per minggu.
  • Standarisasi variabel kontinu
  1. Plot distribusinya

Mari kita lihat lebih dekat distribusi jam per minggu

# Histogram with kernel density curve
library(ggplot2)
ggplot(continuous, aes(x = hours.per.week)) +
    geom_density(alpha = .2, fill = "#FF6666")

Keluaran:

Periksa Variabel Kontinu

Variabel tersebut memiliki banyak outlier dan distribusinya tidak terdefinisi dengan baik. Anda dapat mengatasi sebagian masalah ini dengan menghapus 0.01 persen jam teratas per minggu.

Sintaks dasar kuantil:

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.

Kami menghitung persentil ke-99 dari jam kerja mingguan.

top_one_percent <- quantile(data_adult$hours.per.week, .99)
top_one_percent

Code Penjelasan

  • quantile(data_adult$hours.per.week, .99): Menghitung persentil ke-99 dari waktu kerja mingguan

Keluaran:

## 99% 
##  80

99 persen penduduk bekerja kurang dari 80 jam per minggu.

Anda dapat menurunkan observasi di atas ambang batas ini. Anda menggunakan filter dari dplyr Perpustakaan.

data_adult_drop <-data_adult %>%
filter(hours.per.week<top_one_percent)
dim(data_adult_drop)

Keluaran:

## [1] 45537    10
  1. Standarisasi variabel kontinu

Anda dapat menstandardisasi setiap kolom untuk meningkatkan performa karena data Anda tidak memiliki skala yang sama. Anda dapat menggunakan fungsi mutate_if dari perpustakaan dplyr. Sintaks dasarnya adalah:

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

Anda dapat membakukan kolom numerik sebagai berikut:

data_adult_rescale <- data_adult_drop %>%
	mutate_if(is.numeric, funs(as.numeric(scale(.))))
head(data_adult_rescale)

Code Penjelasan

  • mutate_if(is.numeric, funs(scale)): Syaratnya hanya kolom numerik dan fungsinya skala

Keluaran:

##           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

Langkah 2) Periksa variabel faktor

Langkah ini memiliki dua tujuan:

  • Periksa level di setiap kolom kategori
  • Tentukan level baru

Kami akan membagi langkah ini menjadi tiga bagian:

  • Pilih kolom kategorikal
  • Simpan diagram batang setiap kolom dalam daftar
  • Cetak grafiknya

Kita dapat memilih kolom faktor dengan kode di bawah ini:

# Select categorical column
factor <- data.frame(select_if(data_adult_rescale, is.factor))
	ncol(factor)

Code Penjelasan

  • data.frame(select_if(data_adult, is.factor)): Kami menyimpan kolom faktor dalam faktor dalam tipe bingkai data. Perpustakaan ggplot2 memerlukan objek bingkai data.

Keluaran:

## [1] 6

Dataset berisi 6 variabel kategori

Langkah kedua lebih menantang. Anda ingin membuat grafik batang untuk setiap kolom dalam data frame faktor. Akan lebih mudah untuk mengotomatiskan proses ini, terutama dalam situasi di mana terdapat banyak kolom.

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 Penjelasan

  • lapply(): Gunakan fungsi lapply() untuk meneruskan fungsi di semua kolom kumpulan data. Anda menyimpan hasilnya dalam daftar
  • function(x): Fungsi akan diproses untuk setiap x. Di sini x adalah kolomnya
  • ggplot(factor, aes(get(x))) + geom_bar()+ theme(axis.text.x = element_text(angle = 90)): Buat diagram batang char untuk setiap elemen x. Catatan, untuk mengembalikan x sebagai kolom, Anda perlu memasukkannya ke dalam get()

Langkah terakhir relatif mudah. Anda ingin mencetak 6 grafik.

# Print the graph
graph

Keluaran:

## [[1]]

Periksa Variabel Faktor

## ## [[2]]

Periksa Variabel Faktor

## ## [[3]]

Periksa Variabel Faktor

## ## [[4]]

Periksa Variabel Faktor

## ## [[5]]

Periksa Variabel Faktor

## ## [[6]]

Periksa Variabel Faktor

Catatan: Gunakan tombol berikutnya untuk menavigasi ke grafik berikutnya

Periksa Variabel Faktor

Langkah 3) Rekayasa fitur

Dua variabel kategorikal memiliki lebih banyak level daripada yang dibutuhkan model. Anda akan mengelompokkannya kembali ke dalam kategori yang lebih luas dan lebih lengkap.

Merombak pendidikan

Dari grafik di atas terlihat bahwa variabel pendidikan mempunyai 16 jenjang. Hal ini penting, dan beberapa tingkat memiliki jumlah observasi yang relatif rendah. Jika Anda ingin meningkatkan jumlah informasi yang dapat Anda peroleh dari variabel ini, Anda dapat menyusunnya kembali ke tingkat yang lebih tinggi. Yaitu, Anda membuat grup yang lebih besar dengan tingkat pendidikan yang sama. Misalnya, tingkat pendidikan yang rendah akan dikonversi menjadi putus sekolah. Jenjang pendidikan yang lebih tinggi akan diubah menjadi magister.

Berikut detailnya:

Tingkat lama Level baru
Prasekolah keluar
10th Keluar
11th Keluar
12th Keluar
1st-4 Keluar
5th-6th Keluar
7th-8th Keluar
9th Keluar
Lulusan HS Lulusan Tinggi
Beberapa perguruan tinggi Komunitas
Assoc-acdm Komunitas
Assoc-voc Komunitas
Sarjana Sarjana
Masters Masters
Sekolah Prof Masters
Gelar doktor PhD
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 Penjelasan

  • Kami menggunakan kata kerja bermutasi dari perpustakaan dplyr. Nilai-nilai pendidikan kita ubah dengan pernyataan ifelse

Pada tabel di bawah, Anda membuat ringkasan statistik untuk melihat, rata-rata, berapa tahun pendidikan (nilai z) yang diperlukan untuk mencapai gelar Sarjana, Magister, atau PhD.

recast_data %>%
	group_by(education) %>%
	summarize(average_educ_year = mean(educational.num),
		count = n()) %>%
	arrange(average_educ_year)

Keluaran:

## # 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

Perombakan Maristatus tal

Anda juga dapat membuat level yang lebih rendah untuk status perkawinan. Dalam kode berikut, Anda mengubah level sebagai berikut:

Tingkat lama Level baru
Tidak pernah menikah Belum nikah
Menikah-pasangan-absen Belum nikah
Menikah dengan pasangan AF Menikah
Menikah-Civ-pasangan
Terpisah Terpisah
Bercerai
Janda Janda
# 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")))))

Anda dapat memeriksa jumlah individu dalam setiap grup.

table(recast_data$marital.status)

Keluaran:

## ##     Married Not_married   Separated       Widow
##       21165       15359        7727        1286

Langkah 4) Ringkasan Statistik

Sekarang saatnya untuk memeriksa beberapa statistik tentang variabel target kita. Pada grafik di bawah, Anda menghitung persentase individu yang berpenghasilan lebih dari 50 ribu berdasarkan jenis kelamin mereka.

# Plot gender income
ggplot(recast_data, aes(x = gender, fill = income)) +
    geom_bar(position = "fill") +
    theme_classic()

Keluaran:

Statistik Ringkasan

Selanjutnya, periksa apakah asal usul individu memengaruhi penghasilannya.

# 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))

Keluaran:

Statistik Ringkasan

Jumlah jam kerja berdasarkan jenis kelamin.

# 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()

Keluaran:

Statistik Ringkasan

Diagram kotak menegaskan bahwa distribusi waktu kerja sesuai dengan kelompok yang berbeda. Dalam diagram kotak, kedua jenis kelamin tidak memiliki pengamatan yang homogen.

Anda dapat memeriksa kepadatan waktu kerja mingguan berdasarkan jenis pendidikan. Distribusi tersebut memiliki banyak puncak yang berbeda. Hal ini mungkin dapat dijelaskan oleh jenis pendidikan.tracdi AS.

# 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 Penjelasan

  • ggplot(recast_data, aes( x= jam.per.minggu)): Plot kepadatan hanya memerlukan satu variabel
  • geom_density(aes(color = education), alpha =0.5): Objek geometris untuk mengontrol kepadatan

Keluaran:

Statistik Ringkasan

Untuk mengkonfirmasi pemikiran Anda, Anda dapat melakukan satu arah Uji ANOVA:

anova <- aov(hours.per.week~education, recast_data)
summary(anova)

Keluaran:

##                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

Uji ANOVA mengonfirmasi perbedaan rata-rata antar kelompok.

Non-linearitas

Sebelum menjalankan model, Anda dapat melihat apakah jumlah jam kerja berhubungan dengan usia.

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 Penjelasan

  • ggplot(recast_data, aes(x = age, y = hours.per.week)): Mengatur estetika grafik
  • geom_point(aes(color= pendapatan), size =0.5): Buatlah plot titik
  • stat_smooth(): Tambahkan garis tren dengan argumen berikut:
    • metode='lm': Plot nilai yang dipasang jika regresi linier
    • rumus = y~poli(x,2): Cocok dengan regresi polinomial
    • se = TRUE: Tambahkan kesalahan standar
    • aes(color= income): Pecahkan model berdasarkan pendapatan

Keluaran:

Non-linearitas

Singkatnya, Anda dapat menguji istilah interaksi dalam model untuk mengetahui efek non-linearitas antara waktu kerja mingguan dan fitur lainnya. Penting untuk mendeteksi dalam kondisi apa waktu kerja berbeda.

Korelasi

Pemeriksaan selanjutnya adalah memvisualisasikan korelasi antar variabel. Anda mengonversi tipe tingkat faktor menjadi numerik sehingga Anda dapat memplot peta panas yang berisi koefisien korelasi yang dihitung dengan metode Spearman.

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 Penjelasan

  • data.frame(lapply(recast_data,as.integer)): Mengonversi data menjadi numerik
  • ggcorr() memplot peta panas dengan argumen berikut:
    • metode: Metode untuk menghitung korelasi
    • nbreaks = 6: Jumlah istirahat
    • hjust = 0.8: Mengontrol posisi nama variabel di plot
    • label = TRUE: Tambahkan label di tengah jendela
    • label_size = 3: Label ukuran
    • color = “grey50”): Warna label

Keluaran:

Korelasi

Langkah 5) Set pelatihan/pengujian

Setiap diawasi Mesin belajar Tugas ini mengharuskan Anda untuk membagi data antara set pelatihan dan set pengujian. Anda dapat menggunakan "fungsi" yang telah Anda buat di tutorial pembelajaran terawasi lainnya untuk membuat set pelatihan/pengujian.

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)

Keluaran:

## [1] 36429     9
dim(data_test)

Keluaran:

## [1] 9108    9

Langkah 6) Bangun modelnya

Untuk melihat bagaimana kinerja algoritma, Anda menggunakan fungsi glm() dari paket stats. Model Linier Umum adalah kumpulan model. Sintaks dasarnya adalah:

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")	

Anda siap memperkirakan model logistik untuk membagi tingkat pendapatan antar serangkaian fitur.

formula <- income~.
logit <- glm(formula, data = data_train, family = 'binomial')
summary(logit)

Code Penjelasan

  • rumus <- pendapatan ~ .: Buat model yang sesuai
  • logit <- glm(rumus, data = data_train, family = 'binomial'): Cocokkan model logistik (family = 'binomial') dengan data data_train.
  • ringkasan(logit): Cetak ringkasan model

Keluaran:

## 
## 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

Ringkasan model kami mengungkapkan informasi menarik. Kinerja regresi logistik dievaluasi dengan metrik utama tertentu.

  • AIC (Kriteria Informasi Akaike): Ini setara dengan R2 dalam regresi logistik. Ini mengukur kecocokan ketika penalti diterapkan pada sejumlah parameter. Lebih kecil AIC nilai menunjukkan model tersebut mendekati kebenaran.
  • Penyimpangan nol: Cocok dengan model hanya dengan intersep. Derajat kebebasannya adalah n-1. Kita dapat mengartikannya sebagai nilai Chi-square (nilai fit yang berbeda dengan nilai sebenarnya pengujian hipotesis).
  • Residual Deviance: Model dengan semua variabel. Hal ini juga diartikan sebagai pengujian hipotesis Chi-square.
  • Jumlah iterasi Fisher Scoring: Jumlah iterasi sebelum konvergen.

Output dari fungsi glm() disimpan dalam daftar. Kode di bawah ini menunjukkan semua item yang tersedia dalam variabel logit yang kami buat untuk mengevaluasi regresi logistik.

# Daftarnya sangat panjang, cetak hanya tiga elemen pertama

lapply(logit, class)[1:3]

Keluaran:

## $coefficients
## [1] "numeric"
## 
## $residuals
## [1] "numeric"
## 
## $fitted.values
## [1] "numeric"

Setiap nilai dapat berupatracdiawali dengan tanda $ diikuti nama metrik. Misalnya, Anda menyimpan model sebagai logit. Untuk contohtracBerdasarkan kriteria AIC, Anda menggunakan:

logit$aic

Keluaran:

## [1] 27086.65

Langkah 7) Menilai kinerja model

Matriks Kebingungan

The matriks kebingungan adalah pilihan yang lebih baik untuk mengevaluasi kinerja klasifikasi dibandingkan dengan berbagai metrik yang Anda lihat sebelumnya. Ide umumnya adalah menghitung berapa kali instance True diklasifikasikan menjadi False.

Matriks Kebingungan

Untuk menghitung matriks konfusi, pertama-tama Anda harus memiliki serangkaian prediksi agar dapat dibandingkan dengan target sebenarnya.

predict <- predict(logit, data_test, type = 'response')
# confusion matrix
table_mat <- table(data_test$income, predict > 0.5)
table_mat

Code Penjelasan

  • prediksi(logit,data_test, type = 'response'): Hitung prediksi pada set pengujian. Tetapkan type = 'response' untuk menghitung probabilitas respons.
  • table(data_test$income, prediksi > 0.5): Hitung matriks kebingungan. prediksi > 0.5 berarti ia mengembalikan 1 jika probabilitas prediksi di atas 0.5, jika tidak 0.

Keluaran:

##        
##         FALSE TRUE
##   <=50K  6310  495
##   >50K   1074 1229	

Setiap baris dalam matriks kebingungan mewakili target sebenarnya, sedangkan setiap kolom mewakili target yang diprediksi. Baris pertama matriks ini mempertimbangkan pendapatan di bawah 50 ribu (kelas negatif): 6,310 observasi diklasifikasikan dengan benar sebagai individu dengan pendapatan di bawah 50 ribu (Benar-benar negatif), sementara 495 salah diklasifikasikan sebagai di atas 50 ribu (Salah positif). Baris kedua mempertimbangkan pendapatan di atas 50 ribu: 1,229 diidentifikasi dengan benar (Benar-benar positif), sedangkan 1,074 tidak terdeteksi (Salah negatif).

Anda dapat menghitung modelnya ketepatan dengan menjumlahkan positif benar + negatif benar atas total observasi

Matriks Kebingungan

accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
accuracy_Test

Code Penjelasan

  • sum(diag(table_mat)): Jumlah diagonalnya
  • sum(table_mat): Jumlah matriks.

Keluaran:

## [1] 0.8277339

Model ini tampaknya memiliki satu masalah: menghasilkan terlalu banyak false negative. Ini disebut paradoks tes akurasiKami menyatakan bahwa akurasi adalah rasio prediksi yang benar terhadap jumlah total kasus. Kita dapat memiliki akurasi yang relatif tinggi tetapi model yang tidak berguna. Hal ini terjadi ketika ada kelas dominan. Jika Anda melihat kembali matriks kebingungan, Anda dapat melihat sebagian besar kasus diklasifikasikan sebagai negatif sejati. Bayangkan sekarang, model mengklasifikasikan setiap observasi sebagai negatif (yaitu kurang dari 50 ribu). Anda masih akan memperoleh akurasi sekitar 75 persen (6,805 / 9,108). Model Anda berkinerja lebih baik tetapi kesulitan membedakan positif sejati dengan negatif sejati.

Dalam situasi seperti ini, sebaiknya memiliki metrik yang lebih ringkas. Kita bisa melihat:

  • Presisi=TP/(TP+FP)
  • Penarikan=TP/(TP+FN)

Presisi vs Ingatan

Ketelitian melihat keakuratan prediksi positif. Mengingat kembali adalah rasio kejadian positif yang terdeteksi dengan benar oleh pengklasifikasi;

Anda dapat membuat dua fungsi untuk menghitung dua metrik ini

  1. Membangun presisi
precision <- function(matrix) {
	# True positive
    tp <- matrix[2, 2]
	# false positive
    fp <- matrix[1, 2]
    return (tp / (tp + fp))
}

Code Penjelasan

  • mat[1,1]: Mengembalikan sel pertama dari kolom pertama bingkai data, yaitu positif sebenarnya
  • tikar[1,2]; Mengembalikan sel pertama dari kolom kedua bingkai data, yaitu positif palsu
recall <- function(matrix) {
# true positive
    tp <- matrix[2, 2]# false positive
    fn <- matrix[2, 1]
    return (tp / (tp + fn))
}

Code Penjelasan

  • mat[1,1]: Mengembalikan sel pertama dari kolom pertama bingkai data, yaitu positif sebenarnya
  • tikar[2,1]; Mengembalikan sel kedua dari kolom pertama bingkai data, yaitu negatif palsu

Anda dapat menguji fungsi Anda

prec <- precision(table_mat)
prec
rec <- recall(table_mat)
rec

Keluaran:

## [1] 0.712877
## [2] 0.5336518

Bacalah kedua angka ini dengan saksama. Presisi adalah 0.71, jadi ketika model mengatakan seseorang berpenghasilan di atas 50 ribu, model tersebut benar dalam 71 persen kasus. Recall adalah 0.53, jadi model hanya mendeteksi 53 persen dari individu yang benar-benar berpenghasilan di atas 50 ribu.

Anda dapat membuat file Presisi vs Ingatan skor berdasarkan presisi dan recall. Itu Presisi vs Ingatan adalah rata-rata harmonis dari kedua metrik ini, yang berarti memberikan bobot lebih pada nilai yang lebih rendah.

Presisi vs Ingatan

f1 <- 2 * ((prec * rec) / (prec + rec))
f1

Keluaran:

## [1] 0.6103799

Pengorbanan Presisi vs Perolehan

Tidak mungkin memiliki presisi tinggi dan recall yang tinggi.

Jika kita meningkatkan presisi, individu yang tepat akan dapat diprediksi dengan lebih baik, namun kita akan kehilangan banyak individu (recall lebih rendah). Dalam beberapa situasi, kami lebih memilih presisi yang lebih tinggi daripada perolehan kembali. Ada hubungan cekung antara presisi dan perolehan.

  • Bayangkan, Anda perlu memprediksi apakah seorang pasien mengidap suatu penyakit. Anda ingin setepat mungkin.
  • Jika Anda perlu mendeteksi calon penipu di jalan melalui pengenalan wajah, akan lebih baik jika menangkap banyak orang yang dicap penipu meski presisinya rendah. Polisi akan dapat membebaskan individu yang tidak melakukan penipuan.

Kurva ROC

The Penerima OperaKarakteristik kurva adalah alat umum lainnya yang digunakan dengan klasifikasi biner. Hal ini sangat mirip dengan kurva presisi/recall, namun alih-alih memplot presisi versus perolehan, kurva ROC menunjukkan tingkat positif sebenarnya (yaitu, perolehan kembali) terhadap tingkat positif palsu. Tingkat positif palsu adalah rasio kejadian negatif yang salah diklasifikasikan sebagai positif. Nilai ini sama dengan satu dikurangi tingkat negatif sebenarnya. Tingkat negatif sebenarnya juga disebut kekhususan. Oleh karena itu plot kurva ROC kepekaan (ingat) versus 1 kekhususan

Untuk membuat grafik kurva ROC, kita perlu menginstal paket bernama ROCR. Kita dapat menemukannya di conda. perpustakaan. Anda dapat mengetikkan kode:

conda install -c r r-rocr --yes

Kita dapat memplot ROC dengan fungsi prediksi() dan kinerja().

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 Penjelasan

  • prediksi(prediksi, data_test$pendapatan): Perpustakaan ROCR perlu membuat objek prediksi untuk mengubah data masukan
  • performance(ROCRpred, 'tpr','fpr'): Mengembalikan dua kombinasi yang akan dihasilkan dalam grafik. Di sini, tpr dan fpr dibangun. Untuk memplot presisi dan mengingat secara bersamaan, gunakan “prec”, “rec”.

Keluaran:

Kurva ROC

Langkah 8) Tingkatkan modelnya

Anda dapat mencoba menambahkan non-linearitas pada model dengan interaksi antar keduanya

  • usia dan jam per minggu
  • jenis kelamin dan jam per minggu.

Kemudian, Anda membandingkan skor F1 dari kedua model tersebut.

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

Keluaran:

## [1] 0.6109181

Skor F1 sedikit lebih tinggi dari sebelumnya. Anda dapat terus mengolah data dan mencoba untuk mengalahkan skor tersebut.

Cara Menginterpretasikan Koefisien GLM dan Rasio Peluang di R

Tabel ringkasan yang dicetak pada Langkah 6 melaporkan koefisien pada log-odds skala, yang sulit dijelaskan kepada audiens non-teknis. Mengubahnya menjadi rasio peluang membuat model jauh lebih mudah dikomunikasikan.

Ikuti keempat langkah ini.

  1. Pangkatkan koefisiennya. Terapkan fungsi exp() pada setiap estimasi sehingga log-odds menjadi rasio odds multiplikatif.
  2. Tambahkan interval kepercayaan. Bungkus fungsi confint() dengan fungsi exp() untuk mendapatkan interval 95 persen pada skala peluang yang sama.
  3. Bandingkan setiap nilai dengan 1. Rasio odds di atas 1 meningkatkan probabilitas kelas positif, nilai di bawah 1 menurunkannya, dan nilai mendekati 1 berarti prediktor tersebut memberikan sedikit tambahan.
  4. Periksa signifikansi statistik. Hanya interpretasikan prediktor yang nilai p-nya dalam output ringkasan berada di bawah ambang batas yang Anda pilih, biasanya 0.05.
# 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)))

Membaca hasilnya. Koefisien untuk jam per minggu dalam model kita adalah 0.41942. Dengan memangkatkannya, kita peroleh exp(0.41942) = 1.52, yang berarti bahwa peningkatan satu standar deviasi dalam jam kerja mingguan akan melipatgandakan peluang untuk mendapatkan penghasilan di atas 50 ribu sekitar 1.5 kali, dengan asumsi semua variabel lain tetap konstan.

Koefisien negatif bekerja dengan cara yang sama. marital.statusNot_married adalah -2.50346, jadi exp(-2.50346) = 0.08: individu yang belum menikah memiliki peluang sekitar 8 persen dibandingkan individu yang sudah menikah. Karena prediktor kontinu telah distandarisasi pada Langkah 1, jelaskan perubahan dalam satuan deviasi standar, bukan jam mentah.

Catatan untuk keluarga lain: Koefisien yang dipangkatkan hanya merupakan rasio peluang di bawah keluarga binomial dengan tautan logit. Dengan keluarga = “poisson” dan tautan log, nilai exp() yang sama dibaca sebagai rasio laju.

GLM di R: Referensi Fungsi Cepat

Simpan tabel ini di samping Anda saat Anda melakukan pengkodean. Tabel ini mencantumkan setiap fungsi yang digunakan dalam delapan langkah di atas, beserta paket yang menyediakannya dan argumen yang diharapkan.

Paket Tujuan fungsi Argumen
- Buat kumpulan data pelatihan/pengujian buat_train_set() data, ukuran, kereta
glm Melatih Model Linear Umum glm() rumus, data, keluarga*
glm Rangkum modelnya ringkasan() model terpasang
mendasarkan Buat prediksi meramalkan() model yang dipasang, kumpulan data, tipe = 'respons'
mendasarkan Buat matriks kebingungan meja() y, prediksi()
mendasarkan Buat skor akurasi jumlah(diag(tabel())/jumlah(tabel()
ROCR Buat ROC : Langkah 1 Buat prediksi ramalan() prediksi(), y
ROCR Buat ROC : Langkah 2 Buat kinerja pertunjukan() prediksi(), 'tpr', 'fpr'
ROCR Buat ROC : Langkah 3 Plot grafik merencanakan() pertunjukan()

Yang lain GLM Keluarga yang tersedia melalui proses pengajuan permohonan bantuan keluarga adalah:

  • binomial: (tautan = “logit”)
  • gaussian: (tautan = “identitas”)
  • Gamma: (tautan = “kebalikan”)
  • invers.gaussian: (tautan = “1/mu^2”)
  • poisson: (tautan = “log”)
  • quasi: (link = “identitas”, varians = “konstan”)
  • kuasibinomial: (tautan = “logit”)
  • quasipoisson: (tautan = “log”)

Pertanyaan Umum Demo Slot

Argumen family menyatakan distribusi probabilitas respons dan fungsi tautan default-nya. Gunakan binomial untuk hasil biner, poisson untuk jumlah, Gamma untuk nilai miring positif, dan gaussian untuk mereproduksi regresi linier biasa.

Overdispersi muncul ketika deviasi residual jauh melebihi derajat kebebasan. Ganti famili ke quasibinomial atau quasipoisson, yang mengubah skala kesalahan standar, atau sesuaikan model binomial negatif dengan glm.nb() dari MASS paket.

Ambang batas 0.5 hanyalah konvensi. Pilih ambang batas dari kurva ROC atau kurva presisi-recall yang sesuai dengan biaya kesalahan Anda. Turunkan untuk menangkap lebih banyak kasus positif, naikkan jika kesalahan positif palsu merugikan.

Pipeline AI masih mengandalkan GLM sebagai dasar yang cepat dan transparan untuk penilaian kredit, tingkat pergantian pelanggan, dan model risiko. Industri yang teregulasi lebih menyukai GLM karena setiap koefisiennya dapat diaudit, tidak seperti bobot yang buram dari jaringan saraf dalam (deep neural network).

Ya. Asisten AI dapat membuat draf panggilan glm(), menjelaskan output deviasi, dan menandai kesalahan umum seperti model yang tidak konvergen atau prediktor kolinear. Selalu validasi kode yang dihasilkan terhadap data Anda sendiri sebelum mempercayai hasilnya.

Ringkaslah postingan ini dengan: