如何避免使用numpy.random.multinomial时出现值错误?
当我使用这个随机生成器: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])
4 个回答
1
我使用的 softmax
实现对于我用的数值来说不够稳定。因此,有时候输出的结果总和会大于 1
(比如 1.0000024...
)。
这个情况应该通过一个循环来处理。但是有时候输出会出现 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...
2
有一点很少有人注意到:我们可以通过去掉值中的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])))
很简单,对吧?
5
我知道这个问题已经很久了,但因为我刚遇到同样的问题,所以我觉得这个问题还是很有意义的。这里是我找到的解决办法:
a = np.asarray(a).astype('float64') a = a / np.sum(a) b = np.random.multinomial(1, a, 1)
我把重要的部分加粗了。如果你忽略了那部分,你提到的问题就会时不时出现。但是如果你把数组的类型改成float64,就不会再出现这个问题了。
9
我在做语言模型工作时也遇到了这个问题。
这个问题的根源在于numpy自动转换数据类型的方式:我的sorfmax()输出的是float32
类型,但numpy.random.multinomial()
会自动把pval
转换成float64
类型。这种数据类型的转换有时会导致pval.sum()
的值超过1.0,因为在计算时会出现数值四舍五入的问题。
这个问题已经被大家注意到,并在这里发布了相关信息。