Julia - 将一个4维数组转换为矩阵的矩阵

3
我想从一个数组开始,如A = zeros(nK,nK,m,m),并将其重塑为大小为(nK,nK)的矩阵,其中每个元素都是一个mxm矩阵。
我尝试过使用基本的reshape函数,reshape(A,nK,nK),但是它给了我一个错误提示: DimensionMismatch("新维度(nK, nK)必须与数组大小mxmxnKxnK一致")

3
数组中的第一维是最快移动的,即A[:,i,j,k]的元素在内存中紧密排列。因此,将A转换为一个nKxnK元素的mxm矩阵是有意义的。 - Dan Getz
2个回答

4
在 Julia 1.9 中,您需要使用 eachslice
julia> x = rand(Int8,3,3,2,2)
3×3×2×2 Array{Int8, 4}:
[:, :, 1, 1] =
 127  107   27
  31  -90   95
 -50  -92  117
...

julia> eachslice(x; dims=(3,4))
2×2 Slices{Array{Int8, 4}, Tuple{Colon, Colon, Int64, Int64}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, SubArray{Int8, 2, Array{Int8, 4}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64, Int64}, true}, 2}:
 [127 107 27; 31 -90 95; -50 -92 117]  [-58 7 -16; -77 -110 32; -82 25 -48]
 [-40 13 -43; -63 121 47; 28 -64 57]   [62 -61 19; 117 42 101; 70 -82 -62]

julia> eachslice(x; dims=(1,2))
3×3 Slices{Array{Int8, 4}, Tuple{Int64, Int64, Colon, Colon}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, SubArray{Int8, 2, Array{Int8, 4}, Tuple{Int64, Int64, Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}}, true}, 2}:
 [127 -58; -40 62]  [107 7; 13 -61]     [27 -16; -43 19]
 [31 -77; -63 117]  [-90 -110; 121 42]  [95 32; 47 101]
 [-50 -82; 28 70]   [-92 25; -64 -82]   [117 -48; 57 -62]

如上所述,通常最好使用包含前导维度的切片,例如eachslice(x; dims=(3,4))产生的x[:,:,i,j]
在Julia 1.8及以下版本中,理想情况下,Compat.jl#663将使此功能正常工作。

2

如果我正确理解您的问题,我认为您可以这样做:

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]

希望这对你有所帮助。


1
谢谢!只是想知道 - 有没有一种方法可以不用for循环来实现这个? - Sreekar Voleti
1
@SreekarVoleti,你可以使用map函数,如下所示:map(j->map(i->x[j,i,:,:],axes(x,2)),axes(x,1)) - Vass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接