これは、スタック オーバーフローに関する私の最初の投稿です。
多項 (または条件付き) ロジット モデルのコードを開発しようとしています ( http://data.princeton.edu/wws509/notes/c6s3.htmlで説明されています)。このタイプのモデルは、古典的なバイナリ ロジスティック回帰。多項ロジット モデルは、離散選択モデリングによく使用されます。
以下のコードでは、すべての参加者 (N) が同じ選択肢の質問 (T) に直面した場合の 2 つのオプション (J) の選択を説明するモデルを記述します。私はすでにR用の同様のコードを開発しており、非常にうまく機能しますが、ゆっくりと動作します(「最適な」ルーチンのため)。オーバーフローの問題のため、PYTHON でこのタイプのコードを開発するのはより困難なようです。最初の操作 (つまり、numpsy.dot(X,beta)) は、numpsy.exp() と「互換性がない」非常に大きな/小さな値につながる可能性があります。https://lingpipe-blog.com/2012/02/16/howprevent-overflow-underflow-logistic-regression/に示されているように、オーバーフローの問題は次の場合に発生する傾向があります: abs(np.dot(X,beta)) > 500. 最初のオーバーフローの問題は、コードの残りの部分で 0、NaN、および Inf 値につながるため、重要な結果をもたらします。問題 (例: np.log(0) または number/Inf)。decimal モジュール、bigfloat モジュールなどでこの問題を修正するために何時間も費やしましたが、うまくいかなかったようです ( numpy を使用して exp のオーバーフローを処理します)。
2 番目に最適なオプションは、いくつかの丸め操作 (num[num > 400] = 400 など) を含めて尤度関数を変更し、「Nelder-Mead」アルゴリズムを使用して対数尤度を最小化するようです。理想的には「BFGS」アルゴリズムを使用しますが、丸め操作と互換性がありません。
コードのオーバーフローの問題を修正する方法についてのアイデアはありますか?
備考: 非常に大きな np.dot(X,beta) 値は、R、MATLAB、STATA では問題にならないようです。
あなたの助けは大歓迎です!
パイソンコード
N = len(set(data[:,0]))
T = 20
J = 2
Y = np.reshape(data[:,12],(N*T,J))
X = np.matrix(data[:,[33,10,5,6,7,8,9]])
def fn_mnl(beta):
num = np.dot(X,beta)
num[num > 400] = 400 # to avoid overflow with np.exp()
num[num < -400] = -400 # to avoid underflow with np.exp()
num = np.exp(num)
num = num.reshape(N*T,J)
den = np.sum(num, axis=1)
prbj = num/den
prbi = prbj[Y==1]
prbi[prbi <= 0] = 0.0000001 # to avoid issue with np.log()
llik = np.sum(np.log(prbi))
return(-llik)
sv = [0]*X.shape[1]
res = sc.minimize(fn_mnl, sv, method='Nelder-Mead')
R コード
LOGIT = function(Beta, DATA, X, Y){
num = exp(as.matrix(DATA[,X]) %*% as.vector(Beta))
mat1 = matrix(num, ncol=2, byrow=T)
prbj = mat1/rowSums(mat1)
prbi = prbj[Y==1]
logl = sum(log(prbi))
return(-logl)}