[Python] statsmodelsでnegative binomial regressionを用いるときの落とし穴

statsmodelsでNegative Binomial Regressionをかけようと思ったら,想像以上の落とし穴があったのでここに記録を示す.

Negative binomial RegressionはPoisson Regressionの平均と分散が同じ制約を緩めたregressionと捉える.実際に,Possion Regressionのモデルの当てはまりを向上させるためには3つのregressionを考える.Negative Binomial Regressionはその方法の一つ,かつ,0が多いデータに対してもモデルの当てはまりが良い.0が多いデータでも当てられるregressionとしては,Zero inflated poisson regressionが上げられる,しかし,0になる確率pと平均のパラメターλの両方に説明変数を効かせると解釈がしにくい.最後に,過分散を踏まえて標準偏差を計算する方法としてquasi-possion regressionがある.これは点推定の結果は一緒だが,標準偏差が通常のPoisson regressionより広くなる.データに対して頑健な結果を出してくれる.

さて,以上を踏まえてNegative Binomial Regressionをstatsmodelsで実装していく.

Negative Binomial Regressionの実装

実装自体は簡単.

from patsy import dmatrix
import statsmodels.api as sm

data = sm.datasets.get_rdataset("warpbreaks", "datasets").data
X = dmatrix("~ wool + C(tension, Treatment('L'))", data=data, return_type="dataframe")
y = data["breaks"]
model = sm.NegativeBinomial(y, X).fit()
model.summary()

それか,formulaを使うなら,

import statsmodels.formula.api as smf
import statsmodels.api as sm
data = sm.datasets.get_rdataset("warpbreaks", "datasets").data
model = smf.negativebinomial("breaks ~ wool + C(tension, Treatment('L'))", data=data,  ).fit()
model.summary()

んで結果が,

                     NegativeBinomial Regression Results                      
==============================================================================
Dep. Variable:                 breaks   No. Observations:                   54
Model:               NegativeBinomial   Df Residuals:                       50
Method:                           MLE   Df Model:                            3
Date:                Fri, 10 Jun 2022   Pseudo R-squ.:                 0.04391
Time:                        07:36:08   Log-Likelihood:                -199.38
converged:                       True   LL-Null:                       -208.54
Covariance Type:            nonrobust   LLR p-value:                 0.0003792
===================================================================================================
                                      coef    std err          z      P>|z|      [0.025      0.975]
---------------------------------------------------------------------------------------------------
Intercept                           3.6734      0.095     38.516      0.000       3.486       3.860
wool[T.B]                          -0.1862      0.101     -1.835      0.066      -0.385       0.013
C(tension, Treatment('L'))[T.H]    -0.5114      0.124     -4.134      0.000      -0.754      -0.269
C(tension, Treatment('L'))[T.M]    -0.2992      0.122     -2.446      0.014      -0.539      -0.059
alpha                               0.1006      0.026      3.882      0.000       0.050       0.151
===================================================================================================

となる.alphaがRにおけるθの逆数でdispersionを表す.

今回は,MLEの推定にIterationsが11回で終わっているので良いが,ときどきconvergenceがFailuerするときがある.このようなときは,

model = smf.negativebinomial("breaks ~ wool + C(tension, Treatment('L'))", data=data,  ).fit(max_iter=100)

のように,iterationの上限を35から更に上にしておく.

また,Quassi-NegativeBinomial Regressionを行うときは,

model = smf.negativebinomial("breaks ~ wool + C(tension, Treatment('L'))", data=data,  ).fit(cov_type="HC0")

のように,cov_typeをHC0, HC1, HC2, HC3のいずれかにする.詳細は,statsmodels.regression.linear_model.RegressionResults に書かれているHeteroscedasticity robust covariance matrix,おそらく,White’s (1980),MacKinnon and White’s (1985) を参照のこと.

落とし穴

Negative Binomial Regressionを用いるときの落とし穴としては,当初以下のように実装するものだと思っていた.

import statsmodels.api as sm
import statsmodels.formula.api as smf
data = sm.datasets.get_rdataset("warpbreaks", "datasets").data
model = smf.glm("breaks ~ wool + C(tension, Treatment('L'))", data=data, family=sm.families.NegativeBinomial() ).fit()
display(model.summary())

一般的なglmの実装と同じだが,現在,こちらの連続量として取り扱うNegativeBinomialは挙動が怪しくて,RのMASSパッケージのglm.nbと結果が異なってくる.開発者もdiscreteなNegativeBinomialを用いることを推奨している.また,discreteな場合を用いないとdispersion parameterの推定も行ってくれない.ここが一番,documentsなどから読み取れなかったことだった.

その2.さらにNegativeBinomialPを用いることも推奨されたが,これは挙動が不安定.NegativeBinomialPはNegative Binomial Regressionを行う際の平均と分散の関係を指定するが,その次数を指定出来る.しかしながら,使えない.

まだまだ開発をまたなければいけないよう.

ちなみに,MLEの結果を調べたければ,model.mle_settingsかmodel.mle_retvalsの中にある.特にconvergedの結果に関しては,model.mle_retvals[“converged”]で取得可能.v0.14の段階で記法の改善を期待.

参考文献

FAQ: NegativeBinomial regression’s default uses quassi method? Reason for differences with R’s glm.nb.
Python Negative Binomial Regression – Results Don’t Match those from R
BUG/Review GLM scale type negative binomial
statsmodels.regression.linear_model.RegressionResults
statsmodels.discrete.discrete_model.NegativeBinomial
statsmodels.discrete.discrete_model.NegativeBinomialP
William Greene (2008) Functional forms for the negative binomial model for count data

コメント

タイトルとURLをコピーしました