【问题标题】:Python: How to generate a vector with nonzero entries at random positions?Python:如何在随机位置生成具有非零条目的向量?
【发布时间】:2014-10-15 14:47:17
【问题描述】:

我想使用 Numpy 生成一个 k 稀疏向量,即它有 n 个条目,其中 k 是非零的。非零条目的位置是随机选择的,并且条目本身是从具有零均值和单位方差的高斯分布中选择的。测试向量很小(256 个条目),所以我认为这里不需要 Scipy 的稀疏矩阵接口。

我目前的做法是生成一个介于 0 到 256 之间的 k 个整数的随机列表,初始化一个全零的向量,然后使用 for 循环选择一个随机值并替换具有这些值的向量,如下所示:

# Construct data vector x
# Entries of x are ~N(0, 1) and are placed in the positions specified by the
# 'nonzeros' vector
x = np.zeros((256, 1))

# Get a random value ~N(0, 1) and place it in x at the position specified by
# 'nonzeros' vector
for i in range(k):
    x[nonzeros[i]] = np.random.normal(mu, sigma)

性能在这里不是问题(它与研究相关),所以这很有效,但它感觉 unpythonic,我怀疑有一个更优雅的解决方案。

【问题讨论】:

  • 注意你的随机数是否偶尔会为 0;请参阅 cryptogenomicon.wordpress.com/2014/10/13/… 了解类似的有趣故事。
  • “pythonic”和“numpy-onic”是有区别的。像这样的循环在 Python 中是完全正常的,尽管在合适的时候更喜欢推导式。 numpy 鼓励“矢量化”操作。
  • 你是对的。当我说 pythonic 时,我想我的意思是“矢量化”或“更优雅”。

标签: python numpy


【解决方案1】:

这个怎么样:

In [41]: import numpy as np

In [42]: x = np.zeros(10)

In [43]: positions = np.random.choice(np.arange(10), 3, replace=False)

In [44]: x[positions] = np.random.normal(0,1,3)

In [45]: x
Out[45]: 
array([ 0.        ,  0.11197222,  0.        ,  0.09540939, -0.04488175,
        0.        ,  0.        ,  0.        ,  0.        ,  0.        ])

【讨论】:

    【解决方案2】:

    这里有一个方法:首先用高斯噪声填充零向量的第一个 k 元素,然后随机播放以在随机位置获得这些 k

    >>> n = 10
    >>> k = 3
    >>> a = np.zeros(n)
    >>> a[:k] = np.random.randn(k)
    >>> np.random.shuffle(a)
    >>> a
    array([ 1.26611853,  0.        ,  0.        ,  0.        , -0.84272405,
            0.        ,  0.        ,  1.96992445,  0.        ,  0.        ])
    

    此解决方案可能比公认的解决方案更快:

    >>> def rand_nz_1(n, k):
    ...     a = np.zeros(n)
    ...     pos = np.random.choice(np.arange(n), k, replace=False)
    ...     a[pos] = np.random.randn(k)
    ...     return a
    ... 
    >>> def rand_nz_2(n, k):
    ...     a = np.zeros(n)
    ...     a[:k] = np.random.randn(k)
    ...     np.random.shuffle(a)
    ...     return a
    ... 
    >>> %timeit rand_nz_1(256, 15)
    10000 loops, best of 3: 63.8 µs per loop
    >>> %timeit rand_nz_2(256, 15)
    10000 loops, best of 3: 38.3 µs per loop
    

    【讨论】:

    • @panda-34 我在第一个版本中有一个错误。当我修复它时,我忘了更新输出。现在已经修好了。 (我忘记将k 传递给np.random.randn,所以它只产生了一个数字。)
    【解决方案3】:

    使用random.sample(xrange(n), k) 生成k 随机索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2016-11-15
      • 1970-01-01
      • 2015-08-14
      • 2011-02-24
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多