逻辑回归的 MLE 对数似然给出除以零的错误

MLE Log-likelihood for logistic regression gives divide by zero error

我想计算逻辑回归模型的对数似然。

def sigma(x):
    return 1 / (1 + np.exp(-x))

def logll(y, X, w):
    """"
    Parameters
    y : ndarray of shape (N,)
        Binary labels (either 0 or 1).
    X : ndarray of shape (N,D)
        Design matrix.
    w : ndarray of shape (D,)
        Weight vector.
    """
    p = sigma(X @ w)
    y_1 = y @ np.log(p)
    y_0 = (1 - y) @ (1 - np.log(1 - p))
    return y_1 + y_0

logll(y, Xz, np.linspace(-5,5,D))

应用此函数会导致

/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:16: 
RuntimeWarning: divide by zero encountered in log
  app.launch_new_instance()

我希望 y_0 是负浮点数。我怎样才能避免这个错误,代码中是否存在错误?

编辑 1

X @ w statistics:
Max: 550.775133944
Min: -141.972597608
Sigma(max): 1.0 => Throws error in y_0 in np.log(1 - 1.0)
Sigma(min): 2.19828642169e-62

编辑 2

我也可以访问这个计算 sigma 的 logsigma 函数 space:

def logsigma (x):
   return np.vectorize(np.log)(sigma(x))

不幸的是,那时我没有找到重写 y_0 的方法。以下是我的做法,但显然不正确。

def l(y, X, w):
    y_1 = np.dot(y, logsigma(X @ w))
    y_0 = (1 - y) @ (1 - np.log(1 - logsigma(X @ w)))
    return y_1 + y_0

首先,我认为您在对数似然公式中犯了一个错误:它应该是 y_0y_1 的简单总和,而不是指数总和:

被零除可能是由X @ w中的大负值(我的意思是绝对值大)引起的,例如sigma(-800) 在我的机器上正好是 0.0,所以它的日志结果是 "RuntimeWarning: divide by zero encountered in log"

确保你用接近零的小值初始化你的网络,并且在多次反向传播迭代后你没有爆炸梯度。

顺便说一下,这是我用于交叉熵损失的代码,它也适用于多 class 问题:

def softmax_loss(x, y):
  """
  - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
    for the ith input.
  - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
    0 <= y[i] < C
  """
  probs = np.exp(x - np.max(x, axis=1, keepdims=True))
  probs /= np.sum(probs, axis=1, keepdims=True)
  N = x.shape[0]
  return -np.sum(np.log(probs[np.arange(N), y])) / N

UPD:当别无他法时,还有一个数字技巧(在评论中讨论):计算 log(p+epsilon)log(1-p+epsilon) 具有较小的正 epsilon 值。这确保 log(0.0) 永远不会发生。