Użyj widoku i uzyskaj bezpłatne środowisko uruchomieniowe! Rozszerz n-dimtablice ogólne don+1-dim
Wprowadzone w NumPy1.10.0 , możemy wykorzystać, numpy.broadcast_toaby po prostu wygenerować 3Dwidok w 2Dtablicy wejściowej. Korzyścią byłoby brak dodatkowego obciążenia pamięci i praktycznie wolne środowisko wykonawcze. Byłoby to istotne w przypadkach, gdy tablice są duże i możemy pracować z widokami. Działa to również w n-dimprzypadku ogólnych przypadków.
Użyłbym tego słowa stackzamiast copy, ponieważ czytelnicy mogliby pomylić je z kopiowaniem tablic, które tworzą kopie pamięci.
Stos wzdłuż pierwszej osi
Jeśli chcemy ułożyć dane wejściowe arrwzdłuż pierwszej osi, rozwiązaniem np.broadcast_todo utworzenia 3Dwidoku byłoby -
np.broadcast_to(arr,(3,)+arr.shape) # N = 3 here
Stos wzdłuż trzeciej / ostatniej osi
Aby ułożyć dane wejściowe arrwzdłuż trzeciej osi, rozwiązaniem do utworzenia 3Dwidoku byłoby -
np.broadcast_to(arr[...,None],arr.shape+(3,))
Jeśli faktycznie potrzebujemy kopii pamięci, zawsze możemy ją .copy()tam dołączyć . W związku z tym rozwiązania byłyby:
np.broadcast_to(arr,(3,)+arr.shape).copy()
np.broadcast_to(arr[...,None],arr.shape+(3,)).copy()
Oto jak działa układanie w stos dla dwóch przypadków, pokazane wraz z informacjami o ich kształcie dla przykładowej sprawy -
# Create a sample input array of shape (4,5)
In [55]: arr = np.random.rand(4,5)
# Stack along first axis
In [56]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[56]: (3, 4, 5)
# Stack along third axis
In [57]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[57]: (4, 5, 3)
Te same rozwiązania działałyby, gdyby rozszerzyć dane n-dimwejściowe, aby n+1-dimwyświetlić dane wyjściowe wzdłuż pierwszej i ostatniej osi. Zbadajmy kilka bardziej ciemnych przypadków -
Obudowa wejściowa 3D:
In [58]: arr = np.random.rand(4,5,6)
# Stack along first axis
In [59]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[59]: (3, 4, 5, 6)
# Stack along last axis
In [60]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[60]: (4, 5, 6, 3)
Obudowa wejściowa 4D:
In [61]: arr = np.random.rand(4,5,6,7)
# Stack along first axis
In [62]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[62]: (3, 4, 5, 6, 7)
# Stack along last axis
In [63]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[63]: (4, 5, 6, 7, 3)
i tak dalej.
Czasy
Wykorzystajmy duży przykładowy 2Dprzypadek, pobierzmy czasy i sprawdźmy, czy wyjście jest plikiem view.
# Sample input array
In [19]: arr = np.random.rand(1000,1000)
Udowodnijmy, że proponowane rozwiązanie jest rzeczywiście poglądem. Użyjemy układania wzdłuż pierwszej osi (wyniki byłyby bardzo podobne do układania wzdłuż trzeciej osi) -
In [22]: np.shares_memory(arr, np.broadcast_to(arr,(3,)+arr.shape))
Out[22]: True
Sprawdźmy czasy, aby pokazać, że jest to praktycznie bezpłatne -
In [20]: %timeit np.broadcast_to(arr,(3,)+arr.shape)
100000 loops, best of 3: 3.56 µs per loop
In [21]: %timeit np.broadcast_to(arr,(3000,)+arr.shape)
100000 loops, best of 3: 3.51 µs per loop
Będąc widokiem, zwiększając się Nz 3do 3000niczego nie zmienia się w czasie i oba są pomijalne w jednostkach czasowych. Dlatego wydajne zarówno pod względem pamięci, jak i wydajności!
b[:,:,0],b[:,:,1]ib[:,:,2]. Każdy trzeci wycinek wymiaru jest kopią oryginalnej szyku 2D. Nie jest to takie oczywiste samo patrzenieprint(b).