井出草平の研究ノート

Ordinalパッケージを用いた順序ロジスティック回帰分析

quantifyinghealth.com

注:動作しないコードを書き換え、不足しているものに関して注という形で補完している。

順序ロジスティック回帰は、1つまたは複数の予測変数(数値またはカテゴリ)と順序結果の間の関係をモデルする回帰分析の一種だ。順序結果は、次のような論理的順序を持つ2つ以上のカテゴリを持つ変数である:

  • 癌のステージ:0、1、2、3、4
  • 所得レベル:低、中、高

このチュートリアルでは、GitHubのリンクからダウンロードできる(https://github.com/datasciencedojo/datasets/blob/master/titanic.csv)。

注:ここではtitanicパッケージのtitanic_trainデータを使用する。

titanicデータセットで順序ロジスティック回帰を使い、予測変数Pclass(乗客クラス)を予測する:Pclassは、3つの値(1: first class, 2: second class, 3: third class)のうちの1つを取ることができる: 予測変数:年齢(Age)、性別(Sex)、生存(Survived)。

library(titanic)
titanic.raw <-titanic_train
## サブセットを作成
titanic <- subset(titanic.raw, select = c(Pclass, Age, Sex, Survived))

## Pclassにレベルをつける
titanic$Pclass <- factor(titanic$Pclass, levels = c(3, 2, 1), 
                         labels = c("1st", "2nd", "3rd"), ordered = TRUE)
titanic$Sex <- factor(titanic$Sex)
titanic$Survived <- factor(titanic$Survived, 
                           labels = c("Died", "Survived"))
str(titanic)
'data.frame':    891 obs. of  4 variables:
 $ Pclass  : Ord.factor w/ 3 levels "1st"<"2nd"<"3rd": 1 3 1 3 1 1 3 1 1 2 ...
 $ Age     : num  22 38 26 35 35 NA 54 2 27 14 ...
 $ Sex     : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
 $ Survived: Factor w/ 2 levels "Died","Survived": 1 2 2 2 1 1 1 1 2 2 ...

2. 順序ロジスティック回帰モデルのフィッティング

我々は、順序ロジスティック回帰の最も一般的なタイプである比例オッズ・ロジスティック回帰を使用する。

このモデルは、ordinal パッケージのclm()関数を用いて、下記のように実行できる:

library(ordinal)
model <- clm(Pclass ~ Age + Sex + Survived, data = titanic, na.action = na.omit)
summary(model)
Coefficients:
                 Estimate Std. Error z value Pr(>|z|)    
Age              0.063208   0.005857  10.792   <2e-16 ***
Sexmale          0.315159   0.199921   1.576    0.115    
SurvivedSurvived 1.969870   0.204830   9.617   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Threshold coefficients:
        Estimate Std. Error z value
1st|2nd   2.8120     0.2838    9.91
2nd|3rd   4.2024     0.3091   13.60

na.actionはリストワイズを意味するna.omit、na.excludeは(予測値、標準誤差、区間限界において)残差値NAと表示される。

各予測変数と結果の関係の解釈

予測変数 X1 に関連づけられた順序ロジスティック回帰係数 β1 の一般的な解釈は,次式である.

予測変数X1が1単位増加すると,結果Yがより高いカテゴリーにあることの対数オッズがβ1変化する.

予測変数の係数は対数オッズ比なので、オッズ比を得るためには指数化しなければならない。

Rでは、係数とp値を抽出するために、モデル・フィットの関数tidy()を、引数exponentiate = TRUEとconf.int = TRUE(95%信頼区間を表示する)で呼び出すことができる。そして、表を小さくするために、出力から標準誤差とzスコアを取り除く:

library(tidymodels)
tidy(model, exponentiate = TRUE, conf.int = TRUE) |> 
  select(-c(std.error, statistic))
  term             estimate  p.value conf.low conf.high coef.type
  <chr>               <dbl>    <dbl>    <dbl>     <dbl> <chr>    
1 1st|2nd             16.6  3.77e-23   NA         NA    intercept
2 2nd|3rd             66.8  4.17e-42   NA         NA    intercept
3 Age                  1.07 3.77e-27    1.05       1.08 location 
4 Sexmale              1.37 1.15e- 1    0.930      2.04 location 
5 SurvivedSurvived     7.17 6.77e-22    4.83      10.8  location 

我々は、予測変数の係数(最後の3行)のみを見て、切片は見ない。以下は、その解釈方法 である:

年齢の係数の解釈:

年齢に関する指数係数(オッズ比)は1.07である。年齢が高いことは、より高い客室であることと正の関係があり、解釈は次のようになる:

年齢が高い乗客は、より高いクラスのチケットを持つ傾向がある(p < 0.001)。具体的には、1歳上の乗客は、1.07倍高い確率で、1クラス高い客室のチケットを持つ。

Sexの係数の解釈:

男性のSexに関する指数係数(オッズ比)は統計的に有意ではない(p = 0.115)。

生存率の係数の解釈

Survivedの指数係数(オッズ比)7.17である。

生存した乗客は、より高いクラスのチケットを持っている傾向がある(p < 0.001)。具体的には、生存した乗客は、生存しなかった乗客よりも7.17倍の高い確率で1クラス上の航空券を持っていた。

モデル適合のチェック

rcompanionパッケージの関数nagelkerke()は、擬似R2乗を計算し、尤度比検定を実行する:

library(rcompanion)
nagelkerke(model)
$Models
                                                    
Model: "clm, Pclass ~ Age + Sex + Survived, titanic"
Null:  "clm, Pclass ~ 1, titanic"                   

$Pseudo.R.squared.for.model.vs.null
                             Pseudo.R.squared
McFadden                             0.155862
Cox and Snell (ML)                   0.277186
Nagelkerke (Cragg and Uhler)         0.316640

$Likelihood.ratio.test
 Df.diff LogLik.diff  Chisq   p.value
      -3     -115.88 231.77 5.738e-50

$Number.of.observations
          
Model: 714
Null:  714

$Messages
[1] "Note: For models fit with REML, these statistics are based on refitting with ML"

$Warnings
[1] "None"

特に重要なのは、
NagelkerkeのR2乗: ロジスティック回帰モデルの適合度を測定する0から1の間の数値である。 尤度比検定: フル・モデル(すべての予測変数を含むモデル)がヌル・モデル(変数を含まないモデル)よりもよくデータに適合するかどうかを検定する。我々の事例では、LogLik.diffは-115.88で、p < 0.001であり、これは予測変数を追加することが予測変数を含まない帰無モデルよりもよいことを意味する。

 注

nagelkerkeの疑似R二乗を用いた尤度比検定は行わない方が良いと思われる。一つはnagelkerkeの疑似R二乗が通常のR二乗とは異なるということ、もう一つはR二乗はがモデルのフィッティングを示す指標としては不適切であるためである。
参考:
https://ides.hatenablog.com/entry/2022/05/06/165738
https://ides.hatenablog.com/entry/2022/06/19/030458

また、lipsitz検定を実行して適合度をチェックすることもできる:

library(generalhoslem)
lipsitz.test(model)
Lipsitz goodness of fit test for ordinal response models

data:  formula:  Pclass ~ Age + Sex + Survived
LR statistic = 5.2796, df = 9, p-value = 0.8093

帰無仮説は、指定されたモデルがデータによく適合する。5%水準以下の小さなP値は、モデルが不完全であることを示唆する。つまり、我々のモデルはデータに適合している。

リプシッツ検定は、順序対応ロジスティック回帰モデルの適合度検定である。これは、順序応答スコアに基づいて、観察されたデータを等しい大きさのg群に分割することを含む。このスコアは、各結果水準での各被験者の予測確率に等間隔の整数の重みを掛けて合計することにより計算される。ユーザーは、デフォルトでは10であるgに整数値を代入して、グループの数を指定できる。

データのこの分割が与えられると、各グループについて、被験者が領域gにあればI = 1、なければI = 0となるようなダミー変数Iが導かれる。そして、モデルをこれらのダミー変数で再フィットする。Lipsitz ら (1996) は、尤度比検定、Wald 検定、スコア検定が使用できることを示唆している; lipsitz.test は、自由度 g-1 の尤度比検定を使用するだけである。

モデルを実行する前に、結果変数を因子に変換しなければならないことに注意してほしい。モデル関数内で as.factor() を使用すると、 lipsitz.test がモデルを再適合するために update() 関数を使用する方法のため、エラーが発生する。

Lipsitz 検定は、順序Hosmer-Lemeshow 検定(logitgof)とPulkstenis-Robinson 検定(pulkrob.chisq と pulkrob.deviance)と一緒に実行することが推奨さ れる(Fagerland and Hosmer, 2016)。

https://www.rdocumentation.org/packages/generalhoslem/versions/1.3.4/topics/lipsitz.test

注:Pulkstenis-Robinson 検定

帰無仮説は、指定されたモデルがデータによく適合する。5%水準以下の小さなP値は、モデルが不完全であることを示唆する。 c("Sex","Survived")のところはカテゴリカル変数を指定する必要がある。

pulkrob.chisq(model, c("Sex","Survived"))
 Pulkstenis-Robinson chi-squared test

data:  formula:  Pclass ~ Age + Sex + Survived
X-squared = 28.637, df = 11, p-value = 0.002583
pulkrob.deviance(model, c("Sex","Survived"))
 Pulkstenis-Robinson deviance test

data:  formula:  Pclass ~ Age + Sex + Survived
Deviance-squared = 28.448, df = 11, p-value = 0.002763

注:Hosmer-Lemeshow検定

帰無仮説は、指定されたモデルがデータによく適合する。5%水準以下の小さなP値は、モデルが不完全であることを示唆する。

## 欠損地を削除してtitanic.na.omitに格納
titanic.na.omit <- na.omit(titanic) 

## 従属変数のみのデータをpredprobに格納
predprob <- data.frame(Age = titanic.na.omit$Age, Sex = titanic.na.omit$Sex, Survived = titanic.na.omit$Survived)

## フィットさせたオブジェクトmodelから必要なものをfvに格納
fv <- predict(model, newdata = predprob, type = "prob")$fit

## Hosmer-Lemeshow検定を実行,従属変数、フィットさせたオブジェクト、従属変数のカテゴリー数、順序変数かどうかを指定する。
logitgof(titanic.na.omit$Pclass, fv, g = 3, ord = TRUE)
     Hosmer and Lemeshow test (ordinal model)

data:  titanic.na.omit$Pclass, fv
X-squared = 3.5784, df = 3, p-value = 0.3107

順序ロジスティック回帰モデルの精度

次に、3つのステップでモデルの精度を計算する:

ステップ#1: フィット値を取得し、predsに保存する:

注:ここではbroomパッケージのaugment()を用いる。

preds <- augment(model, type = "class", na.action="na.omit")
preds
# A tibble: 714 × 6
   .rownames Pclass   Age Sex    Survived .fitted
   <chr>     <ord>  <dbl> <fct>  <fct>    <fct>  
 1 1         1st       22 male   Died     1st    
 2 2         3rd       38 female Survived 3rd    
 3 3         1st       26 female Survived 3rd    
 4 4         3rd       35 female Survived 3rd    
 5 5         1st       35 male   Died     1st    
 6 7         3rd       54 male   Died     3rd    
 7 8         1st        2 male   Died     1st    
 8 9         1st       27 female Survived 3rd    
 9 10        2nd       14 female Survived 1st    
10 11        1st        4 female Survived 1st  

ステップ2:混同行列を見る:

注:yardstickのconf_mat()を用いる。

conf_mat(preds, truth = Pclass, estimate = .fitted)
          Truth
Prediction 1st 2nd 3rd
       1st 306 114  73
       2nd   0   0   0
       3rd  49  59 113

このモデルは、2等席のチケットを持っている人を分類していないことに注意してほしい。

ここで停止して、混同行列を用いて手動で精度を計算することもできますが、yardstickのaccuracy()関数を用いるとより速く計算できるでしょう。

ステップ3: モデルの精度を計算する:

yardstick::accuracy(preds, truth = Pclass, estimate = .fitted)
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy multiclass     0.587

つまり、年齢、性別、生存率に基づいて、モデルは乗客のクラスを58.7%の確率で正しく推測していることになる。

比例オッズの仮定のチェック

上記の順序ロジスティック回帰モデルの特定のタイプ(比例オッズ・ロジスティック回帰)は、結果での各予測変数の効果が結果のすべてのレベルについて同じであると仮定している。たとえば、2等席のチケット vs 1等席のチケットを持つオッズでの年齢の1歳増加の効果は、3等席のチケット vs 2等席のチケットを持つオッズでの年齢の1歳増加の効果と同じといったものだ。

ここで帰無仮説は、比例オッズの仮定が成り立つというものです。帰無仮説は,比例オッズの仮定が成り立つというものである.オムニバス検定でp < 0.05と変数の少なくとも1つが重なると,仮定が破られたとみなされる[source: McNulty K. Handbook of Regression Modeling in People Analytics: With Examples in R and Python. 第1版。Chapman and Hall/CRC; 2021.].

library(gofcat)
brant.test(model)
Brant Test:
                    chi-sq   df   pr(>chi)
Omnibus              3.699    3       0.30
Age                  2.027    1       0.15
Sexmale              1.554    1       0.21
SurvivedSurvived     0.679    1       0.41

H0: Proportional odds assumption holds

ここでは、すべてのp値が0.05を超えているので、比例オッズの仮定が成り立つ。