PyTorch中張量的創建方法的選擇 | Pytorch系列(五)

點擊上方AI算法與圖像處理”,選擇加"星標"或“置頂”

重磅乾貨,第一時間送達

文 |AI_study

歡迎回到PyTorch神經網絡編程系列。在這篇文章中,我們將仔細研究將數據轉換成PyTorch張量的主要方法之間的區別。

在這篇文章的最後,我們將知道主要選項之間的區別,以及應該使用哪些選項和何時使用。言歸正傳,我們開始吧。

我們已經見過的PyTorch張量就是PyTorch類torch.Tenso的實例。張量和PyTorch張量之間的抽象概念的區別在於PyTorch張量給了我們一個具體的實現,我們可以在代碼中使用它。

在上一篇文章中《Pytorch中張量講解 | Pytorch系列(四)》,我們瞭解瞭如何使用Python列表、序列和NumPy ndarrays等數據在PyTorch中創建張量。給定一個numpy.ndarray,我們發現有四種方法可以創建 torch.Tensor 對象。

下面是快速回顧一下:

> data = np.array([1,2,3])
> type(data)
numpy.ndarray


> o1 = torch.Tensor(data)
> o2 = torch.tensor(data)
> o3 = torch.as_tensor(data)
> o4 = torch.from_numpy(data)


> print(o1)
> print(o2)
> print(o3)
> print(o4)
tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)

我們在這篇文章的任務是探索這些選項之間的區別,併爲我們的張量創建需求提出一個最佳的選擇。


生成張量的操作:有什麼區別?

讓我們開始並找出這些不同之處。

一、Uppercase/Lowercase: torch.Tensor() Vs torch.tensor()

注意到第一個選項torch.Tensor()是大寫的T,而第二個選項torch.tensor()是小寫的T。

第一個選項(即包含大寫T的)是torch.Tensor 類的構造函數。第二個選項是我們所謂的工廠函數( factory function),該函數構造torch.Tensor對象並將其返回給調用者。


你可以將torch.tensor()函數看作是在給定一些參數輸入的情況下構建張量的工廠。工廠函數是用於創建對象的軟件設計模式

如果您想了解更多關於它的信息,請點擊這裏。https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)

好的。那是大寫字母T和小寫字母t之間的區別,但是兩者之間哪種方法更好?答案是可以使用其中之一。但是,工廠函數torch.tensor() 具有更好的文檔和更多的配置選項,因此現在它可以贏得勝利。

二、Default dtype Vs Inferred dtype


好了,在我們把torch.Tensor()構造函數從我們的列表中刪除之前,讓我們複習一下打印出來的張量輸出的不同之處。

區別在於每個張量的 dtype。讓我們看看:

> print(o1.dtype)
> print(o2.dtype)
> print(o3.dtype)
> print(o4.dtype)
torch.float32
torch.int32
torch.int32
torch.int32


此處的差異是由於在構建張量時,torch.Tensor() 構造函數使用的默認的dtype不同。我們可以使用torch.get_default_dtype() 方法驗證默認的dtype:

> torch.get_default_dtype()
torch.float32

爲了驗證代碼,我們可以這樣做:

> o1.dtype == torch.get_default_dtype()
True

其他調用根據傳入的數據來選擇 dtype。這稱爲類型推斷(type inference)。dtype 根據傳入的數據來推斷。請注意,也可以通過給 dtype 指定參數來爲這些調用顯示設置 dtype。

> torch.tensor(data, dtype=torch.float32)
> torch.as_tensor(data, dtype=torch.float32)


使用torch.Tensor(),我們無法將 dtype 傳遞給構造函數。這是torch.Tensor() 構造函數缺少配置選項的示例。這也是使用 torch.tensor() 工廠函數創建張量的原因之一。

讓我們看一下這些替代創建方法之間的最後隱藏的區別。

三、共享內存以提高性能:複製與共享


第三個區別是隱藏的區別。爲了揭示差異,我們需要在使用ndarray創建張量之後,對numpy.ndarray中的原始輸入數據進行更改。

讓我們這樣做,看看會得到什麼:

> print('old:', data)
old: [1 2 3]


> data[0] = 0


> print('new:', data)
new: [0 2 3]


> print(o1)
> print(o2)
> print(o3)
> print(o4)


tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)


請注意,一開始data [0] = 1,並且還注意到我們只更改了原始numpy.ndarray中的數據。注意,我們沒有明確地對張量(o1,o2,o3,o4)進行任何更改。

但是,在設置data [0] = 0後,我們可以看到一些張量發生了變化。對於索引0,前兩個o1和o2仍具有原始值1,而對於索引0,後兩個 o3 和 o4 具有新值0。

發生這種情況是因爲torch.Tensor() 和torch.tensor() 複製了它們的輸入數據,而torch.as_tensor() 和torch.from_numpy() 與原始輸入對象共享了它們在內存中的輸入數據


這種共享僅僅意味着內存中的實際數據存在於一個地方。因此,基礎數據中發生的任何更改都將反映在兩個對象中,即torch.Tensor和numpy.ndarray。

與複製數據相比,共享數據更高效,佔用的內存更少,因爲數據不是寫在內存中的兩個位置。

如果我們有 torch.Tensor 的話,我們要把它轉換成一個numpy.ndarray,我們是這樣做的:

> print(o3.numpy())
> print(o4.numpy())
[0 2 3]
[0 2 3]

這給出:

> print(type(o3.numpy()))
> print(type(o4.numpy()))
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>

這樣可以確定torch.as_tensor() 和torch.from_numpy() 都與它們的輸入數據共享內存。但是,我們應該使用哪一個,它們有何不同?

torch.from_numpy() 函數僅接受 numpy.ndarrays,而torch.as_tensor()  函數則接受包括其他PyTorch張量在內的各種數組對象。因此,torch.as_tensor() 是內存共享比賽中的獲勝選擇。

在PyTorch中創建張量的最佳選擇

考慮到所有這些細節,這兩個是最佳選擇

  • torch.tensor()

  • torch.as_tensor()

torch.tensor() 調用是一種 go-to 調用,而在調整代碼性能時應使用torch.as_tensor()。

關於內存共享,要記住一些注意事項(它可以在某些地方起作用):

  1. 由於numpy.ndarray對象是在CPU上分配的,因此在使用GPU時,as_tensor() 函數必須將數據從CPU複製到GPU。

  2. as_tensor() 的內存共享不適用於內置Python數據結構(如列表)。

  3. 調用as_tensor() 要求開發人員瞭解共享功能。這是必要的,因此我們不會在未意識到更改會影響多個對象的情況下無意間對基礎數據進行不必要的更改。

  4. 如果在numpy.ndarray對象和張量對象之間進行大量來回操作,則as_tensor() 的性能提高會更大。但是,如果僅執行一次加載操作,則從性能角度來看不會有太大影響。

總結:

至此,我們現在應該對PyTorch張量創建選項有了更好的瞭解。我們已經瞭解了工廠函數,並且瞭解了內存共享與複製如何影響性能和程序行爲。 

文章中內容都是經過仔細研究的,本人水平有限,翻譯無法做到完美,但是真的是費了很大功夫,希望小夥伴能動動你性感的小手,分享朋友圈或點個“在看”,支持一下我 ^_^

英文原文鏈接是:

https://deeplizard.com/learn/video/AglLTlms7HU

加羣交流

歡迎小夥伴加羣交流,目前已有交流羣的方向包括:AI學習交流羣,目標檢測,秋招互助,資料下載等等;加羣可掃描並回復感興趣方向即可(註明:地區+學校/企業+研究方向+暱稱)

 我的生活不能沒有你! ????

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章