當張量中某個維度的尺寸為 1 時,步長實際上可以是任意值。
我們直接用程式碼來驗證。首先中規中矩地使用 torch.arange 建立一個一維張量 x:
python
x = torch.arange(10)
x.shape
x.stride()
輸出:
torch.Size([10])
(1,)
接著使用 slice 語法,把步長拉大到 100,再取第一個元素:
python
y = x[::100][:1]
y
y.shape
y.stride()
輸出:
tensor([0])
torch.Size([1])
(100,)
這裡的關鍵是:
x[::100]先把步長變成 100- 再取
[:1],把尺寸變成 1 - 因此最後得到的是尺寸為 1、但步長為 100 的張量
也就是說:只要先用 ::k 拉大步長,再把結果切成單一元素,就能得到尺寸為 1、但步長為 k 的 view。
剛剛的例子是從 x 的第 0 個元素開始取的。我們也可以透過 slice 的 start 參數,讓 view 從別的位置開始:
python
y = x[3::100][:1]
y
y.shape
y.stride()
輸出:
tensor([3])
torch.Size([1])
(100,)
跟剛剛的例子一樣,尺寸皆為 1,但步長皆為 100。但是張量中唯一一個元素的值變成了 3,而不是原本的 0。
我們可以用 storage_offset 函數來查看張量在底層記憶體中的 offset:
python
y.storage_offset()
輸出:
3
可以看到,view 張量在底層記憶體中的offset隨著 slice 的起始點改變了。
我們可以把它總結成一般公式:
python
x = torch.arange(N)
y = x[offset::k][:1]
以後如果要製造一個「尺寸為 1、但步長和起始位置皆任意」的 view,就可以套用這個公式:
offset控制storage_offsetk設定步長[:1]只取第0個元素,使尺寸變為 1
以上程式驗證了本文一開始的說法:當某個維度的尺寸為 1 時,其步長可以是任意值。