在 Scipy 中,为什么 custom.rvs() 具有均匀概率 return 的值仅在开始区域?

In Scipy why does custom.rvs() having uniform probability return the values in the begining region only?

如果我生成一个数组

custom=np.ones(800, dtype=np.float32)

然后使用

从中创建自定义概率分布
custom=normalize(custom)[0]
customPDF = stats.rv_discrete(name='pdfX', values=(np.arange(800), custom))

那如果我用

customPDF.rvs()

我得到的返回值在 0 - 20 范围内,而我期望随机数在 0 到 800 之间变化。

下面的代码给出了我需要的输出,

random.uniform(0,800) 

但是由于需要能够通过改变自定义数组来操纵概率分布,我必须使用 customPDF.rvs()

有解决办法吗?为什么会这样?


In [206]: custom=np.ones(800, dtype=np.float32)

In [207]: custom=normalize(custom)[0]
/usr/local/lib/python3.4/dist-packages/sklearn/utils/validation.py:386: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and willraise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample.
  DeprecationWarning)

In [208]: customPDF = stats.rv_discrete(name='pdfX', values=(np.arange(800), custom))

In [209]: customPDF.rvs()
Out[209]: 7

In [210]: customPDF.rvs()
Out[210]: 13

In [211]: customPDF.rvs()
Out[211]: 15

In [212]: customPDF.rvs()
Out[212]: 3

In [213]: customPDF.rvs()
Out[213]: 8

In [214]: customPDF.rvs()
Out[214]: 10

In [215]: customPDF.rvs()
Out[215]: 10

In [216]: customPDF.rvs()
Out[216]: 11

In [217]: customPDF.rvs()
Out[217]: 15

In [218]: customPDF.rvs()
Out[218]: 6

In [219]: customPDF.rvs()
Out[219]: 7

In [220]: random.uniform(0,800)
Out[220]: 707.0265562968543

问题出在这一行:

custom=normalize(custom)[0]

根据警告,normalize 似乎指的是 sklearn.preprocessing.normalizenormalize 需要一个 [n_samples, n_features] 二维数组——因为你给它一个一维向量,它会插入一个新维度并将其视为一个 [1, n_features] 数组(因此你要索引第 0 个元素输出)。

默认情况下,它会将每行特征的 L2 (Euclidean) norm 调整为等于 1。这 not 与使元素总和为 1 相同:

print(normalize(np.ones(800))[0].sum())
# 28.2843

由于custom的总和远大于1,所以在到达概率向量的末尾之前,绘制特定整数的累积概率达到1:

print(custom.cumsum().searchsorted(1))
# 28

结果是你永远不会画出大于28的整数:

print(customPDF.rvs(size=100000).max())
# 28

为了使 custom 正常化,您应该除以其总和:

custom /= custom.sum()

# or alternatively:
custom = np.repeat(1./800, 800)