Sederhananya, torch.Tensor.view()
yang terinspirasi oleh numpy.ndarray.reshape()
atau numpy.reshape()
, menciptakan tampilan tensor baru, selama bentuk baru tersebut kompatibel dengan bentuk tensor asli.
Mari kita pahami ini secara detail dengan menggunakan contoh nyata.
In [43]: t = torch.arange(18)
In [44]: t
Out[44]:
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17])
Dengan tensor ini t
bentuk (18,)
, baru dilihat dapat hanya dibuat untuk bentuk berikut:
(1, 18)
atau ekuivalen (1, -1)
atau atau setara atau atau ekuivalen atau atau ekuivalen atau atau ekuivalen atau atau ekuivalen atau(-1, 18)
(2, 9)
(2, -1)
(-1, 9)
(3, 6)
(3, -1)
(-1, 6)
(6, 3)
(6, -1)
(-1, 3)
(9, 2)
(9, -1)
(-1, 2)
(18, 1)
(18, -1)
(-1, 1)
Seperti yang sudah dapat kita amati dari bentuk tuple di atas, penggandaan elemen-elemen dari tuple bentuk (misalnya 2*9
, 3*6
dll.) Harus selalu sama dengan jumlah total elemen dalam tensor asli (18
dalam contoh kita).
Hal lain yang perlu diperhatikan adalah bahwa kami menggunakan a -1
di salah satu tempat di masing-masing bentuk tuple. Dengan menggunakan -1
, kita menjadi malas dalam melakukan perhitungan diri kita sendiri dan agak mendelegasikan tugas untuk PyTorch untuk melakukan perhitungan yang nilai untuk bentuk ketika ia menciptakan baru tampilan . Satu hal penting yang perlu diperhatikan adalah kita hanya bisa menggunakan satu -1
tuple dalam bentuk. Nilai yang tersisa harus diberikan secara eksplisit oleh kami. Lain PyTorch akan mengeluh dengan melemparkan RuntimeError
:
RuntimeError: hanya satu dimensi yang dapat disimpulkan
Jadi, dengan semua bentuk yang disebutkan di atas, PyTorch akan selalu mengembalikan tampilan baru dari tensor aslit
. Ini pada dasarnya berarti bahwa itu hanya mengubah informasi langkah tensor untuk setiap tampilan baru yang diminta.
Di bawah ini adalah beberapa contoh yang menggambarkan bagaimana langkah tensor diubah dengan setiap tampilan baru .
# stride of our original tensor `t`
In [53]: t.stride()
Out[53]: (1,)
Sekarang, kita akan melihat langkah untuk tampilan baru :
# shape (1, 18)
In [54]: t1 = t.view(1, -1)
# stride tensor `t1` with shape (1, 18)
In [55]: t1.stride()
Out[55]: (18, 1)
# shape (2, 9)
In [56]: t2 = t.view(2, -1)
# stride of tensor `t2` with shape (2, 9)
In [57]: t2.stride()
Out[57]: (9, 1)
# shape (3, 6)
In [59]: t3 = t.view(3, -1)
# stride of tensor `t3` with shape (3, 6)
In [60]: t3.stride()
Out[60]: (6, 1)
# shape (6, 3)
In [62]: t4 = t.view(6,-1)
# stride of tensor `t4` with shape (6, 3)
In [63]: t4.stride()
Out[63]: (3, 1)
# shape (9, 2)
In [65]: t5 = t.view(9, -1)
# stride of tensor `t5` with shape (9, 2)
In [66]: t5.stride()
Out[66]: (2, 1)
# shape (18, 1)
In [68]: t6 = t.view(18, -1)
# stride of tensor `t6` with shape (18, 1)
In [69]: t6.stride()
Out[69]: (1, 1)
Jadi itulah keajaiban view()
fungsinya. Itu hanya mengubah langkah dari tensor (asli) untuk masing-masing tampilan baru , selama bentuk tampilan baru kompatibel dengan bentuk aslinya.
Hal lain yang satu yang menarik bisa mengamati dari tupel langkah adalah bahwa nilai dari elemen dalam 0 th posisi sama dengan nilai dari elemen dalam 1 st posisi tuple bentuk.
In [74]: t3.shape
Out[74]: torch.Size([3, 6])
|
In [75]: t3.stride() |
Out[75]: (6, 1) |
|_____________|
Hal ini karena:
In [76]: t3
Out[76]:
tensor([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17]])
langkahnya (6, 1)
mengatakan bahwa untuk beralih dari satu elemen ke elemen berikutnya sepanjang dimensi ke- 0 , kita harus melompat atau mengambil 6 langkah. (yaitu untuk pergi dari 0
ke 6
, kita harus mengambil 6 langkah.) Tapi untuk pergi dari satu elemen ke elemen berikutnya dalam 1 st dimensi, kita hanya perlu satu langkah (untuk misalnya untuk pergi dari 2
ke 3
).
Dengan demikian, informasi langkah adalah inti dari bagaimana elemen diakses dari memori untuk melakukan perhitungan.
Fungsi ini akan mengembalikan tampilan dan persis sama dengan menggunakan torch.Tensor.view()
selama bentuk baru tersebut kompatibel dengan bentuk tensor asli. Jika tidak, itu akan mengembalikan salinan.
Namun, catatan torch.reshape()
memperingatkan bahwa:
input dan input yang bersebelahan dengan langkah yang kompatibel dapat dibentuk kembali tanpa menyalin, tetapi orang tidak harus bergantung pada perilaku menyalin vs melihat.
reshape
di PyTorch ?!