逻辑回归的MLE对数似然性给出除零误差

时间:2017-10-01 09:15:10

标签: python machine-learning logistic-regression gradient-descent divide-by-zero

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

Get-ScheduledTask| %{$taskName=$_.TaskName; $_.Triggers | 
where {$_ -ne $null -and $_.Enabled -eq $true -and $_.StartBoundary -ne $null -and ([System.DateTime]$_.StartBoundary).Hour -in 21..23} |  %{ 
[pscustomobject]@{
Name=$taskName; 
trigger=$_
Enabled=$_.Enabled
EndBoundary=$_.EndBoundary
ExecutionTimeLimit=$_.ExecutionTimeLimit
Id=$_.Id
Repetition=$_.Repetition
StartBoundary=$_.StartBoundary
DaysInterval=$_.DaysInterval
RandomDelay=$_.RandomDelay
PSComputerName=$_.PSComputerName
}

}

} 

应用此功能会导致

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))

我希望y_0是一个负浮动。如何避免此错误,代码中是否存在错误?

修改1

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

修改2

我也可以访问这个用于在日志空间中计算sigma的logsigma函数:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

log-likelihood

除以零可能是由X @ w中的大的负值(我的意思是大的绝对值)引起的,例如sigma(-800)在我的计算机上完全是0.0,因此其日志会生成"RuntimeWarning: divide by zero encountered in log"

确保使用接近零的小值初始化网络,并且在多次反向提升之后,您不会爆炸渐变。

顺便说一句,这里是我用于交叉熵丢失的代码,它也适用于多类问题:

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)永远不会发生。

相关问题