1

私はk異なるクラスを区別するマルチクラスロジスティック回帰分類器を実装しようとしています。Pythonはlog - logistic regressionでゼロで除算する

これは私のコードです。

import numpy as np 
from scipy.special import expit 


def cost(X,y,theta,regTerm): 
    (m,n) = X.shape 
    J = (np.dot(-(y.T),np.log(expit(np.dot(X,theta))))-np.dot((np.ones((m,1))-y).T,np.log(np.ones((m,1)) - (expit(np.dot(X,theta))).reshape((m,1)))))/m + (regTerm/(2 * m)) * np.linalg.norm(theta[1:]) 
    return J 

def gradient(X,y,theta,regTerm): 
    (m,n) = X.shape 
    grad = np.dot(((expit(np.dot(X,theta))).reshape(m,1) - y).T,X)/m + (np.concatenate(([0],theta[1:].T),axis=0)).reshape(1,n) 
    return np.asarray(grad) 

def train(X,y,regTerm,learnRate,epsilon,k): 
    (m,n) = X.shape 
    theta = np.zeros((k,n)) 
    for i in range(0,k): 
     previousCost = 0; 
     currentCost = cost(X,y,theta[i,:],regTerm) 
     while(np.abs(currentCost-previousCost) > epsilon): 
      print(theta[i,:]) 
      theta[i,:] = theta[i,:] - learnRate*gradient(X,y,theta[i,:],regTerm) 
      print(theta[i,:]) 
      previousCost = currentCost 
      currentCost = cost(X,y,theta[i,:],regTerm) 
    return theta 

trX = np.load('trX.npy') 
trY = np.load('trY.npy') 
theta = train(trX,trY,2,0.1,0.1,4) 
Iが(コストはスカラーを返し、傾きが1、n個の行ベクトルによって返さ)正しい寸法にある値を返すされるコスト及び勾配を確認することができ、私はエラーを取得

RuntimeWarning: divide by zero encountered in log 
    J = (np.dot(-(y.T),np.log(expit(np.dot(X,theta))))-np.dot((np.ones((m,1))-y).T,np.log(np.ones((m,1)) - (expit(np.dot(X,theta))).reshape((m,1)))))/m + (regTerm/(2 * m)) * np.linalg.norm(theta[1:]) 

なぜこれが起こっているのですか?これを避けるにはどうすればよいですか?

+0

あなたの公式を見ると、mは0なので(regTerm /(2 * m)) '/ m 'は0で割り切れるようになります。 – Munir

+0

mは0ではなく、私の場合は4104です。 –

答えて

3

ブロードキャスト、ベクトルのドット積の演算子*、行列の乗算—の演算子@を使用して、適切に除算することができます。

def cost(X, y, theta, regTerm): 
    m = X.shape[0] # or y.shape, or even p.shape after the next line, number of training set 
    p = expit(X @ theta) 
    log_loss = -np.average(y*np.log(p) + (1-y)*np.log(1-p)) 
    J = log_loss + regTerm * np.linalg.norm(theta[1:])/(2*m) 
    return J 

あなたが同じラインに沿ってあなたの勾配関数をクリーンアップすることができます

はここにあなたのコスト関数です。

ところで、あなたは確かにnp.linalg.norm(theta[1:])が欲しいですか? L2正則化をしようとしている場合、用語はnp.linalg.norm(theta[1:]) ** 2でなければなりません。

0

あなたのデータに負の値があると思います。ネガを記録することはできません。

import numpy as np 
np.log(2) 
> 0.69314718055994529 
np.log(-2) 
> nan 

このような場合に役立つデータを変換する方法はたくさんあります。

+0

いいえ、私はちょうどチェックしました。どこでもデータに負の値はありません。 –

+0

その場合、エラーが発生したその巨大な行の中で減算と除算の両方を行っているので、次に見ていきます。また、それは、私が思うように、その行を分けて分かりやすくするでしょう。また、デバッグも容易になります。 – Jeff

+1

たとえば、分母を別々に計算して変数に代入し、その行を変数で除算します。しかし、その前に分母を出力する中間出力を入れてください。実際にゼロであるかどうかを確認することができます。もしそれが分かれば、そこにどのように到達しているかを追跡することができます。 – Jeff