簡體   English   中英

Numpy View重塑沒有復制(2d移動/滑動窗口,跨步,蒙面內存結構)

[英]Numpy View Reshape Without Copy (2d Moving/Sliding Window, Strides, Masked Memory Structures)

我有一個圖像存儲為2d numpy數組(可能是multi-d)。

我可以在反射2d滑動窗口的數組上進行視圖,但是當我重塑它以使每行都是一個平坦的窗口(行是窗口,列是該窗口中的一個像素)時,python會生成一個完整的副本。 它這樣做是因為我使用了典型的步幅技巧,並且新形狀在內存中不連續。

我需要這個,因為我將整個大圖像傳遞給sklearn分類器,該分類器接受2d矩陣,其中沒有批處理/部分擬合程序,並且完整的擴展副本對於存儲器來說太大了。

我的問題:如果沒有完整地復制視圖,有沒有辦法做到這一點?

我相信一個答案將是(1)關於我忽略的步幅或numpy內存管理,或者(2)python的某種屏蔽內存結構,它可以模擬一個numpy數組,甚至包括像sklearn這樣的外部包用Cython。

這種在內存中移動二維圖像窗口的訓練任務很常見,但我所知道的唯一一個直接考慮補丁的嘗試是Vigra項目( http://ukoethe.github.io/vigra/ )。

謝謝您的幫助。

>>> A=np.arange(9).reshape(3,3)
>>> print A
[[0 1 2]
 [3 4 5]
 [6 7 8]]
>>> xstep=1;ystep=1; xsize=2; ysize=2
>>> window_view = np.lib.stride_tricks.as_strided(A, ((A.shape[0] - xsize + 1) / xstep, (A.shape[1] - ysize + 1) / ystep, xsize, ysize),
...       (A.strides[0] * xstep, A.strides[1] * ystep, A.strides[0], A.strides[1]))
>>> print window_view 
[[[[0 1]
   [3 4]]

  [[1 2]
   [4 5]]]


 [[[3 4]
   [6 7]]

  [[4 5]
   [7 8]]]]
>>> 
>>> np.may_share_memory(A,window_view)
True
>>> B=window_view.reshape(-1,xsize*ysize)
>>> np.may_share_memory(A,B)
False

僅使用步幅不可能完成任務,但NumPy確實支持一種完成工作的數組。 使用masked_arraymasked_array您可以為數據創建所需的視圖。 但是,並非所有NumPy函數都支持使用masked_array操作,因此scikit-learn可能也不能很好地處理這些操作。

讓我們首先重新審視一下我們在這里要做的事情。 考慮您的示例的輸入數據。 從根本上說,數據只是內存中的一維數組,如果我們考慮這方面的進步,它就更簡單了。 該數組似乎只是2-d,因為我們已經定義了它的形狀。 使用步幅,形狀可以這樣定義:

from numpy.lib.stride_tricks import as_strided

base = np.arange(9)
isize = base.itemsize
A = as_strided(base, shape=(3, 3), strides=(3 * isize, isize))

現在的目標是設置這樣的進展,以base在於它命令數字像端陣列,在B 換句話說,我們要求整數ab這樣

>>> as_strided(base, shape=(4, 4), strides=(a, b))
array([[0, 1, 3, 4],
       [1, 2, 4, 5],
       [3, 4, 6, 7],
       [4, 5, 7, 8]])

但這顯然是不可能的。 就可以達到這樣的最接近的觀點與在滾動窗口base

>>> C = as_strided(base, shape=(5, 5), strides=(isize, isize))
>>> C
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])

但這里的區別在於我們有額外的列和行,我們想要擺脫它們。 所以,實際上我們要求的是一個不連續的滾動窗口,並且還會定期跳轉。 在這個例子中,我們希望從窗口中排除每三個項目,並在兩行之后跳過一個項目。

我們可以將其描述為masked_array

>>> mask = np.zeros((5, 5), dtype=bool)
>>> mask[2, :] = True
>>> mask[:, 2] = True
>>> D = np.ma.masked_array(C, mask=mask)

此數組包含我們想要的數據,它只是原始數據的視圖。 我們可以確認數據是否相等

>>> D.data[~D.mask].reshape(4, 4)
array([[0, 1, 3, 4],
       [1, 2, 4, 5],
       [3, 4, 6, 7],
       [4, 5, 7, 8]])

但正如我在開始時所說,scikit-learn很可能不了解蒙面數組。 如果它只是將其轉換為數組,則數據將是錯誤的:

>>> np.array(D)
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM