我必须采用一个随机的50x50x50整数数组,并确定其中的哪个连续3x3x3多维数据集具有最大的总和。
除非将较小的多维数据集均匀地分成较大的多维数据集,否则Numpy中的许多拆分功能似乎无法正常工作。尝试通过思考过程,我制作了一个48x48x48的多维数据集,其大小从1到110,592。然后,我考虑使用以下代码将其重塑为4D数组,并评估哪个数组的总和最大?当我输入此代码时,尽管它以不理想的顺序拆分数组。我希望第一个数组是3x3x3多维数据集,该多维数据集应该位于48x48x48多维数据集的角落。我可以添加某种语法来实现这一点吗?
import numpy as np
arr1 = np.arange(0,110592)
arr2=np.reshape(arr1, (48,48,48))
arr3 = np.reshape(arr2, (4096, 3,3,3))
arr3
输出:
array([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[ 12, 13, 14],
[ 15, 16, 17]],
[[ 18, 19, 20],
[ 21, 22, 23],
[ 24, 25, 26]]],
所需的输出:
array([[[[ 0, 1, 2],
[ 48, 49, 50],
[ 96, 97, 98]],
等
最佳答案
解
There's a live version of this solution online you can try for yourself
对于您最初的问题有一个简单的(某种)解决方案,即在50x50x50的多维数据集中找到最大的3x3x3子多维数据集,该子多维数据集基于更改输入数组的步幅。该解决方案是完全矢量化的(意味着没有循环),因此应该从Numpy中获得最佳性能:
import numpy as np
def cubecube(arr, cshape):
strides = (*arr.strides, *arr.strides)
shape = (*np.array(arr.shape) - cshape + 1, *cshape)
return np.lib.stride_tricks.as_strided(arr, shape=shape, strides=strides)
def maxcube(arr, cshape):
cc = cubecube(arr, cshape)
ccsums = cc.sum(axis=tuple(range(-arr.ndim, 0)))
ix = np.unravel_index(np.argmax(ccsums), ccsums.shape)[:arr.ndim]
return ix, cc[ix]
maxcube
函数采用数组和子多维数据集的形状,并返回(first-index-of-largest-cube, largest-cube)
的元组。这是有关如何使用maxcube
的示例:shape = (50, 50, 50)
cshape = (3, 3, 3)
# set up a 50x50x50 array
arr = np.arange(np.prod(shape)).reshape(*shape)
# set one of the subcubes as the largest
arr[37, 26, 11] = 999999
ix, cube = maxcube(arr, cshape)
print('first index of largest cube: {}'.format(ix))
print('largest cube:\n{}'.format(cube))
输出:
first index of largest cube: (37, 26, 11)
largest cube:
[[[999999 93812 93813]
[ 93861 93862 93863]
[ 93911 93912 93913]]
[[ 96311 96312 96313]
[ 96361 96362 96363]
[ 96411 96412 96413]]
[[ 98811 98812 98813]
[ 98861 98862 98863]
[ 98911 98912 98913]]]
深入解释
多维数据集
您拥有的是48x48x48的多维数据集,但是您想要的是一个较小的多维数据集的多维数据集。可以通过改变步幅将其转换为另一个。对于dtype
int64
的48x48x48数组,步幅最初将设置为(48*48*8, 48*8, 8)
。每个不重叠的3x3x3子多维数据集的第一个值都可以以(3*48*48*8, 3*48*8, 3*8)
的步长进行迭代。结合这些步幅以获得多维数据集的步幅:# Set up a 48x48x48 array, like in OP's example
arr = np.arange(48**3).reshape(48,48,48)
shape = (16,16,16,3,3,3)
strides = (3*48*48*8, 3*48*8, 3*8, 48*48*8, 48*8, 8)
# restride into a 16x16x16 array of 3x3x3 cubes
arr2 = np.lib.stride_tricks.as_strided(arr, shape=shape, strides=strides)
arr2
是形状为arr
的(16,16,16,3,3,3)
的视图(表示它们共享数据,因此无需复制)。可以通过将索引传递给ijk
来访问arr
中的arr2
第3x3多维数据集:i,j,k = 0,0,0
print(arr2[i,j,k])
输出:
[[[ 0 1 2]
[ 48 49 50]
[ 96 97 98]]
[[2304 2305 2306]
[2352 2353 2354]
[2400 2401 2402]]
[[4608 4609 4610]
[4656 4657 4658]
[4704 4705 4706]]]
您可以通过对内轴求和来获得所有子立方体的和:
sumOfSubcubes = arr2.sum(3,4,5)
这将产生一个16x16x16数组,其中每个值都是原始数组中不重叠的3x3x3子多维数据集的总和。这解决了OP询问的有关48x48x48阵列的特定问题。像上面的
cubecube
函数一样,重排也可以用于查找所有重叠的3x3x3多维数据集。关于python - 需要使用Numpy评估较大的3D阵列中的较小的3D阵列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53459647/