【问题标题】:How can I avoid value errors when using numpy.random.multinomial?使用 numpy.random.multinomial 时如何避免值错误?
【发布时间】:2014-04-24 00:19:36
【问题描述】:

当我使用这个随机生成器:numpy.random.multinomial,我不断得到:

ValueError: sum(pvals[:-1]) > 1.0

我总是传递这个 softmax 函数的输出:

def softmax(w, t = 1.0):
    e = numpy.exp(numpy.array(w) / t)
    dist = e / np.sum(e)
    return dist

除了现在我收到此错误外,我还为参数添加了此错误 (pvals):

while numpy.sum(pvals) > 1:
    pvals /= (1+1e-5)

但这并没有解决问题。确保避免此错误的正确方法是什么?

编辑:这是包含此代码的函数

def get_MDN_prediction(vec):
    coeffs = vec[::3]
    means = vec[1::3]
    stds = np.log(1+np.exp(vec[2::3]))
    stds = np.maximum(stds, min_std)
    coe = softmax(coeffs)
    while np.sum(coe) > 1-1e-9:
        coe /= (1+1e-5)
    coeff = unhot(np.random.multinomial(1, coe))
    return np.random.normal(means[coeff], stds[coeff])

【问题讨论】:

  • 你检查过所有的值都是有限的吗?
  • 当您将pvals.sum() 传递给np.random.multinomial 时,它的值是多少?
  • 有些东西你没有展示出来,比如A, and the full traceback (including the actual code, sum(pvals[:-1]) > 1.0` is not here)。
  • A 是 numpy.array,我已经替换了它。
  • 如果你使用np.random.choice而不是np.random.multinomial,你不会得到错误并且得到相同的结果。

标签: python numpy random numerical-stability


【解决方案1】:

我知道这个问题很老,但由于我刚才遇到了同样的问题,在我看来它仍然有效。这是我找到的解决方案:

a = np.asarray(a).astype('float64') a = a / np.sum(a) b = np.random.multinomial(1, a, 1)

我把重要的部分加粗了。如果您忽略该部分,您提到的问题将不时发生。但是如果你把数组的类型改成float64,就永远不会发生了。

【讨论】:

    【解决方案2】:

    我在语言建模工作中也遇到了这个问题。

    这个问题的根源在于 numpy 的隐式数据转换:我的 sorfmax() 的输出是 float32 类型,但是,numpy.random.multinomial() 会将 pval 隐式转换为 float64 类型。由于数字舍入,这种数据类型转换有时会导致 pval.sum() 超过 1.0。

    此问题已被识别并发布here

    【讨论】:

      【解决方案3】:

      很少有人注意到的一点:通过从值中删除 logsumexp 可以很容易地获得 softmax 的稳健版本:

      from scipy.misc import logsumexp
      
      def log_softmax(vec):
          return vec - logsumexp(vec)
      
      def softmax(vec):
          return np.exp(log_softmax(vec))
      

      检查一下:

      print(softmax(np.array([1.0, 0.0, -1.0, 1.1])))
      

      很简单,不是吗?

      【讨论】:

      • softmax(np.array([1/20.]*20)).sum() 的总和为 1.0000000000000002。
      【解决方案4】:

      我使用的softmax 实现对于我使用它的值来说不够稳定。因此,有时输出的总和大于1(例如1.0000024...)。

      这种情况应该由while循环处理。但有时输出包含 NaN,在这种情况下永远不会触发循环,并且错误仍然存​​在。

      另外,numpy.random.multinomial 在看到 NaN 时不会引发错误。

      这是我现在使用的,而不是:

      def softmax(vec):
          vec -= min(A(vec))
          if max(vec) > 700:
              a = np.argsort(vec)
              aa = np.argsort(a)
              vec = vec[a]
              i = 0
              while max(vec) > 700:
                  i += 1
                  vec -= vec[i]
              vec = vec[aa]
          e = np.exp(vec)
          return e/np.sum(e)
      
      def sample_multinomial(w):
          """
             Sample multinomial distribution with parameters given by softmax of w
             Returns an int    
          """
          p = softmax(w)
          x = np.random.uniform(0,1)
          for i,v in enumerate(np.cumsum(p)):
              if x < v: return i
          return len(p)-1 # shouldn't happen...
      

      【讨论】:

        猜你喜欢
        • 2013-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-31
        • 1970-01-01
        • 2020-06-17
        • 1970-01-01
        • 2015-06-13
        相关资源
        最近更新 更多