我必须采用一个随机的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/

10-12 15:54