我有一个尺寸为[batch_size, input_dim]
的数组,只需要用0
或1
填充即可。我需要每列中的元素都与其余各列不同。我采用了如下方法:
train_data = np.zeros(shape=[batch, input_dim])
num_of_ones = random.sample(range(input_dim + 1), batch)
for k in range(batch):
num_of_one = num_of_ones[k]
for _ in range(num_of_one):
train_data[k][np.random.randint(0, input_dim)] = 1
尽管这保证了不会重复任何元素(由于每个列具有不同数量的1
),但是仍然有许多组合被遗漏了。例如,当num_of_one = 1
时,存在input_dim
种可能性,依此类推。我认为该方法的另一个缺点是batch_size
和input_dim
必须相同(否则random.sample
会引发错误)。我不想列出所有可能的方法,因为这将永远需要完成。
有没有简单的方法可以解决上述问题?
答案 0 :(得分:1)
您可以选择一组介于0和2 ^ {itertools
之间的不同数字(在input_dim
中查看),并使用它们的二进制表示形式来获取每个值的0和1序列。由于选择的数字是不同的,因此它们的二进制表示形式也将是不同的。
答案 1 :(得分:1)
观察从0
到7
的数字的二进制表示形式:
000
001
010
011
100
101
110
111
每行都不一样!因此,我们要做的就是将每一行都转换为列。例如
arr = [
[0, 0, 0, 0, 1, 1, 1, 1],
[0, 0, 1, 1, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 1, 0, 1],
]
此外,请注意我们已经使用了所有独特的可能性。现在,对于3
行,我们无法添加第2**3 + 1
列。
通常,如果cols > 2**rows
,则我们找不到唯一的表示形式。
您可以执行以下操作:
rows = 3
cols = 8
if 2**rows < cols:
print('Not possible')
arr = [[None] * cols for _ in range(rows)]
for col_idx in range(cols):
binary = bin(col_idx)[2:]
binary = binary.zfill(rows)
for row_idx in range(rows):
arr[row_idx][col_idx] = int(binary[row_idx])
for row in arr:
print(row)
时间复杂度:O(rows * cols)
空间复杂度:O(rows * cols)
答案 2 :(得分:1)
您对此行有疑问:
for _ in range(num_of_one):
train_data[k][np.random.randint(0, input_dim)] = 1
由于您选择了要设置为1的随机行,因此可以重复这些行,并且不能保证每列中的行数都正确,因此可以重复。从本质上讲,这并不比将整个数组随机化并希望没有重复项更好。
您可以通过二进制计数的魔术来实现此目的。这些列中的每一列都是不同数字的二进制表示形式。就像任何解决方案一样,这样做有一些局限性,因为不可能有所有唯一的列。
d = np.arange(input_dim)
random.shuffle(d)
train_data = (((d[:,None] & (1 << np.arange(batch)))) > 0).astype(float).T
print( train_data )
答案 3 :(得分:1)
您最好的选择是将np.unpackbits
与python的random.sample
结合使用。 random.sample
将采样而不替换,而不会创建输入列表。这意味着您可以在任意大整数上使用range
对象,只要样本大小适合内存,就不会有问题的风险。 np.unpackbits
然后将整数转换为唯一的位序列。这个想法是@ScottHunter's answer的具体实现。
batch_size = number_of_bits
input_size = number_of_samples
首先,确定您需要生成多少个字节,以及覆盖范围所需的最大整数。请记住,Python支持任意精度的整数,所以请发疯:
bytes_size = np.ceil(batch_size / 8)
max_int = 1<<batch_size
现在获取您的独特样品:
samples = random.sample(range(max_int), input_size)
Python整数是使用to_bytes
方法的完整对象,它将为np.unpackbits
准备样本:
data = np.array([list(x.to_bytes(bytes_size, 'little')) for x in samples], dtype=np.uint8).T
如果batch_size
不是8的倍数,则字节顺序很重要:要修剪最终数组的大小。
现在打开包装,您就可以开始了:
result = np.unpackbits(data, axis=0)[:batch, :]
将所有内容放到一个包中
def random_bit_columns(batch_size, input_size):
samples = random.sample(range(1 << batch_size), input_size)
data = np.array([list(x.to_bytes(np.ceil(batch_size / 8), 'little')) for x in samples], dtype=np.uint8).T
result = np.unpackbits(data, axis=0)[:batch, :]
return result
如果您想利用python的任意精度整数的好处,恐怕我看不出对列数使用列表理解的方法。