首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >生成不重复的二进制序列

生成不重复的二进制序列
EN

Code Review用户
提问于 2021-01-12 06:51:34
回答 2查看 384关注 0票数 3

我正在尝试生成只包含0's和1's的序列。我已经编写了以下代码,它可以工作。

代码语言:javascript
运行
复制
import numpy as np

batch = 1000
dim = 32

while 1:
    is_same = False
    seq = np.random.randint(0, 2, [batch, dim])
    for i in range(batch):
        for j in range(i + 1, batch):
            if np.array_equal(seq[i], seq[j]):
                is_same = True
    if is_same:
        continue
    else:
        break

我的batch变量有数千个。上面的循环大约需要30秒才能完成。这是另一个for循环的数据生成部分,它运行大约500个迭代,因此非常慢。是否有更快的方法不重复地生成这个序列列表?谢谢。

期望的结果是一个序列的batch_size数集合,每个序列的长度都是dim,只包含0、S和1s,因此集合中没有两个序列是相同的。

EN

回答 2

Code Review用户

回答已采纳

发布于 2021-01-12 08:19:05

生成所有的序列,然后检查它们是否是唯一的,这是相当昂贵的,正如您注意到的。考虑这一备选办法:

  1. 生成一个序列
  2. 将其转换为元组并将其添加到集合中。
  3. 如果集合大小为batch_size,则返回它,否则转到步骤1

这种方法可以实现如下:

代码语言:javascript
运行
复制
def unique_01_sequences(dim, batch_size):
    sequences = set()
    while len(sequences) != batch_size:
        sequences.add(tuple(np.random.randint(0, 2, dim)))
    return sequences

运行dim=32batch_size=1000的两种解决方案:

代码语言:javascript
运行
复制
Original: 2.296s
Improved: 0.017s

注意:我建议的函数的结果是一组元组,但它可以转换成您喜欢的格式。

其他一些建议和考虑:

  • 功能:考虑将代码封装在一个函数中,这样更容易重用和测试。
  • 退出条件:此部分:如果is_same:继续,否则:中断可以简化为:如果不是is_same:中断
  • 二进制序列与整数序列:可能您知道,但结果是整数的“序列”,而不是标题中所说的二进制序列。
  • 碰撞:对于dimbatch_size的某些配置,建议的方法可能变得非常慢。例如,如果输入是dim=10batch_size=1024,则结果包含10“位”的所有配置,这些配置是0到1023之间数字的二进制表示。在生成过程中,当集合sequences的大小接近1024时,碰撞次数增加,从而减慢了函数的速度。在这些情况下,生成所有配置(作为数字)并对它们进行洗牌将更有效。
  • 边缘大小写:对于dim=10batch_size=1025,函数永远不会结束。考虑验证输入。
票数 3
EN

Code Review用户

发布于 2021-01-12 14:19:04

正如其他答案@Marc中所指出的,生成一个随机样本,然后在有任何重复的情况下将其全部丢弃是非常浪费和缓慢的。相反,您可以使用内置set,也可以使用np.unique。我还会使用稍微快一点的算法,一次生成多个元组,然后去重复,检查丢失了多少元组,然后生成足够多的元组,假设现在存在重复,然后重复它。

代码语言:javascript
运行
复制
def random_bytes_numpy(dim, n):
    nums = np.unique(np.random.randint(0, 2, [n, dim]), axis=1)
    while len(nums) < n:
        nums = np.unique(
            np.stack([nums, np.random.randint(0, 2, [n - len(nums), dim])]),
            axis=1
        )
    return nums

这里有一种使用set的替代方法,但是使用相同的算法,在没有重复的情况下,生成的样本总是完全相同的:

代码语言:javascript
运行
复制
def random_bytes_set(dim, n):
    nums = set()
    while len(nums) < n:
        nums.update(map(tuple, np.random.randint(0, 2, [n - len(nums), dim])))
    return nums

下面是他们在固定batch_size上增加dim=32所需时间的比较,包括@Marc和您的函数:

对于更大的batch_size值,不使用您的算法,因为这需要太长时间:

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/254587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档