【问题标题】:Generate Random Binary Matrix生成随机二进制矩阵
【发布时间】:2015-11-26 04:54:42
【问题描述】:

我希望生成 10,000 个随机二进制矩阵,它们每行和每列的 1 数量与给定的二进制矩阵相同。

矩阵为 ~500 x ~10,000。大约有 2,000,000 个 1。没有零行或列。

我当前的方法是将二进制矩阵转换为二分邻接矩阵,并执行 1,000,000 次随机边缘切换以保证随机性。 1 个矩阵需要 13,000 秒。我在 python 中编码,使用 networkx 的 double_edge_swap 函数的修改版本。

有没有更有效的方法来生成这样的矩阵?

【问题讨论】:

  • 我正在寻找这个问题的名称。这是discrete tomography“处理从水平和垂直线和重建二进制图像”的主要问题,对于二维(成对非平行晶格方向)的情况,问题在 P 中。这会很有趣知道什么需要 10,000 个随机选择的可能重建。
  • 您应该指定是否需要特定的分布,因为不同的方法可能会给出稍微不同的分布。
  • 这取决于您是否只想提高生成矩阵的效率,好的解决方案是调用 c( 从 python 生成矩阵的函数。

标签: python matrix random


【解决方案1】:

试过了,效果很好

np.mod(np.random.permutation(N*N).reshape(N,N),2)

例子:

>>> np.mod(np.random.permutation(4*4).reshape(4,4),2)  
array([[0, 0, 0, 1],
      [1, 1, 1, 0],
      [1, 0, 0, 1],
      [0, 1, 1, 0]])
>>> np.mod(np.random.permutation(4*4).reshape(4,4),2)  
array([[0, 0, 0, 1],
      [1, 1, 0, 0],
      [1, 1, 1, 1],
      [0, 0, 1, 0]])

【讨论】:

    【解决方案2】:

    我觉得你可以先构建这样一个矩阵的特例,然后用numpy.shuffle来洗牌:

    row_sum = 2
    col_sum = 1
    arr     = np.zeros((5, 10))
    #generate a special case, with given row_sum and col_sum
    for i in range(row_sum):
        arr.ravel()[i::arr.shape[1]+row_sum] = 1
    arr
    
    Out[84]: 
    array([[ 1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.]])
    
    np.random.shuffle(arr)
    #np.random.shuffle(arr.T) to shuffle the columns
    arr
    Out[89]: 
    array([[ 0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.],
           [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
           [ 1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])
    
    arr.sum(1) #row sums
    Out[90]: array([ 2.,  2.,  2.,  2.,  2.])
    
    arr.sum(0) #col sums
    Out[91]: array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])
    

    【讨论】:

    • 如果可能的话,我还建议您稍微懒惰。我们可以通过定义一个行号列表(在示例中为[2, 4, 1, 3, 0])生成一个新矩阵,如果应该进行分配,则转到完整的np.array,或者转到某种类型的更改历史(但我不确定numpy 是否可以使用动态大小的数组)。
    • 动态 numpy 数组可能不起作用,在 stackoverflow.com/questions/6950456/… 之前已经讨论过。我想一个可能是FortranC 用于动态数组。但是等等,这不再是一个 lazy 解决方案,:)
    • 如果行是 [6, 5, 6, 4, 6, 7, 4, 5, 4, 4] 而列是 [3, 6, 5, 7, 2, 8 , 3, 3, 4, 10] 而不是常数?即使您有一种解决方案,简单的洗牌也不会总是产生其他解决方案。
    猜你喜欢
    • 2020-08-31
    • 2020-03-16
    • 2022-01-03
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2017-04-30
    • 2016-06-30
    • 2019-10-14
    相关资源
    最近更新 更多