我如何通过合并元素来减少我的4-d数组的形状到3-d ?



我有形状为1bit的(3,32,32,32)的4-d数组,我想将其减少到(3,32,32),元素变为32位。数组中的值是0和1。数组中的编号只是一种可视化我的问题的方式,它代表了我想要的32位的结果段的nth位。

[[[[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
...,
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.]],
[[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
...,
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],
[[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
...,
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],
...,
[[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
...,
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.]],
[[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
...,
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.]],
[[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
...,
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.]]], #1

[[[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
...,
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.]],
[[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
...,
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],
[[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
...,
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],
...,
[[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
...,
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.]],
[[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
...,
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.]],
[[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
...,
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.]]], #2

[[[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
...,
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.],
[ 0.,  0.,  0.,  ...,  0.,  0.,  0.]],
[[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
...,
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
[ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],
[[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
...,
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
[ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],
...,
[[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
...,
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.],
[29., 29., 29.,  ..., 29., 29., 29.]],
[[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
...,
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.],
[30., 30., 30.,  ..., 30., 30., 30.]],
[[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
...,
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.],
[31., 31., 31.,  ..., 31., 31., 31.]]]] #3

很抱歉,如果这是一个如此明显的问题,因为我还在学习。

我希望我的结果数组的大小为(3,32,32)与以下安排:

[[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
..., 
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]], #1

[[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
..., 
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]], #2

[[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
..., 
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]]] #3



最快的方法,我认为(也是最短的一个写,虽然不理解,如果你不习惯这个函数)可能是使用einsum

import numpy as np
# Just for the example, I build it backward
x = np.random.randint(0,2000000000, (3, 32, 32))
# So x is the result we expect to find. 
# Let build the 3,32,32,32 array of 1/0
bits = np.stack([(x//(2**k))%2 for k in range(32)], axis=1)
# So now, what we want is to create x back from bits
# For that we need a array of multiplicators
coef = np.array([2**k for k in range(32)])
# And now the magic one liner
xx=np.einsum('ijkl,j', bits, coef)
# And the test to check if we found back x
np.abs(xx-x).max()
# 0 

一行是np.einsum('ijkl,j', bits, [2**k for k in range(32)])

这里使用的einsum意味着迭代i, j, k, l的所有可能值(所以4个嵌套循环,但在numpy中有效地完成)。无论如何,您需要读取所有值,因此这是操作数量方面的最小值)。沿着重复索引(这里是j),结果是两个数组中值的乘积的和。这里,ijkl,j表示

res=np.empty((3,32,32))
for i in range(3):
for k in range(32):
for l in range(32):
res[i,k,l] = 0 
for j in range(32):
res[i,k,l] += bits[i,j,k,l]*coef[j]

但是非常非常快。一般来说,你无法打败np.einsum

(注意:我不确定从你的角度来看哪位是最重要的。您可能需要还原coef。例如,通过将coef[::-1]传递给einsum)

最新更新