Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

隣接カテゴリロジットモデル(adjacent category logit model)

隣接カテゴリロジットモデル(adjacent category logit model) は、順序カテゴリデータに対するモデルの一種で、隣り合うカテゴリ間のオッズを対象にモデル化する。

累積ロジットモデルが「kk 以下 vs kk より上」という累積確率のオッズを扱うのに対し、隣接カテゴリロジットモデルは「カテゴリ kk vs カテゴリ k+1k+1」という隣接ペアのオッズを直接モデル化する。

モデルの定式化

隣接カテゴリロジット

目的変数 y∈{1,2,…,K}y \in \{1, 2, \dots, K\} が KK カテゴリの順序変数であるとする。隣接カテゴリロジットは、隣り合うカテゴリの確率の比を対数オッズとして定義する:

log⁡P(y=k∣x)P(y=k+1∣x)=αk−x⊤β(k=1,…,K−1)\log \frac{P(y = k \mid \mathbf{x})}{P(y = k+1 \mid \mathbf{x})} = \alpha_k - \mathbf{x}^\top \boldsymbol{\beta} \quad (k = 1, \dots, K-1)

ここで

  • αk\alpha_k:カテゴリ kk に固有の切片パラメータ

  • β\boldsymbol{\beta}:全カテゴリ共通の回帰係数ベクトル

β\boldsymbol{\beta} が全カテゴリで共通であるという制約は、累積ロジットモデルにおける比例オッズ仮定に対応する。

カテゴリ確率の導出

隣接カテゴリロジットの定義から

P(y=k∣x)=P(y=k+1∣x)⋅exp⁡(αk−x⊤β)P(y = k \mid \mathbf{x}) = P(y = k+1 \mid \mathbf{x}) \cdot \exp(\alpha_k - \mathbf{x}^\top \boldsymbol{\beta})

これを再帰的に適用すると、最後のカテゴリ KK を基準として

P(y=k∣x)=P(y=K∣x)⋅∏j=kK−1exp⁡(αj−x⊤β)P(y = k \mid \mathbf{x}) = P(y = K \mid \mathbf{x}) \cdot \prod_{j=k}^{K-1} \exp(\alpha_j - \mathbf{x}^\top \boldsymbol{\beta})

すなわち

P(y=k∣x)=P(y=K∣x)⋅exp⁡(∑j=kK−1αj−(K−k) x⊤β)P(y = k \mid \mathbf{x}) = P(y = K \mid \mathbf{x}) \cdot \exp\left( \sum_{j=k}^{K-1} \alpha_j - (K - k)\, \mathbf{x}^\top \boldsymbol{\beta} \right)

確率の総和が1になるという制約 ∑k=1KP(y=k∣x)=1\sum_{k=1}^{K} P(y = k \mid \mathbf{x}) = 1 から

P(y=k∣x)=exp⁡(∑j=kK−1αj−(K−k) x⊤β)∑m=1Kexp⁡(∑j=mK−1αj−(K−m) x⊤β)P(y = k \mid \mathbf{x}) = \frac{\exp\left( \sum_{j=k}^{K-1} \alpha_j - (K-k)\, \mathbf{x}^\top \boldsymbol{\beta} \right)}{\sum_{m=1}^{K} \exp\left( \sum_{j=m}^{K-1} \alpha_j - (K-m)\, \mathbf{x}^\top \boldsymbol{\beta} \right)}

ただし k=Kk = K のとき ∑j=KK−1(⋅)=0\sum_{j=K}^{K-1}(\cdot) = 0 と約束する。

累積ロジットモデルとの比較

累積ロジットモデル隣接カテゴリロジットモデル
ロジットlog⁡P(y≤k)P(y>k)\log \frac{P(y \le k)}{P(y > k)}log⁡P(y=k)P(y=k+1)\log \frac{P(y = k)}{P(y = k+1)}
解釈「kk以下」vs「kkより上」の累積オッズ「kk」vs「k+1k+1」の隣接オッズ
確率の導出累積確率の差再帰的に計算
IRTとの対応段階反応モデル(GRM)部分採点モデル(PCM)
比例オッズの意味累積オッズ比が xx に依らず一定隣接オッズ比が xx に依らず一定

隣接カテゴリロジットモデルの方が「直前のカテゴリから次のカテゴリへの移行」を直接モデル化するため、各カテゴリ間の遷移の難しさを表現する場合に直感的である。

係数の解釈

exp⁡(βj)\exp(\beta_j) は、説明変数 xjx_j が1単位増加したときの隣接カテゴリ間のオッズの変化倍率である。

具体的に、βj>0\beta_j > 0 のとき

P(y=k∣xj+1)P(y=k+1∣xj+1)=e−βj⋅P(y=k∣xj)P(y=k+1∣xj)\frac{P(y = k \mid x_j + 1)}{P(y = k+1 \mid x_j + 1)} = e^{-\beta_j} \cdot \frac{P(y = k \mid x_j)}{P(y = k+1 \mid x_j)}

なので、βj>0\beta_j > 0 は xjx_j が増えると「カテゴリ kk よりカテゴリ k+1k+1 を選ぶオッズが eβje^{\beta_j} 倍になる」、すなわち高いカテゴリを選びやすくなることを意味する。

この解釈はすべての隣接ペアで共通であり(比例オッズ仮定)、累積ロジットモデルの exp⁡(βj)\exp(\beta_j) が「累積オッズの変化倍率」であるのと対比される。

最尤推定

対数尤度

nn 個の独立な観測 (yi,xi)(y_i, \mathbf{x}_i) に対する対数尤度は

ℓ(α,β)=∑i=1n∑k=1K1(yi=k) log⁡P(yi=k∣xi)\ell(\boldsymbol{\alpha}, \boldsymbol{\beta}) = \sum_{i=1}^{n} \sum_{k=1}^{K} \mathbb{1}(y_i = k)\, \log P(y_i = k \mid \mathbf{x}_i)

ここで P(yi=k∣xi)P(y_i = k \mid \mathbf{x}_i) は上で導出したカテゴリ確率である。

最尤推定はニュートン・ラフソン法やその他の数値最適化アルゴリズムで行う。

Pythonによる実装

シミュレーションデータでの検証

カテゴリ数: 4
サンプルサイズ: 1000
カテゴリ分布: {0: 569, 1: 98, 2: 79, 3: 254}
真のパラメータ: α = [ 1.5  0.5 -0.5], β = [ 0.8 -0.5]
収束: False
対数尤度: -828.2744

Loading...

カテゴリ確率の可視化

<Figure size 1200x400 with 2 Axes>

累積ロジットモデルとの比較

同じデータに対して累積ロジットモデルも推定し、カテゴリ確率曲線を比較する。

                             OrderedModel Results                             
==============================================================================
Dep. Variable:                      y   Log-Likelihood:                -840.99
Model:                   OrderedModel   AIC:                             1692.
Method:            Maximum Likelihood   BIC:                             1717.
Date:                Sat, 14 Feb 2026                                         
Time:                        09:34:35                                         
No. Observations:                1000                                         
Df Residuals:                     995                                         
Df Model:                           2                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
x1             1.5838      0.099     16.030      0.000       1.390       1.777
x2            -1.0113      0.081    -12.473      0.000      -1.170      -0.852
0/1            0.4330      0.082      5.292      0.000       0.273       0.593
1/2           -0.3938      0.096     -4.100      0.000      -0.582      -0.206
2/3           -0.4807      0.107     -4.483      0.000      -0.691      -0.271
==============================================================================
<Figure size 1200x400 with 2 Axes>

PyMCによる実装

隣接カテゴリロジットモデルは pm.OrderedLogistic が累積ロジットモデルに対応するため直接は使えないが、カテゴリ確率を自前で構成して pm.Categorical に渡すことで実装できる。

Initializing NUTS using jitter+adapt_diag...
/home/mitama/notes/.venv/lib/python3.10/site-packages/pytensor/link/c/cmodule.py:2968: UserWarning: PyTensor could not link to a BLAS installation. Operations that might benefit from BLAS will be severely degraded.
This usually happens when PyTensor is installed via pip. We recommend it be installed via conda/mamba/pixi instead.
Alternatively, you can use an experimental backend such as Numba or JAX that perform their own BLAS optimizations, by setting `pytensor.config.mode == 'NUMBA'` or passing `mode='NUMBA'` when compiling a PyTensor function.
For more options and details see https://pytensor.readthedocs.io/en/latest/troubleshooting.html#how-do-i-configure-test-my-blas-library
  warnings.warn(
Multiprocess sampling (4 chains in 4 jobs)
NUTS: [alpha, beta]
Loading...
Loading...
Sampling 4 chains for 1_000 tune and 2_000 draw iterations (4_000 + 8_000 draws total) took 3 seconds.
Loading...
<Figure size 1200x800 with 4 Axes>