Mungkin cara terbersih adalah dengan menggunakan np.repeat
:
a = np.array([[1, 2], [1, 2]])
print(a.shape)
# (2, 2)
# indexing with np.newaxis inserts a new 3rd dimension, which we then repeat the
# array along, (you can achieve the same effect by indexing with None, see below)
b = np.repeat(a[:, :, np.newaxis], 3, axis=2)
print(b.shape)
# (2, 2, 3)
print(b[:, :, 0])
# [[1 2]
# [1 2]]
print(b[:, :, 1])
# [[1 2]
# [1 2]]
print(b[:, :, 2])
# [[1 2]
# [1 2]]
Karena itu, Anda sering dapat menghindari pengulangan array Anda sama sekali dengan menggunakan penyiaran . Misalnya, saya ingin menambahkan (3,)
vektor:
c = np.array([1, 2, 3])
kepada a
. Saya dapat menyalin konten sebanyak a
3 kali di dimensi ketiga, lalu menyalin konten c
dua kali di dimensi pertama dan kedua, sehingga kedua array saya (2, 2, 3)
, lalu menghitung jumlahnya. Namun, jauh lebih sederhana dan lebih cepat untuk melakukan ini:
d = a[..., None] + c[None, None, :]
Di sini, a[..., None]
memiliki bentuk (2, 2, 1)
dan c[None, None, :]
bentuk (1, 1, 3)
*. Ketika saya menghitung jumlahnya, hasilnya 'disiarkan' sepanjang dimensi ukuran 1, memberi saya hasil bentuk (2, 2, 3)
:
print(d.shape)
# (2, 2, 3)
print(d[..., 0]) # a + c[0]
# [[2 3]
# [2 3]]
print(d[..., 1]) # a + c[1]
# [[3 4]
# [3 4]]
print(d[..., 2]) # a + c[2]
# [[4 5]
# [4 5]]
Penyiaran adalah teknik yang sangat ampuh karena menghindari overhead tambahan yang terlibat dalam pembuatan salinan berulang dari larik input Anda dalam memori.
* Meskipun saya memasukkannya untuk kejelasan, None
indeks ke dalam c
sebenarnya tidak diperlukan - Anda juga bisa melakukannya a[..., None] + c
, yaitu menyiarkan (2, 2, 1)
array terhadap (3,)
array. Ini karena jika salah satu array memiliki dimensi yang lebih sedikit daripada yang lain maka hanya dimensi trailing dari dua array yang perlu kompatibel. Untuk memberikan contoh yang lebih rumit:
a = np.ones((6, 1, 4, 3, 1)) # 6 x 1 x 4 x 3 x 1
b = np.ones((5, 1, 3, 2)) # 5 x 1 x 3 x 2
result = a + b # 6 x 5 x 4 x 3 x 2
b[:,:,0]
,b[:,:,1]
danb[:,:,2]
. Setiap potongan dimensi ketiga adalah salinan dari larik 2D asli. Ini tidak begitu jelas hanya dengan melihatprint(b)
.np.newaxis
hanyalah alias dariNone
Cara lain adalah dengan menggunakan
numpy.dstack
. Misalkan Anda ingin mengulang waktu matriksa
num_repeats
:Triknya adalah dengan membungkus matriks
a
ke dalam daftar satu elemen, kemudian menggunakan*
operator untuk menduplikasi elemen dalamnum_repeats
waktu daftar ini .Misalnya, jika:
Ini mengulangi larik sebanyak
[1 2; 1 2]
5 kali di dimensi ketiga. Untuk memverifikasi (di IPython):Pada akhirnya kita bisa melihat bahwa bentuk matriksnya adalah
2 x 2
, dengan 5 irisan pada dimensi ketiga.sumber
reshape
? Lebih cepat? memberikan struktur yang sama? Ini pasti lebih rapi.Gunakan tampilan dan dapatkan runtime gratis! Perluas
n-dim
larik generik ken+1-dim
Diperkenalkan di NumPy
1.10.0
, kita dapat memanfaatkannumpy.broadcast_to
untuk menghasilkan3D
tampilan ke dalam2D
larik input. Manfaatnya tidak akan ada overhead memori tambahan dan runtime yang hampir bebas. Ini akan menjadi penting dalam kasus di mana array besar dan kami baik-baik saja untuk bekerja dengan view. Juga, ini akan bekerja dengann-dim
kasus umum .Saya akan menggunakan kata tersebut
stack
sebagai pengganticopy
, karena pembaca mungkin bingung dengan menyalin array yang membuat salinan memori.Tumpuk di sepanjang sumbu pertama
Jika kita ingin menumpuk input di
arr
sepanjang sumbu pertama, solusi dengannp.broadcast_to
membuat3D
tampilan adalah -Tumpuk di sepanjang sumbu ketiga / terakhir
Untuk menumpuk input di
arr
sepanjang sumbu ketiga, solusi untuk membuat3D
tampilan adalah -Jika kita benar-benar membutuhkan salinan memori, kita selalu dapat menambahkannya di
.copy()
sana. Oleh karena itu, solusinya adalah -Berikut cara kerja penumpukan untuk dua kasing, yang ditunjukkan dengan informasi bentuknya untuk contoh kasing -
Solusi yang sama akan bekerja untuk memperluas
n-dim
masukan untukn+1-dim
melihat keluaran sepanjang sumbu pertama dan terakhir. Mari jelajahi beberapa casing redup yang lebih tinggi -Kasus masukan 3D:
Kasus masukan 4D:
dan seterusnya.
Pengaturan waktu
Mari gunakan contoh
2D
kasus yang besar dan dapatkan pengaturan waktu dan verifikasi keluaran menjadi aview
.Mari kita buktikan bahwa solusi yang diusulkan memang sebuah pandangan. Kami akan menggunakan penumpukan di sepanjang sumbu pertama (hasilnya akan sangat mirip untuk penumpukan di sepanjang sumbu ketiga) -
Mari kita dapatkan pengaturan waktu untuk menunjukkan bahwa ini hampir gratis -
Sebagai tampilan, meningkat
N
dari3
menjadi3000
tidak mengubah apa pun pada pengaturan waktu dan keduanya dapat diabaikan pada unit pengaturan waktu. Karenanya, efisien baik dalam memori dan kinerja!sumber
Edit @ Mr. F, untuk menjaga urutan dimensi:
sumber
B.shape
mencetak(N, 2, 2)
untuk nilai berapapunN
. Jika Anda transposB
denganB.T
maka sesuai dengan output yang diharapkan.B[0], B[1],...
akan memberi Anda bagian yang tepat, yang menurut saya akan lebih mudah untukB[:,:,0], B[:,:,1]
B[:,:,i]
dan itulah yang biasa saya lakukan.Berikut adalah contoh penyiaran yang melakukan persis seperti yang diminta.
Maka
b*a
adalah hasil yang diinginkan dan(b*a)[:,:,0]
menghasilkanarray([[1, 2],[1, 2]])
, yang aslia
, seperti halnya(b*a)[:,:,1]
, dllsumber
Ini sekarang juga bisa dicapai menggunakan np.tile sebagai berikut:
sumber