1. 程式人生 > >PyTorch 的這些更新,你都知道嗎?

PyTorch 的這些更新,你都知道嗎?

翻譯 | 林椿眄

出品 | AI 科技大本營(公眾號ID:rgznai100)

這次版本的主要更新一些效能的優化,包括權衡記憶體計算,提供 Windows 支援,24個基礎分佈,變數及資料型別,零維張量,張量變數合併,支援 CuDNN 7.1,加快分散式計算等,並修復部分重要 bug等。

目錄

  • 主要變化

    • 張量/變數合併

    • 零維張量

    • 資料型別

    • 版本遷移指南

  • 新特性

    • 張量

      • 高階的索引功能

      • 快速傅立葉變換

    • 神經網路

      • 權衡記憶體計算

      • 瓶頸—用於識別程式碼熱點的工具

    • torch中的分佈

      • 24個基礎的概率分佈

      • 新增 cdf,variance,entropy,perplexity 等方法

    • 分散式計算

      • 便捷使用的Launcher utility

      • NCCL2 後端

    • C++ 拓展

    • Window 支援

    • 改善 ONNX 效能

      • RNN 支援

  • 效能改善

  • Bug 修復

主要變化

以下我們將為Pytorch使用者總結一些頻繁使用到的最重要的核心功能。

主要變化及潛在的突破性變化

  • Tensors/Variables 合併

  • 零維 Tensors 的一些操作

  • 棄用Volatile 標誌

效能改善

  • 添加了 dtypes、devices及numpy風格的 tensor 建立函式

  • 支援編寫一些不依賴裝置的程式碼

我們編寫了一個版本遷移指南,幫助你將程式碼轉換為新版本的 APIs和風格。如果你想要遷移先前版本的 PyTorch程式碼,請閱讀遷移指南。此外,本部分的內容(包括主要核心變化)都包含在遷移指南中。

Tensor 和Variable 類合併

新版本中,torch.autograd.Variable和torch.Tensor將同屬一類。更確切地說,torch.Tensor 能夠跟蹤歷史並像舊版本的 Variable 那樣執行; Variable 封裝仍舊可以像以前一樣工作,但返回的物件型別是 torch.Tensor。 這意味著你不再需要程式碼中的所有變數封裝器。

  • Tensor 的type () 變化

這裡需要注意到張量的 type()不再反映資料型別,而是改用 isinstance()或 x.type()來表示資料型別,程式碼如下:

>>> x = torch.DoubleTensor([1, 1, 1])
>>

> print(type(x)) # was torch.DoubleTensor
<class 'torch.autograd.variable.Variable'>
>>> print(x.type())  # OK: 'torch.DoubleTensor'
'torch.DoubleTensor'
>>> print(isinstance(x, torch.DoubleTensor))  # OK: True
True

  • autograd 用於跟蹤歷史記錄

作為 autograd方法的核心標誌,requires_grad現在是 Tensors 類的一個屬性。 讓我們看看這個變化是如何體現在程式碼中的。Autograd的使用方法與先前用於 Variable 的規則相同。當操作中任意輸入 Tensor的require_grad = True時,它開始跟蹤歷史記錄。程式碼如下所示,

>>> x = torch.ones(1)  # create a tensor with requires_grad=False (default)
>>> x.requires_grad
False
>>> y = torch.ones(1)  # another tensor with requires_grad=False
>>> z = x + y
>>> # both inputs have requires_grad=False. so does the output
>>> z.requires_grad
False
>>> # then autograd won't track this computation. let's verify!
>>> z.backward()
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
>>>
>>> # now create a tensor with requires_grad=True
>>> w = torch.ones(1, requires_grad=True)
>>> w.requires_grad
True
>>> # add to the previous result that has require_grad=False
>>> total = w + z
>>> # the total sum now requires grad!
>>> total.requires_grad
True
>>> # autograd can compute the gradients as well
>>> total.backward()
>>> w.grad
tensor([ 1.])
>>> # and no computation is wasted to compute gradients for x, y and z, which don't require grad
>>> z.grad == x.grad == y.grad == None
True

  • requires_grad 操作

除了直接設定屬性之外,你還可以使用 my_tensor.requires_grad_(requires_grad = True)在原地更改此標誌,或者如上例所示,在建立時將其作為引數傳遞(預設為 False)來實現,程式碼如下:

>>> existing_tensor.requires_grad_()
>>> existing_tensor.requires_grad
True
>>> my_tensor = torch.zeros(3, 4, requires_grad=True)
>>> my_tensor.requires_grad
True

  • 關於 .data

.data 是從 Variable中獲取底層 Tensor 的主要方式。 合併後,呼叫 y = x.data仍然具有相似的語義。因此 y將是一個與 x共享相同資料的 Tensor,並且 requires_grad = False,它與 x的計算曆史無關。

然而,在某些情況下 .data 可能不安全。 對 x.data 的任何更改都不會被 autograd 跟蹤,如果在反向過程中需要 x,那麼計算出的梯度將不正確。另一種更安全的方法是使用 x.detach(),它將返回一個與 requires_grad = False 時共享資料的 Tensor,但如果在反向過程中需要 x,那麼 autograd 將會就地更改它。

零維張量的一些操作

先前版本中,Tensor向量(1維張量)的索引將返回一個Python數字,但一個Variable向量的索引將返回一個大小為(1,)的向量。同樣地, reduce函式存在類似的操作,即tensor.sum()會返回一個Python數字,但是variable.sum()會呼叫一個大小為(1,)的向量。

幸運的是,新版本的PyTorch中引入了適當的標量(0維張量)支援! 可以使用新版本中的torch.tensor函式來建立標量(這將在後面更詳細地解釋,現在只需將它認為是PyTorch中numpy.array的等效項)。現在你可以做這樣的事情,程式碼如下:

>>> torch.tensor(3.1416)         # create a scalar directly
tensor(3.1416)
>>> torch.tensor(3.1416).size()  # scalar is 0-dimensional
torch.Size([])
>>> torch.tensor([3]).size()     # compare to a vector of size 1
torch.Size([1])
>>>
>>> vector = torch.arange(2, 6)  # this is a vector
>>> vector
tensor([ 2.,  3.,  4.,  5.])
>>> vector.size()
torch.Size([4])
>>> vector[3]                    # indexing into a vector gives a scalar
tensor(5.)
>>> vector[3].item()             # .item() gives the value as a Python number
5.0
>>> sum = torch.tensor([2, 3]).sum()
>>> sum
tensor(5)
>>> sum.size()
torch.Size([])

  • 累計損失函式

考慮在 PyTorch0.4.0 版本之前廣泛使用的 total_loss + = loss.data[0] 模式。Loss 是一個包含張量(1,)的Variable,但是在新發布的0.4.0版本中,loss 是一個0維標量。 對於標量的索引是沒有意義的(目前的版本會給出一個警告,但在0.5.0中將會報錯一個硬錯誤):使用 loss.item()從標量中獲取 Python 數字。

還值得注意得是,如果你在累積損失時未能將其轉換為 Python 數字,那麼程式中的記憶體使用量可能會增加。這是因為上面表示式的右側,在先前版本中是一個Python 浮點型數字,而現在它是一個零維的張量。 因此,總損失將會累積了張量及其歷史梯度,這可能會需要更多的時間來自動求解梯度值。

棄用volatile標誌

新版本中,volatile 標誌將被棄用且不再會有任何作用。先前的版本中,任何涉及到 volatile = True 的 Variable 的計算都不會由 autograd 追蹤到。這已經被一組更靈活的上下文管理器所取代,包括 torch.no_grad(),torch.set_grad_enabled(grad_mode)等等。程式碼如下:

>>> x = torch.zeros(1, requires_grad=True)
>>> with torch.no_grad():
...    y = x * 2
>>> y.requires_grad
False
>>>
>>> is_train = False
>>> with torch.set_grad_enabled(is_train):
...    y = x * 2
>>> y.requires_grad
False
>>> torch.set_grad_enabled(True)  # this can also be used as a function
>>> y = x * 2
>>> y.requires_grad
True
>>> torch.set_grad_enabled(False)
>>> y = x * 2
>>> y.requires_grad
False

dtypes、devices 及陣列風格的新函式

在先前版本的 PyTorch 中,我們通常需要指定資料型別(例如float vs double),裝置型別(cpu vs cuda)和佈局(dense vs sparse)作為“張量型別”。例如,torch.cuda.sparse.DoubleTensor是 Tensor 類的 double 資料型別,用在 CUDA 裝置上,並具有 COO 稀疏張量佈局。

在新版本中,我們將引入 torch.dtype,torch.device 和 torch.layout 類,以便通過 NumPy 風格的建立函式來更好地管理這些屬性。

  • torch.dtype

以下給出可用的 torch.dtypes(資料型別)及其相應張量型別的完整列表。

640?wx_fmt=png

使用 torch.set_default_dtype 和 torch.get_default_dtype來操作浮點張量的預設 dtype。

  • torch.device

torch.device 包含裝置型別('cpu'或'cuda')及可選的裝置序號(id)。它可以通過 torch.device('{device_type}')或 torch.device('{device_type}:{device_ordinal}')來初始化所選裝置。

如果裝置序號不存在,則用當前裝置表示裝置型別; 例如,torch.device('cuda')等同於 torch.device('cuda:X'),其中 x 是 torch.cuda.current_device()的結果。

  • torch.layout

torch.layout 表示張量的資料佈局。新版本中,torch.strided(密集張量)和torch.sparse_coo(帶有 COO 格式的稀疏張量)均受支援。

建立張量

新版本中,建立 Tensor 的方法還可以使用 dtype,device,layout 和 requires_grad選項在返回的 Tensor 中指定所需的屬性。程式碼如下:

>>> device = torch.device("cuda:1")
>>> x = torch.randn(3, 3, dtype=torch.float64, device=device)
tensor([[-0.6344,  0.8562, -1.2758],
       [ 0.8414,  1.7962,  1.0589],
       [-0.1369, -1.0462, -0.4373]], dtype=torch.float64, device='cuda:1')
>>> x.requires_grad  # default is False
False
>>> x = torch.zeros(3, requires_grad=True)
>>> x.requires_grad
True

  • torch.tensor

torch.tensor 是新新增的張量建立方法之一。它像所有型別的資料一樣排列,並將包含值複製到一個新的 Tensor 中。如前所述,PyTorch 中的 torch.tensor等價於 NumPy 中的建構函式 numpy.array。與 torch.*tensor 方法不同的是,你也可以通過這種方式(單個 python 數字在 torch.*tensor  方法中被視為大小)建立零維張量(也稱為標量)。此外,如果沒有給出 dtype 引數,它會根據給定的資料推斷出合適的 dtype。這是從現有資料(如 Python 列表)建立張量的推薦方法。程式碼如下:

>>> cuda = torch.device("cuda")
>>> torch.tensor([[1], [2], [3]], dtype=torch.half, device=cuda)
tensor([[ 1],
       [ 2],
       [ 3]], device='cuda:0')
>>> torch.tensor(1)               # scalar
tensor(1)
>>> torch.tensor([1, 2.3]).dtype  # type inferece
torch.float32
>>> torch.tensor([1, 2]).dtype    # type inferece
torch.int64

我們還添加了更多的張量建立方法。其中包括一些有torch.*_like或tensor.new_ *變體。

1. torch.*_like 輸入一個 tensor 而不是形狀。除非另有說明,它預設將返回一個與輸入張量相同屬性的張量。程式碼如下:

>>> x = torch.randn(3, dtype=torch.float64)
>>> torch.zeros_like(x)
tensor([ 0.,  0.,  0.], dtype=torch.float64)
>>> torch.zeros_like(x, dtype=torch.int)
tensor([ 0,  0,  0], dtype=torch.int32)

2. tensor.new_ * 也可以建立與 tensor 具有相同屬性的 tensor,但它需要指定一個形狀引數:

>>> x = torch.randn(3, dtype=torch.float64)
>>> x.new_ones(2)
tensor([ 1.,  1.], dtype=torch.float64)
>>> x.new_ones(4, dtype=torch.int)
tensor([ 1,  1,  1,  1], dtype=torch.int32)

要得到所需的形狀,在大多數情況下你可以使用元組(例如 torch.zeros((2,3)))或可變引數(例如 torch.zeros(2,3))來指定。

640?wx_fmt=png

其中 *:torch.from_numpy 只接受一個 NumPy ndarray 型別作為其輸入引數。

編寫一些與裝置無關的程式碼

先前版本的 PyTorch 很難編寫一些裝置不可知或不依賴裝置的程式碼(例如,可以在沒有修改的情況下,在CUDA環境下和僅CPU環境的計算機上執行)。

在新版本PyTorch 0.4.0中,你通過一下兩種方式讓這一過程變得更容易:

  • 張量的device屬性將為所有張量提供torch.device屬性(get_device僅適用於CUDA張量)

  • Tensors和Modules的to方法可用於將物件輕鬆移動到不同的裝置(而不必根據上下文資訊呼叫cpu()或cuda())

我們推薦用以下的模式:

# at beginning of the script
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
...
# then whenever you get a new Tensor or Module
# this won't copy if they are already on the desired device
input = data.to(device)
model = MyModule(...).to(device)

張量

支援高階的索引方式

新版本的 PyTorch 將完全支援高階索引,遵循 numpy 的高階索引規則。現在你可以使用以下示例:

a = torch.rand(10, 10, 10, 10)
# the indexing elements can have other shapes than 1
b = a[[[3, 2]], :, [[1, 3]]]
# broadcasting also supported in the indices, as well as lists,
# negative indices, slices, elipses, numbers
c = a[[1, -2], 2:4, :, [1]]
# can also support tensors as indices
index = torch.tensor([2, 4])
d = a[index]
# and the indices can be on the GPU
# or CPU
e = a[index.cuda()]
f = a.cuda()[index]


mask = torch.rand(10) > 0.5
# we can now index with a mask that has fewer
# dimensions than the indexing tensor
c = a[mask, :5]

快速傅立葉變換

  • 新增新的 FFT 方法#5856

  • 新增 torch.stft(短時傅立葉變換)和 hann / hamming / Bartlett 窗函式。#4095

  • 在 * FFT#6528 中支援任意數量的批次維度

已更新的 torch 新功能和操作

  • 增加了 torch.log2 和 torch.log10#6272

  • 增加了 torch.isnan#5273

  • 新增 torch.reshape,這與 numpy.reshape 的功能類似。它大致相當於 tensor.contiguous().view(),但在某些情況下避免了複製#5575

  • 相關推薦

    PyTorch這些更新知道

    翻譯 | 林椿眄出品 | AI 科技大本營(公眾號ID:rgznai100)這次版本的主要更新一

    這些Spring中的設計模式知道

    設計模式作為工作學習中的枕邊書,卻時常處於勤說不用的尷尬境地,也不是我們時常忘記,只是一直沒有記憶。 Spring作為業界的經典框架,無論是在架構設計方面,還是在程式碼編寫方面,都堪稱行內典範。好了,話不多說,開始今天的內容。 spring中常用的設計模式達到九種,我

    【本人禿頂程式設計師】這些Spring中的設計模式知道

    ←←←←←←←←←←←← 快!點關注!!! 設計模式作為工作學習中的枕邊書,卻時常處於勤說不用的尷尬境地,也不是我們時常忘記,只是一直沒有記憶。 Spring作為業界的經典框架,無論是在架構設計方面,還是在程式碼編寫方面,都堪稱行內典範。好了,話不多說,開始今天的內容。 spri

    這些 Spring 中的設計模式知道

    開發十年,就只剩下這套架構體系了! >>>   

    2017年科技界十大新聞知道

    blank 展示 時代 https 狀態 tps 一段 隨著 支付 2017年馬上就要過去了,小編帶你一起來盤點今年最具影響力的十大科技新聞…… 1、人工智能AI元年到來 2017年也叫做AI元年,雖然很早前就開始被提出被關註,但今年它才開始

    家裝輔材包括哪些?吉材易達講的這些必備清單知道

    裝修是每個家的大事,辛辛苦苦買了房子都想裝得好一些,住的舒心一些,在家裝中人們往往注重大件的建材的選購缺忽視一些家裝輔材,要知道有時候輔材有的不環保或者質量有問題的話都會對整體的家裝有影響,下面小編就向大家羅列一些家裝的輔材材料,一起來了解吧。 家裝輔材包括哪些

    學習Python需要了解的十種方法知道

    Python 2與Python 3不相容,這讓我不知道該選擇哪個版本的Python。最終我選擇了Python 2,因為當時許多我需要用的庫都與Python 3不相容。 但實際上,日常使用中最大的版本差異是輸出(print)和除法行為。現在我在Python 2的程式碼

    大資料的三大趨勢和三大困境知道?此文全解!!!

    一家公司的數字化改造應該從清晰的趨勢和障礙出發,更好地規劃出一條通往其所尋求業務成果的路線。考慮到這一點,以下是我們關注的三大資料趨勢,以及在數字時代可能出現在企業和成功之間的三大困境。 三大趨勢 1.真實的機器學習  2018年6月2日,由雲豆資料主辦的《大資料時代趨

    這21個自動化部署工具知道

    作者:Darren Perucci 翻譯:袁思思 來源:DZone 原文連結:https://dzone.com/articles/21-automated-deployment-tools-you-should-know 比爾蓋茨曾說過: “任何技術在一個

    華為手機的5種截圖方法知道

    如今蘋果手機不再那麼受人追捧,越來越多人開始使用華為手機,伴隨著智慧手機的出現,越來越多的手機功能讓我們感慨科技帶給我們的便利,就從華為說起,光是一個截圖,就有5種方法,究竟是哪5種方法,讓小編帶大家看一下! 手機按鍵 方法:電源鍵+音量下鍵,最傳統的使用方法,知道的人也是最多的。 快捷

    華為手機的5種截屏方法知道

    快捷 使用 操作 直接 隨著 感慨 截屏 電源 開關 如今蘋果手機不再那麽受人追捧,越來越多人開始使用華為手機,伴隨著智能手機的出現,越來越多的手機功能讓我們感慨科技帶給我們的便利,就從華為說起,光是一個截屏,就有5種方法,究竟是哪5種方法,讓小編帶大家看一下! 手機按鍵

    挖掘機的日常故障判斷日常維護知道

    目前市場上的挖掘機一般都採用了機電液一體化控制模式,常見故障為發動機轉速下降,工作速度變慢,挖掘無力等一些日常使用中的故障。本文簡單介紹了挖掘機在這幾類故障中的故障判斷及維修技術,另外還介紹了挖掘機的日常保養技術,以保障挖掘機的正常工作。 隨著科技的進步,目前挖掘機一般都採用了機電液一體化控制模式,我們在排

    十種常用的的資料分析思路知道

    道家強調四個字,叫“道、法、術、器”。 層次區別:“器”是指物品或工具,在資料分析領域指的就是資料分析的產品或工具,“工欲善其事,必先利其器”; “術”是指操作技術,是技能的高低、效率的高

    HTML5新特性有哪些知道

    一、畫布(Canvas) 畫布是網頁中的一塊區域,可所以用JavaScript在上面繪圖。下面我們來建立一個畫布並在上面繪製一個坦克(後面將用HTML5做一個坦克大戰遊戲),程式碼如下: <!DOCTYPE html> <html> <

    IT安全漏洞、威脅與風險的區別知道

    在當前的世界中,資料和資料保護是企業至關重要的考慮因素。客戶希望您確保其資訊的安全性,如果您不能保證資訊保安,就會失去業務。許多擁有敏感資訊的客戶在與您開展業務之前,會要求您部署堅固的資料安全基礎架構。基於這種考慮,您是否相信自己企業內的IT安全性? 與去年同期相比,儘

    JAVA語言開發的十個誤區知道

    目前,對於java的開發正在蓬勃發展,已形成很大的市場,然而對於JAVA語言的認識仍有不少誤解,接下來由卓躍教育為大家介紹 學習java語言的十大誤區。  1、JAVA是HTML擴充的,JAVA是程式語言,HTML是個頁面描述語言。除了新版本HTML可以在WEB頁中插入JA-VA小應用之外,它們之 間沒有任

    這些繼承知識知道

    本文最初發表在個人部落格http://nijiaben058.jspkj.com,歡迎大家光臨。      在這裡我主要是想記錄點繼承的基礎知識,當是一次小小的總結吧,以便自己將來查閱,也便於初學者學習,此文主要是以知識小結為主,不會詳細闡述原理,當然我覺得有必要的還是會講點

    Java開發中一定要註意的幾點知道

    alt 利用 原則 nac date 時間 查詢 節點類 所有 Java學習交流群967051845!進群免費領取2019最全學習資料! 1. 將一些需要變動的配置寫在屬性文件中 比如,沒有把一些需要並發執行時使用的線程數設置成可在屬性文件中配置。那麽你的程序無論在DEV

    這四種物件屬性拷貝方式知道

    當get/set太繁瑣時;當BeanUtils無法拷貝集合時;當。。。可能,你需要好好看看這篇文章,文末附完整示例程式碼。 在做業務的時候,為了隔離變化,我們會將DAO查詢出來的DO和對前端提供的DTO隔離開來。大概90%的時候,它們的結構都是類似的;但是我們很不喜歡寫很多冗長的b.setF1(a.getF1

    網曝“吃雞”國服17日上線關於外掛這些知道

    後來 湖北 height 相對 一位 ots 付費 大於 方法 先來一組思考題:聽舅舅黨說,騰訊《絕地求生》國服會在1月17日上線?如果不免費,你會不會玩?如果沒外拐,你會不會玩?如果免費+道具付費,你會不會玩?如果只收你皮膚的錢,你會不會玩?為什麽“吃雞”官方對外掛認慫?