首先,讓我們考慮一個黑盒子,其中m和n是兩個變數(其中m是n的倍數),它輸出一個形狀為(m * n,m * n)的二維矩陣。現在,需要將此 2D 矩陣轉換為形狀為 ( m , m , n , n ) 的 4D 矩陣。我不確定以書面形式描述這一點的最佳方式,但資料的結構方式是在 2D ( m * n )x( m * n ) 矩陣中存在m很多 (n x n ) 每個方向的“瓦片”。考慮一個示例陣列a,在這種情況下,我們有m = 3和n = 2,因此傳入的 2D 矩陣是 6x6:
print(a)
[[0 1 4 5 8 9 ]
[2 3 6 7 10 11]
[12 13 16 17 20 21]
[14 15 18 19 22 23]
[24 25 28 29 32 33]
[26 27 30 31 34 35]]
然后將 this 傳遞給某個函式:
b = some_func(a)
所需的輸出將是 4D 陣列:
print(b)
[[[[ 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 27]]
[[28 29]
[30 31]]
[[32 33]
[34 35]]]]
簡而言之,我們需要在較大的二維陣列中分離出“ n x n ”個圖塊。這種情況的實際含義是我們有m x m矩陣,其中每個條目實際上是一個n x n矩陣,創建一個 4D 矩陣,然后我們可以做以下作業。這是一個高度簡化的示例,用于演示目的,這是一個更復雜的系統,還有很多事情要做。在我的例子中,還有一個額外的軸,m = 256,矩陣中的條目很復雜(64 位),我們非常關注性能,但是這些細節與問題無關。如果它在所有情況下都有幫助n = 2是我們關心的唯一情況,但是我希望有一個更通用的解決方案。
我可以合理地構想出一個使用 for 回圈、索引、模算術等的解決方案,但是這在 Python 中將是非常低效的。
潛在的解決方案?
- 頭腦會立即跳到像 np.reshape() 這樣的東西,但是我們不能簡單地使用 a.reshape(m, m, n, n),因為由于 np.reshape() 首先解開陣列,正如在
uj5u.com熱心網友回復:
我將嘗試說明評論中討論的問題。
一個起始陣列 - 一維陣列的重塑:
In [160]: arr = np.arange(16).reshape(4,4) In [161]: arr Out[161]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) In [162]: arr.ravel() Out[162]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) In [163]: arr.strides Out[163]: (32, 8)進一步重塑為 4d。注意
ravel是一樣的。我還可以arr2.__array_interface__用來顯示資料緩沖區 ID。In [164]: arr1 = arr.reshape(2,2,2,2) In [165]: arr1.ravel() Out[165]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) In [166]: arr1.strides Out[166]: (64, 32, 16, 8)測驗你對步伐變化與形狀變化的理解是一個好主意。
現在交換:
In [167]: arr2 = arr1.swapaxes(1,2) In [168]: arr2 Out[168]: array([[[[ 0, 1], [ 4, 5]], [[ 2, 3], [ 6, 7]]], [[[ 8, 9], [12, 13]], [[10, 11], [14, 15]]]]) In [169]: arr2.strides Out[169]: (64, 16, 32, 8)仍然是 (2,2,2,2) 但步伐已經改變。這也是一種看法。但是對此的重塑(包括拉威爾)將復制。元素已重新排序:
In [170]: arr2.ravel() Out[170]: array([ 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15]) In [171]: arr3 = arr2.reshape(4,4) In [172]: arr3 Out[172]: array([[ 0, 1, 4, 5], [ 2, 3, 6, 7], [ 8, 9, 12, 13], [10, 11, 14, 15]]) In [173]: arr3.ravel() Out[173]: array([ 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15])我們在更簡單的 2d 轉置中看到了相同的步幅變化:
In [174]: arr4 = arr.T In [175]: arr4.strides Out[175]: (8, 32) In [176]: arr4.ravel() Out[176]: array([ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15])我們可以
view通過指定“F”列的順序來進行解構。雖然這可能對理解沒有幫助。秩序不容易擴展到更高的維度,但跨步可以。In [177]: arr4.ravel(order='F') Out[177]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])uj5u.com熱心網友回復:
我不確定這是否比 hpaulj 答案更好/更快,我想在性能上會相似。請在大陣列上檢查自己
a.reshape((m, m * n * n)).reshape(m, n, m * n).transpose(0, 2, 1).reshape(m, m, n, n).transpose(0, 1, 3, 2)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/414379.html標籤:
