【问题标题】:Julia - Reshaping a 4D array into a matrix of matricesJulia - 将 4D 数组重塑为矩阵矩阵
【发布时间】:2023-01-25 00:19:11
【问题描述】:

我想从一个数组开始 A = zeros( nK , nK , m , m ) 并将其重塑为大小为(nK,nK) 的矩阵,其中每个元素都是一个mxm 矩阵。

我已经尝试了基础reshape 函数,reshape(A , nK , nK ),但它给了我

DimensionMismatch("new dimensions (nK, nK) must be consistent with array size mxmxnKxnK")

【问题讨论】:

  • 数组中的第一个维度移动最快,即 A[:,i,j,k] 的元素在内存中聚集在一起。因此,将A 转换为nKxnK 元素的mxm 矩阵是有意义的。

标签: arrays matrix multidimensional-array julia reshape


【解决方案1】:

如果我正确理解你的问题,我想你可以这样做:

julia> x = rand(1:10, 2, 4, 3, 3)
2×4×3×3 Array{Int64, 4}:
[:, :, 1, 1] =
 9  5  4   1
 2  2  2  10

[:, :, 2, 1] =
 8  1  4  9
 9  5  5  8

...

julia> # With copy:

julia> [x[i, j, :, :] for i in axes(x, 1), j in axes(x, 2)]
2×4 Matrix{Matrix{Int64}}:
 [9 5 4; 8 2 6; 5 7 5]  [5 8 5; 1 6 1; 1 5 5]   [4 10 4; 4 3 10; 4 7 10]  [1 10 5; 9 2 5; 7 1 10]
 [2 7 1; 9 5 3; 7 1 7]  [2 3 9; 5 7 10; 4 1 4]  [2 1 2; 5 1 1; 1 2 4]     [10 1 3; 8 3 8; 9 10 2]

julia> # With views:

julia> [view(x, i, j, :, :) for i in axes(x, 1), j in axes(x, 2)]
2×4 Matrix{SubArray{Int64, 2, Array{Int64, 4}, Tuple{Int64, Int64, Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}}, true}}:
 [9 5 4; 8 2 6; 5 7 5]  [5 8 5; 1 6 1; 1 5 5]   [4 10 4; 4 3 10; 4 7 10]  [1 10 5; 9 2 5; 7 1 10]
 [2 7 1; 9 5 3; 7 1 7]  [2 3 9; 5 7 10; 4 1 4]  [2 1 2; 5 1 1; 1 2 4]     [10 1 3; 8 3 8; 9 10 2]

我希望它能帮助你。

【讨论】:

  • 谢谢!只是想知道 - 有没有办法在没有 for 循环的情况下做到这一点?
【解决方案2】:

这不回答 OP 问题,而是将 A 转换为大小为 m x m 的矩阵的相关问题,其中每个元素都是大小为 nk x nk 的矩阵(问题所问的“渐开线”)。这可以高效地完成,因为数组的内存排列为第一个索引随相邻的内存位置而变化(然后是下一个索引,依此类推)。

例如:一个4 x 2矩阵M在内存中组织:

M[1,1] M[2,1] M[3,1] M[4,1] M[1,2] M[2,2] M[3,2] M[4,2]

此答案中的方法使用两个包:StaticArraysMappedArrays,熟悉它们会很好。代码:

using StaticArrays, MappedArrays

A = rand(1:10, 2, 4, 3, 3)
B = mappedarray(x->SMatrix{2, 4, Int, 8}(x),
  reinterpret(reshape, NTuple{4*2, Int}, reshape(A, (4*2, 3, 3))))

现在以下工作:

julia> B[1,1]
2×4 SMatrix{2, 4, Int64, 8} with indices SOneTo(2)×SOneTo(4):
 4  7  1  2
 9  9  1  1

请注意,使用 SMatrix 是必要的,因为与常规 Julia Arrays 相比,内部矩阵的大小已知且固定。

此外,这是有效的:

julia> using BenchmarkTools

julia> @btime $B[2,3]
  10.645 ns (0 allocations: 0 bytes)
2×4 SMatrix{2, 4, Int64, 8} with indices SOneTo(2)×SOneTo(4):
 8   4  10  5
 3  10   8  2

【讨论】:

    猜你喜欢
    • 2020-03-19
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多