Fisher Scoring dan IRLS untuk GLM dengan variabel respon biner

GLM
R Programming
Computational Statistics
Author

Gerry Alfa Dito

Published

September 10, 2023

Package

library(tidyverse)
library(Matrix)
library(broom)

Fisher Scoring untuk GLM

Formula Fisher Scoring yang digunakan untuk mendapatkan penduga bagi koefisien GLM adalah sebagai berikut:

β(p+1)×1(i+1)=β(p+1)×1(i)+[Ip×p(i)]1S(p+1)×1(i)

dengan

S(p+1)×1(i)=X(p+1)×ntWn×n(i)(Dn×n(i))1(yn×1μn×1(i)) dan

Ip×p(i)=X(p+1)×ntWn×n(i)Xn×(p+1)

Algoritme Fisher Scoring dapat dituliskan sebagai berikut:

  1. Tentukan perkiraan awal nilai optimal β(p+1)×1(0) dan stopping criterion
  2. Tentukan Score function S(p+1)×1(0) dan Expected Fisher Information Ip×p(0).
  3. Hitung β(p+1)×1(1)=β(p+1)×1(0)+[Ip×p(0)]1S(p+1)×1(0), sehingga diperoleh perkiraan nilai optimal β(p+1)×1(1)
  4. Lakukan Langkah 5 sampai stopping criterion terpenuhi
  5. Hitung β(p+1)×1(i+1)=β(p+1)×1(i)+[Ip×p(i)]1S(p+1)×1(i) untuk iterasi i=1,2,
  6. Saat stopping criterion terpenuhi maka β(p+1)×1(i+1) merupakan nilai penduga bagi parameter β(p+1)×1
  7. Ragam dari β(p+1)×1 diperoleh dengan $Var(_{(p+1)})=^{-1} $saat stopping criterion terpenuhi

Iteratively reweighted least squares (IRLS) untuk GLM

IRLS untuk GLM merupakan hasil reformulasi dari Fisher Scoring untuk GLM. Berikut proses penurunanya

β(p+1)×1(𝑖+1)=β((𝑝+1)×1)(i)+[Ip×p(i)]1S(𝑝+1)×1(i)Ip×p(i)β(𝑝+1)×1(𝑖+1)=Ip×p(i)β((𝑝+1)×1)(i)+S(𝑝+1)×1(i)

kemudiann dengan mensubtitusikan Ip×p(i) dan S(𝑝+1)×1(i) sesuai dengan definisi yang ada di fisher scoring, didapat

{X(𝑝+1)×ntWn×n(i)Xn×(𝑝+1)}β(p+1)×1(𝑖+1)={X(𝑝+1)×ntWn×n(i)Xn×(𝑝+1)}β((𝑝+1)×1)(i)+[X(𝑝+1)×ntWn×n(i)(Dn×n(i))1(yn×1μ𝑛×1(i))]=X(𝑝+1)×ntWn×n(i)[X(𝑝+1)×ntβ((𝑝+1)×1)(i)+(Dn×n(i))1(yn×1μ𝑛×1(i))] misal zn×1=X(𝑝+1)×ntβ((𝑝+1)×1)(i)+(Dn×n(i))1(yn×1μ𝑛×1(i))=X(p+1)×ntWn×n(i)zn×1(i)

maka diperoleh persamaan normal (normal equation) sebagai berikut:

{X(𝑝+1)×ntWn×n(i)Xn×(𝑝+1)}β(p+1)×1(𝑖+1)=X(p+1)×ntWn×n(i)zn×1(i)β(p+1)×1(𝑖+1)={X(p+1)×ntWn×n(i)Xn×(𝑝+1)}1X(p+1)×ntWn×n(i)zn×1(i)

Kemudian, solusi dari persamaan normal diatas adalah

β(p+1)×1(𝑖+1)={X(𝑝+1)×ntWn×n(i)Xn×(𝑝+1)}1X(𝑝+1)×ntWn×n(i)zn×1(i)

jadi, formulasi untuk IRLS adalah

β(p+1)×1(𝑖+1)={Xn×(𝑝+1)tWn×n(i)Xn×(𝑝+1)}1Xn×(p+1)tWn×n(i)zn×1(i)

Algoritme Fisher Scoring dapat dituliskan sebagai berikut:

  1. Tentukan perkiraan awal nilai optimal β(p+1)×1(0) dan stopping criterion
  2. Tentukan Wn×n(0) dan zn×1(0).
  3. Hitung β(p+1)×1(1)={Xn×(𝑝+1)tWn×n(0)Xn×(𝑝+1)}1Xn×(p+1)tWn×n(0)zn×1(0), sehingga diperoleh perkiraan nilai optimal β(p+1)×1(1)
  4. Lakukan Langkah 5 sampai stopping criterion terpenuhi
  5. Hitung β(p+1)×1(𝑖+1)={Xn×(𝑝+1)tWn×n(i)Xn×(𝑝+1)}1Xn×(p+1)tWn×n(i)zn×1(i) untuk iterasi i=1,2,
  6. Saat stopping criterion terpenuhi maka β(p+1)×1(i+1) merupakan nilai penduga bagi parameter β(p+1)×1
  7. Ragam dari β(p+1)×1 diperoleh dengan Var(β(p+1))={Xn×(𝑝+1)tWn×n(i)Xn×(𝑝+1)}1saat stopping criterion terpenuhi

Data

No Variabel Keterangan
1 age umur nasabah(numeric)
2 job jenis pekerjaan nasabah(categorical:"admin.","unknown","unemployed","management","housemaid","entrepreneur","student","blue-collar","self-employed","retired","technician","services")
3 marital status perkawinan nasabah (categorical: "married","divorced","single")
4 education tingkat pendidikan(categorical: "unknown","secondary","primary","tertiary")
5 default apakah nasabah memiliki kredit yang macet? (binary: "yes","no")
6 balance saldo tahunan rata-rata dalam euros (numeric)
7 housing apakah nasabah memiliki cicilan rumah? (binary: "yes","no")
8 loan apakah nasabah memiliki pinjaman pribadi? (binary: "yes","no")
9 contact perangkat telekomunikasi (categorical: "unknown","telephone","cellular")
10 duration durasi panggilan terakhir, dalam detik (numeric)
11 pdays banyaknya hari yang telah berlalu setelah klien terakhir kali dihubungi dari campaign sebelumnya (angka, -1 berarti klien tidak dihubungi sebelumnya)
12 previous banyaknya komunikasi yang dilakukan sebelum campaign ini(numeric)
13 poutcome hasil dari promosi campaign sebelumnya (categorical: "unknown","other","failure","success")
14 subscribed response variable (desired target),apakah nasabah telah berlangganan deposito berjangka? (binary: "yes","no")

Data bisa didownload di link berikut

Download Data

Import Data

bank_marketing <- read.csv("bank_marketing.csv",stringsAsFactors = TRUE)
glimpse(bank_marketing)
Rows: 45,211
Columns: 14
$ subscribed <fct> no, no, no, no, no, no, no, no, no, no, no, no, no, no, no,…
$ age        <int> 58, 44, 33, 47, 33, 35, 28, 42, 58, 43, 41, 29, 53, 58, 57,…
$ job        <fct> management, technician, entrepreneur, blue-collar, unknown,…
$ marital    <fct> married, single, married, married, single, married, single,…
$ education  <fct> tertiary, secondary, secondary, unknown, unknown, tertiary,…
$ default    <fct> no, no, no, no, no, no, no, yes, no, no, no, no, no, no, no…
$ balance    <int> 2143, 29, 2, 1506, 1, 231, 447, 2, 121, 593, 270, 390, 6, 7…
$ housing    <fct> yes, yes, yes, yes, no, yes, yes, yes, yes, yes, yes, yes, …
$ loan       <fct> no, no, yes, no, no, no, yes, no, no, no, no, no, no, no, n…
$ contact    <fct> unknown, unknown, unknown, unknown, unknown, unknown, unkno…
$ duration   <int> 261, 151, 76, 92, 198, 139, 217, 380, 50, 55, 222, 137, 517…
$ pdays      <int> -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,…
$ previous   <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ poutcome   <fct> unknown, unknown, unknown, unknown, unknown, unknown, unkno…

Fisher Scoring dan IRLS untuk Binomial GLM

Misal Binomial GLM didefinisikan sebagai

π=exp(Xβ)1+exp(Xβ) atau

logit(π)=log(π1π)=Xβ dengan

π=P(y=1)

Untuk ilustrasi penggunaan Fisher-scoring dan IRLS kita akan menggunakan variabel prediktor balance, age, housing dan marital

set.seed(2045)
bank_marketing_mini <-  bank_marketing %>% 
                            select(subscribed,balance,age,housing,marital) %>% 
                            slice_sample(n=250,by = subscribed)
glimpse(bank_marketing_mini)
Rows: 500
Columns: 5
$ subscribed <fct> no, no, no, no, no, no, no, no, no, no, no, no, no, no, no,…
$ balance    <int> 354, 5838, 39, -123, 1150, 263, -11, 1733, 14, 416, 2, 0, 4…
$ age        <int> 29, 56, 55, 35, 33, 40, 51, 33, 50, 34, 26, 27, 32, 23, 45,…
$ housing    <fct> yes, no, no, yes, yes, yes, no, yes, yes, no, yes, yes, yes…
$ marital    <fct> single, married, married, single, single, single, married, …

Kemudian kita akan ekstrak matriks modelnya Xn×(p+1)

X <- model.matrix(subscribed~balance+age+housing+marital,data = bank_marketing_mini)
#dimensi matrix X
dim(X)
[1] 500   6

dan kemudian untuk yn×1, kita misalkan kategori yes sebagai 1 dan 0 adalah untuk kategori no

y <- ifelse(bank_marketing_mini$subscribed=="yes",1,0)
# ukuran variabel respon
length(y)
[1] 500
# banyaknya nilai 1 dan 0
table(y)
y
  0   1 
250 250 

berikut overview dari matriks Xn×(p+1)

X[1:10,]
   (Intercept) balance age housingyes maritalmarried maritalsingle
1            1     354  29          1              0             1
2            1    5838  56          0              1             0
3            1      39  55          0              1             0
4            1    -123  35          1              0             1
5            1    1150  33          1              0             1
6            1     263  40          1              0             1
7            1     -11  51          0              1             0
8            1    1733  33          1              0             1
9            1      14  50          1              1             0
10           1     416  34          0              0             1

Binomial sebagai distribusi keluarga eksponensial

Selanjutnya kita akan mendefinisikan matriks-matriks lain yang dibutuhkan untuk fisher scoring dan IRLS. Pertama-tama kita ingat terlebih dahulu tentang distribusi binomail sebagai distribusi keluarga eksponensial.

Distribusi Binomial yang digunakan untuk GLM adalah YBinomial(m,π)m. Ingat bahwa, Cumulant function b(θ) untuk YBinomial(m,π)m adalah

b(θ)=log[1+exp(θ)]

dan parameter dispersi a(ϕ)

a(ϕ)=1m

Kemudian, μ dan Var(Y) dari YBinomial(m,π)m sebagai keluarga eksponensial adalah

μ=E(Y)=db(θ)dθ=exp(θ)1+exp(θ)

dan

$$

Var(Y) &= Var() a()
&= a()
&=

$$

Ingat bahwa koneksi (pemisalan) θ dengan parameter π adalah sebagai berikut

θ=log(π1π)

Jika kita subtitusi ke dalam μ dan Var(Y)

μ=exp(θ)1+exp(θ)=(π1π)1+(π1π)=π

Var(Y)=exp(θ)[1+exp(θ)]21m=(π1π)[1+(π1π)]21m=π(1π)1m=π(1π)m

jadi μ=π dan Var(Y)=π(1π)m. Kemudian, fungsi hubung (link function) yang digunakan adalah fungsi hubung kanonik (canonical link function) yaitu

η=logit(μ)=logit(π)=log(π1π)

jika kita ubah menjadi fungsi dari η

g1(η)=μ=π=exp(η)1+exp(η)

Mendefiniskan matriks untuk Fisher Scoring dan IRLS

Kemudian kita akan dapatkan matriks Wn×n yang didefinisikan

Wn×n=[(dμ1dη1)2Var(y1)000(dμ2dη2)2Var(y2)0000(dμndη2)2Var(yn)]

elemen-elemen diagonalnya sebagai berikut:

dμidηi=dπidηi=d(exp(ηi)1+exp(ηi))dηi=exp(ηi)[1+exp(ηi)]2=(πi1πi)[1+(πi1πi)]2=πi(1πi)

dan

Var(yi)=πi(1πi)mi

sehingga

(dμidηi)2Var(yi)=[πi(1πi)]2πi(1πi)mi=miπi(1πi)

Jadi matriks Wn×n adalah

Wn×n=[m1π1(1π1)000m2π2(1π2)0000mnπn(1πn)]

kita tuliskan matriks Wn×n dalam sintaks R

W <- function(m,pi){
wi <- m * pi * ( 1- pi )
Diagonal(x=as.numeric(wi))
}

misalkan m1=m2=m3=1 dan π1=0.5,π2=0.6,π3=0.7 maka Wn×n adalah

W(m=c(1,1,1),pi=c(0.5,0.6,0.7))
3 x 3 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3]
[1,] 0.25    .    .
[2,]    . 0.24    .
[3,]    .    . 0.21

Selanjutnya kita akan dapatkan matriks Dn×n yang didefinisikan

Dn×n=[dμ1dη1000dμ2dη20000dμndηn]

elemen-elemen diagonalnya sebagai berikut:

dμidηi=dπidηi=d(exp(ηi)1+exp(ηi))dηi=exp(ηi)[1+exp(ηi)]2=(πi1πi)[1+(πi1πi)]2=πi(1πi)

Jadi matriks Dn×n adalah

Dn×n=[π1(1π1)000π2(1π2)0000πn(1πn)]

kita tuliskan matriks Dn×n dalam sintaks R

D <- function(pi){
di <- pi * ( 1- pi )
Diagonal(x=as.numeric(di))
}

misalkan π1=0.5,π2=0.6,π3=0.7 maka Dn×n adalah

D(pi=c(0.5,0.6,0.7))
3 x 3 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3]
[1,] 0.25    .    .
[2,]    . 0.24    .
[3,]    .    . 0.21

Selanjutnya kita akan dapatkan matriks μn×1 yang didefinisikan

μn×1=g1(Xβ)=exp(Xn×(p+1)β(p+1))1+exp(Xn×(p+1)β(p+1))

mu <- function(X,beta){
  exp(X %*% beta) / ( 1+exp( X%*% beta) )
}

misalkan Xn×(p+1) berasal dari data bank_marketing_mini dan β(p+1)=[0.2300.001 0.002 0.769 0.166 0.109]t maka μn×1 adalah

# memeriksa dimensi
dim( mu(X=X,beta = c(0.230,0.001,0.002,-0.769,-0.166,0.109) ) )
[1] 500   1
# menampilkan 10 elemen pertama
mu(X=X,beta = c(0.230,0.001,0.002,-0.769,-0.166,0.109) )[1:10]
 [1] 0.4955001 0.9975617 0.5530496 0.3815440 0.6869718 0.4782637 0.5386726
 [8] 0.7972185 0.3564054 0.6948728

Fisher Scoring

matriks S(p+1)×1 adalah

S(p+1)×1=X(p+1)×ntWn×n(Dn×n)1(yn×1μn×1)

kita tuliskan matriks S(p+1)×1 dalam sintaks R

S <- function(X,W,D,y,mu){
  inv_D <- chol2inv(chol(D))
 crossprod( X, W %*% inv_D %*% (y-mu) )
}

misalkan Wn×n,Dn×n dan μn×1 adalah sebagai berikut:

set.seed(2045)

W_coba <- W(m = 1,pi = rep(0.5,nrow(X)))
dim(W_coba)
[1] 500 500
W_coba[1:5,1:5]
5 x 5 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3] [,4] [,5]
[1,] 0.25    .    .    .    .
[2,]    . 0.25    .    .    .
[3,]    .    . 0.25    .    .
[4,]    .    .    . 0.25    .
[5,]    .    .    .    . 0.25
D_coba <- D(pi = rep(0.5,nrow(X)))
dim(D_coba)
[1] 500 500
D_coba[1:5,1:5]
5 x 5 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3] [,4] [,5]
[1,] 0.25    .    .    .    .
[2,]    . 0.25    .    .    .
[3,]    .    . 0.25    .    .
[4,]    .    .    . 0.25    .
[5,]    .    .    .    . 0.25
mu_coba <- as.matrix( runif(n = nrow(X),min = 0,max = 1 ) )
dim(mu_coba)
[1] 500   1
head(mu_coba)
           [,1]
[1,] 0.77550659
[2,] 0.94264755
[3,] 0.47241345
[4,] 0.08665263
[5,] 0.63646300
[6,] 0.42453500
S(X = X,W = W_coba,D = D_coba,y = y,mu = mu_coba)
6 x 1 Matrix of class "dgeMatrix"
                      [,1]
(Intercept)       -5.12588
balance        64379.67806
age             -132.00826
housingyes       -27.00537
maritalmarried    -9.45959
maritalsingle      5.37219

matriks Ip×p adalah

Ip×p=X(p+1)×nWn×nXn×(p+1)

kita tuliskan matriks Ip×p dalam sintaks R

I_fs <- function(X,W){
 crossprod(X,W %*% X)
}
set.seed(2045)

W_coba <- W(m = 1,pi = rep(0.5,nrow(X)))
dim(W_coba)
[1] 500 500
W_coba[1:5,1:5]
5 x 5 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3] [,4] [,5]
[1,] 0.25    .    .    .    .
[2,]    . 0.25    .    .    .
[3,]    .    . 0.25    .    .
[4,]    .    .    . 0.25    .
[5,]    .    .    .    . 0.25
I_fs(X = X,W = W_coba)[1:5,1:5]
5 x 5 Matrix of class "dgeMatrix"
               (Intercept)      balance        age housingyes maritalmarried
(Intercept)          125.0 1.901442e+05    5160.00      58.00          68.50
balance           190144.2 1.821748e+09 8400186.75   59549.75      101843.00
age                 5160.0 8.400187e+06  230156.50    2279.50        3062.25
housingyes            58.0 5.954975e+04    2279.50      58.00          31.00
maritalmarried        68.5 1.018430e+05    3062.25      31.00          68.50

Supaya lebih mudah, kita kumpulkan semua definisi matriks yang sudah dituliskan ke program R dibawah ini

W <- function(m,pi){
wi <- m * pi * ( 1- pi )
Diagonal(x=as.numeric(wi))
}
D <- function(pi){
di <- pi * ( 1- pi )
Diagonal(x=as.numeric(di))
}
mu <- function(X,beta){
  exp(X %*% beta) / ( 1+exp( X%*% beta) )
}
S <- function(X,W,D,y,mu){
  inv_D <- chol2inv(chol(D))
 crossprod( X, W %*% inv_D %*% (y-mu) )
}
I_fs <- function(X,W){
 crossprod(X,W %*% X)
}

Selanjutnya kita akan mulai menuliskan program R untuk iterasi fisher scoring

stop_criterion <- function(beta_old,beta_new,tol) {
  error <- as.matrix(abs(beta_new-beta_old))
  status <- all(error  < tol)
  return(list(error=as.data.frame(t(error)),status=status))
}
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.51,-0.91),tol = 1e-5)
$error
    V1   V2
1 0.01 0.01

$status
[1] FALSE
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.50001,-0.90001),tol = 1e-5)
$error
     V1    V2
1 1e-05 1e-05

$status
[1] TRUE
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.5001,-0.90001),tol = 1e-5)
$error
     V1    V2
1 1e-04 1e-05

$status
[1] FALSE

berikut adalah nilai awal dari β(p+1), nilai toleransi, iterasi maksimum dan nilai dari mi. Khusus untuk mi=1 karena respon subscribed adalah respon distribusi bernouli.

beta_new <- rep(0,ncol(X))
names(beta_new) <- colnames(X)
beta_new
   (Intercept)        balance            age     housingyes maritalmarried 
             0              0              0              0              0 
 maritalsingle 
             0 
max_iter <- 1000
mi <- 1

tolerance <-  1e-15

Ingat Formula Fisher Scoring yang digunakan adalah sebagai berikut:

β(p+1)×1(i+1)=β(p+1)×1(i)+[Ip×p(i)]1S(p+1)×1(i)

for(i in 1:max_iter){
  
  #menyimpan beta lama
  beta_old <- beta_new
  
  mu_new <- mu(X = X,beta = beta_new)
  W_new <- W(m = mi,pi = mu_new)
  D_new <- D(pi = mu_new)
  
  I_inv <- chol2inv(chol( I_fs(X = X,W = W_new) ))
  
  #formulasi fisher scoring
  beta_new <- beta_new +I_inv %*% S(X=X,W = W_new,D = D_new,y =y ,mu = mu_new) 
  

  #menghitung stopping criterion
  stop_criterion_iter <- stop_criterion(
                 beta_old = beta_old,
                 beta_new = beta_new,
                 tol = tolerance)
  

  
  #iterasi berhenti jika sudah memenuhi stopping criterion
  if(stop_criterion_iter$status) break
}

Saat Convergent maka kita mendapatkan

Var(β^(p+1)×1)=[Ip×p]1 kemudian standard error dari β^(p+1)×1 adalah akar dari diagonal utama [Ip×p]1.

result_fs <- list(iter_convergence=i,coefficients=as.numeric(beta_new),var_beta=I_inv)
result_fs$iter_convergence
[1] 31
result_fs$var_beta
6 x 6 Matrix of class "dpoMatrix"
                 (Intercept)       balance           age    housingyes
(Intercept)     2.743637e-01 -5.891964e-07 -4.050466e-03 -3.584211e-02
balance        -5.891964e-07  1.308069e-09 -3.003060e-08  6.255880e-07
age            -4.050466e-03 -3.003060e-08  8.377425e-05  3.146135e-04
housingyes     -3.584211e-02  6.255880e-07  3.146135e-04  3.568298e-02
maritalmarried -7.623728e-02 -2.022522e-07  2.006810e-04  5.139815e-03
maritalsingle  -1.230458e-01 -4.027429e-07  1.169965e-03  8.360438e-03
               maritalmarried maritalsingle
(Intercept)     -7.623728e-02 -1.230458e-01
balance         -2.022522e-07 -4.027429e-07
age              2.006810e-04  1.169965e-03
housingyes       5.139815e-03  8.360438e-03
maritalmarried   8.060487e-02  6.751034e-02
maritalsingle    6.751034e-02  1.072151e-01
summary_fs <- data.frame(variables=rownames(beta_new),
                         Estimate=round(result_fs$coefficients,10),
                         Std_Err=round(sqrt(diag(as.matrix(result_fs$var_beta))),10),row.names = NULL) %>% 
              mutate(z=Estimate / Std_Err, p_value=round(2*pnorm(q=abs(z),lower.tail = F),3))
summary_fs
ABCDEFGHIJ0123456789
variables
<chr>
Estimate
<dbl>
Std_Err
<dbl>
z
<dbl>
p_value
<dbl>
(Intercept)0.23006334450.52379742600.43922200.661
balance0.00005578330.00003616721.54237260.123
age0.00246532470.00915282730.26935120.788
housingyes-0.76904478150.1888993831-4.07118740.000
maritalmarried-0.16611149160.2839099667-0.58508510.558
maritalsingle0.10875066380.32743718980.33212680.740

IRLS

matriks z adalah

zn×1=Xn×(p+1)β((𝑝+1)×1)+(Dn×n)1(yn×1μ𝑛×1)

kita tuliskan matriks z dalam sintaks R

z <- function(X,beta,D,y,mu){
  inv_D <- chol2inv(chol(D))
 X %*% beta + inv_D %*%  (y-mu)
}

misalkan Wn×n,β((𝑝+1)×1),Dn×n dan μn×1 adalah sebagai berikut:

set.seed(2045)

W_coba <- W(m = 1,pi = rep(0.5,nrow(X)))
dim(W_coba)
[1] 500 500
W_coba[1:5,1:5]
5 x 5 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3] [,4] [,5]
[1,] 0.25    .    .    .    .
[2,]    . 0.25    .    .    .
[3,]    .    . 0.25    .    .
[4,]    .    .    . 0.25    .
[5,]    .    .    .    . 0.25
beta_coba <- c(0.230,0.001,0.002,-0.769,-0.166,0.109)
beta_coba
[1]  0.230  0.001  0.002 -0.769 -0.166  0.109
D_coba <- D(pi = rep(0.5,nrow(X)))
dim(mu_coba)
[1] 500   1
D_coba[1:5,1:5]
5 x 5 diagonal matrix of class "ddiMatrix"
     [,1] [,2] [,3] [,4] [,5]
[1,] 0.25    .    .    .    .
[2,]    . 0.25    .    .    .
[3,]    .    . 0.25    .    .
[4,]    .    .    . 0.25    .
[5,]    .    .    .    . 0.25
mu_coba <- as.matrix( runif(n = nrow(X),min = 0,max = 1 ) )
dim(mu_coba)
[1] 500   1
head(mu_coba)
           [,1]
[1,] 0.77550659
[2,] 0.94264755
[3,] 0.47241345
[4,] 0.08665263
[5,] 0.63646300
[6,] 0.42453500
z_coba <- z(X = X,beta = beta_coba,D = D_coba,y = y,mu = mu_coba)
dim(z_coba)
[1] 500   1
z_coba[1:10]
 [1] -3.1200264  2.2434098 -1.6766538 -0.8296105 -1.7598520 -1.7851400
 [7] -3.2987687 -1.1895575 -1.5743409  0.1808609

Supaya lebih mudah, kita kumpulkan semua definisi matriks yang sudah dituliskan ke program R dibawah ini

mu <- function(X,beta){
  exp(X %*% beta) / ( 1+exp( X%*% beta) )
}
W <- function(m,pi){
wi <- m * pi * ( 1- pi )
Diagonal(x=as.numeric(wi))
}
D <- function(pi){
di <- pi * ( 1- pi )
Diagonal(x=as.numeric(di))
}
z <- function(X,beta,D,y,mu){
  inv_D <- chol2inv(chol(D))
 X %*% beta + inv_D %*%  (y-mu)
}

Selanjutnya kita akan mulai menuliskan program R untuk iterasi IRLS

stop_criterion <- function(beta_old,beta_new,tol) {
  error <- as.matrix(abs(beta_new-beta_old))
  status <- all(error  < tol)
  return(list(error=as.data.frame(t(error)),status=status))
}
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.51,-0.91),tol = 1e-5)
$error
    V1   V2
1 0.01 0.01

$status
[1] FALSE
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.50001,-0.90001),tol = 1e-5)
$error
     V1    V2
1 1e-05 1e-05

$status
[1] TRUE
stop_criterion(beta_old = c(0.5,-0.9),beta_new = c(0.5001,-0.90001),tol = 1e-5)
$error
     V1    V2
1 1e-04 1e-05

$status
[1] FALSE

berikut adalah nilai awal dari β(p+1) nilai toleransi, iterasi maksimum dan nilai dari mi. Khusus untuk mi=1 karena respon subscribed adalah respon distribusi bernouli.

beta_new <- rep(0,ncol(X))
names(beta_new) <- colnames(X)
beta_new
   (Intercept)        balance            age     housingyes maritalmarried 
             0              0              0              0              0 
 maritalsingle 
             0 
max_iter <- 1000
mi <- 1

tolerance <-  1e-15

Ingat Formula IRLS yang digunakan adalah sebagai berikut:

β(p+1)×1(𝑖+1)={X(𝑝+1)×ntWn×n(i)Xn×(𝑝+1)}1X(𝑝+1)×ntWn×n(i)zn×1(i)

for(i in 1:max_iter){
  
  #menyimpan beta lama
  beta_old <- beta_new
  
  mu_new <- mu(X = X,beta = beta_new)
  W_new <- W(m = mi,pi = mu_new)
  D_new <- D(pi = mu_new)
  
  z_new <- z(X = X,beta = beta_new,D = D_new,y = y,mu = mu_new)
  inv_XWX <- chol2inv(chol(crossprod(X,W_new %*% X)))
  
  #formulasi fisher scoring
  beta_new <- inv_XWX %*% crossprod(X,W_new %*% z_new) 
  

  #menghitung stopping criterion
  stop_criterion_iter <- stop_criterion(
                 beta_old = beta_old,
                 beta_new = beta_new,
                 tol = tolerance)
  

  
  #iterasi berhenti jika sudah memenuhi stopping criterion
  if(stop_criterion_iter$status) break
}

Saat Convergent maka kita mendapatkan

Var(β^(p+1)×1)={Xn×(𝑝+1)tWn×n(i)Xn×(𝑝+1)}1

kemudian standard error dari β^(p+1)×1 adalah akar dari diagonal utama {Xn×(𝑝+1)tWn×n(i)Xn×(𝑝+1)}1.

result_irls <- list(iter_convergence=i,coefficients=as.numeric(beta_new),var_beta=inv_XWX)
result_irls$iter_convergence
[1] 33
result_irls$var_beta
6 x 6 Matrix of class "dpoMatrix"
                 (Intercept)       balance           age    housingyes
(Intercept)     2.743637e-01 -5.891964e-07 -4.050466e-03 -3.584211e-02
balance        -5.891964e-07  1.308069e-09 -3.003060e-08  6.255880e-07
age            -4.050466e-03 -3.003060e-08  8.377425e-05  3.146135e-04
housingyes     -3.584211e-02  6.255880e-07  3.146135e-04  3.568298e-02
maritalmarried -7.623728e-02 -2.022522e-07  2.006810e-04  5.139815e-03
maritalsingle  -1.230458e-01 -4.027429e-07  1.169965e-03  8.360438e-03
               maritalmarried maritalsingle
(Intercept)     -7.623728e-02 -1.230458e-01
balance         -2.022522e-07 -4.027429e-07
age              2.006810e-04  1.169965e-03
housingyes       5.139815e-03  8.360438e-03
maritalmarried   8.060487e-02  6.751034e-02
maritalsingle    6.751034e-02  1.072151e-01
summary_irls <- data.frame(variables=rownames(beta_new),
                         Estimate=round(result_irls$coefficients,10),
                         Std_Err=round(sqrt(diag(as.matrix(result_irls$var_beta))),10),row.names = NULL) %>% 
              mutate(z=Estimate / Std_Err, p_value=round(2*pnorm(q=abs(z),lower.tail = F),3))
summary_irls
ABCDEFGHIJ0123456789
variables
<chr>
Estimate
<dbl>
Std_Err
<dbl>
z
<dbl>
p_value
<dbl>
(Intercept)0.23006334450.52379742600.43922200.661
balance0.00005578330.00003616721.54237260.123
age0.00246532470.00915282730.26935120.788
housingyes-0.76904478150.1888993831-4.07118740.000
maritalmarried-0.16611149160.2839099667-0.58508510.558
maritalsingle0.10875066380.32743718980.33212680.740

Default fungsi R

mod1 <- glm(formula = subscribed~.,
            data = bank_marketing_mini,
            family = binomial(link = "logit"))
tidy(mod1) %>% 
  mutate(across(where(is.numeric),function(x) round(x,7)))
ABCDEFGHIJ0123456789
term
<chr>
estimate
<dbl>
std.error
<dbl>
statistic
<dbl>
p.value
<dbl>
(Intercept)0.23006330.52379740.43922200.6605007
balance0.00005580.00003621.54237250.1229831
age0.00246530.00915280.26935120.7876595
housingyes-0.76904480.1888994-4.07118740.0000468
maritalmarried-0.16611150.2839100-0.58508510.5584905
maritalsingle0.10875070.32743720.33212680.7397935