Basitçe söylemek gerekirse, torch.Tensor.view()esinlenerek numpy.ndarray.reshape()veya esinlenerek , yeni şekil orijinal tensörün şekli ile uyumlu olduğu sürece, tensörün yeni bir görünümününumpy.reshape() oluşturur .
Somut bir örnek kullanarak bunu ayrıntılı olarak anlayalım.
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])
Bu tşekil tensörü ile , yalnızca aşağıdaki şekiller için (18,)yeni görünümler oluşturulabilir:
(1, 18)ya da eşdeğer (1, -1)ya da eşdeğer ya da eşdeğer ya da eşdeğer ya da eşdeğer ya da eşdeğer ya da(-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)
Yukarıdaki şekil tüplerinden zaten gözlemleyebileceğimiz gibi, şekil demetinin elemanlarının (örn. 2*9, 3*6Vb.) Çoğaltılması her zaman orijinal tensördeki toplam 18örneğe eşit olmalıdır ( örneğimizde).
Gözlemlenecek bir başka şey -1de, şekil tupleslerinin her birinde bir yer kullanmış olmamızdır . A kullanarak -1, hesaplamayı kendimiz yapmakta tembel davranıyoruz ve yeni görünümü oluştururken şekil için bu değerin hesaplanmasını yapmak için görevi PyTorch'a devrediyoruz . Unutulmaması gereken önemli bir nokta, şekil demetinde sadece bir tane kullanabileceğimizdir -1. Kalan değerler bizim tarafımızdan açıkça belirtilmelidir. Else PyTorch atarak şikayet edecek RuntimeError:
RuntimeError: yalnızca bir boyut çıkarılabilir
Bu nedenle, yukarıda belirtilen şekillerin hepsiyle, PyTorch her zaman orijinal tensörün yeni bir görünümünü döndürecektir t. Bu temel olarak, istenen yeni görünümlerin her biri için sadece tensörün adım bilgilerini değiştirdiği anlamına gelir.
Aşağıda, her yeni görünümde tansörlerin adımlarının nasıl değiştiğini gösteren bazı örnekler verilmiştir .
# stride of our original tensor `t`
In [53]: t.stride()
Out[53]: (1,)
Şimdi, yeni görünümlerin adımlarını göreceğiz :
# 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)
İşte bu view()fonksiyonun büyüsü . Yeni görünümün şekli orijinal şekliyle uyumlu olduğu sürece, yalnızca yeni görünümlerin her biri için (orijinal) tensörün adımlarını değiştirir .
Adımlar dizilerini gözlemlemek olabilir bir başka ilginç olan bir 0 elemanın değeri olmasıdır inci pozisyon 1 'de elemanının değerine eşittir st şekil başlığın konumu.
In [74]: t3.shape
Out[74]: torch.Size([3, 6])
|
In [75]: t3.stride() |
Out[75]: (6, 1) |
|_____________|
Bunun nedeni ise:
In [76]: t3
Out[76]:
tensor([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17]])
adım (6, 1)olduğunu 0 boyunca sonraki öğeye bir öğeden gitmek diyor inci Zorunda, boyutun atlamak ya da 6 adımları atın. (yani gitmek için 0için 6. bir 6 adım atması gerekir,) Ama 1'de sonraki öğeye bir öğeden gitmek st (örn dan gitmek için boyutun, sadece tek bir adım gerekir 2için 3).
Bu nedenle, adım bilgileri, hesaplamayı gerçekleştirmek için öğelere bellekten nasıl erişildiğinin merkezindedir.
Bu işlev bir görünüm döndürür torch.Tensor.view()ve yeni şekil orijinal tensörün şekliyle uyumlu olduğu sürece kullanmakla tamamen aynıdır . Aksi takdirde bir kopyasını döndürür.
Ancak, notlar şunları torch.reshape()uyarıyor:
bitişik girişler ve uyumlu adımlara sahip girişler kopyalamadan yeniden şekillendirilebilir, ancak kopyalama ve görüntüleme davranışına bağlı olmamalıdır.
reshapenumpy'nin yeniden şekillenmesine benziyor" - neden sadece PyTorch'ta çağırmadılar ?!