丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強烈建議使用更快更安全的瀏覽器
此為臨時鏈接,僅用于文章預(yù)覽,將在時失效
人工智能開發(fā)者 正文
發(fā)私信給三川
發(fā)送

0

從原理到實戰(zhàn) 英偉達教你用PyTorch搭建RNN(上)

本文作者: 三川 2017-05-05 16:55
導(dǎo)語:動態(tài)計算圖加持,PyTorch 相比 TensorFlow 是否有優(yōu)勢?

從原理到實戰(zhàn) 英偉達教你用PyTorch搭建RNN(上)

雷鋒網(wǎng)按:本文原載于英偉達博客,雷鋒網(wǎng)編譯。

從 Siri 到谷歌翻譯,深度神經(jīng)網(wǎng)絡(luò)大步推動了機器對自然語言的理解。

迄今為止,大多數(shù)模型把語言看作是字詞的平面序列(flat sequence),使用時間遞歸神經(jīng)網(wǎng)絡(luò)(recurrent neural network)來處理。但語言學家認為,這并不是看待語言的最佳方式,應(yīng)把其理解為由短語組成的的分層樹狀結(jié)構(gòu)( hierarchical tree of phrases)。由于對該類結(jié)構(gòu)的支持,大量深度學習研究投入到結(jié)構(gòu)遞歸神經(jīng)網(wǎng)絡(luò)(recursive neural network)之中。在業(yè)內(nèi),這些模型有非常難以執(zhí)行、運行起來效率低下的名聲。

但對于今年 Facebook 開源的新深度學習框架 PyTorch ,業(yè)內(nèi)人士人認為它的一大貢獻是:搭建結(jié)構(gòu)遞歸神經(jīng)網(wǎng)絡(luò)以及其它復(fù)雜自然語言處理模型,變得更簡便。

結(jié)構(gòu)遞歸神經(jīng)網(wǎng)絡(luò),是展示 PyTorch 靈活性的一個不錯的例子。但同時,PyTorch 是一個對于各類深度學習任務(wù)有完備功能的框架,雖然特別適于計算機視覺問題。它誕生于 Facebook AI 研究院 FAIR 的研究人員之手,PyTorch 把 Torch7 中高效、靈活的 GPU 加速后端算法庫,和直覺性的 Python 前端結(jié)合到一起,并具有快速創(chuàng)建原型機的能力、高度可讀性的代碼、以及對于各類深度學習模型的支持。

SPINNing Up

本文將帶領(lǐng)大家在 PyTorch 上,實現(xiàn)一個有 recurrent tracker 和 TreeLSTM 節(jié)點的結(jié)構(gòu)遞歸神經(jīng)網(wǎng)絡(luò),即 SPINN。對于相當多的主流深度學習框架,這是一個很難搭建的自然語言處理模型。這里我描述的實現(xiàn)部分做了 batch,所以能夠利用 GPU 加速的性能,比不用 batch 的版本要快得多。

SPINN 模型的全稱是“Stack-augmented Parser-Interpreter Neural Network”,它作為一種解決了自然語言推理任務(wù)的方案,隨 Bowman et al. (2016) 論文面世,當時使用的是斯坦福的 SNLI 數(shù)據(jù)集。

這里的任務(wù),是把成對的語句分類為三組類別:假設(shè)第一個句子是對某幅用戶無法看到的圖像的準確注解,第二個句子同樣是對該圖像的注解,那么第二句話到底是 (a) 絕對準確 (b) 可能準確還是 (c) 絕對不準確的?舉個例子,假設(shè)第一句話是 “two dogs are running through a field”(兩條狗穿過一片農(nóng)田)。那么,讓這組語句“絕對正確”的句子可以是““there are animals outdoors”(戶外有動物);讓它們“可能準確”的,可以是“some puppies are running to catch a stick”(一群幼犬跑著去接一個木棒);讓它們“絕對不準確”的可以是 “the pets are sitting on a couch”(寵物們坐在沙發(fā)上)。

導(dǎo)致 SPINN 誕生的研究,為實現(xiàn)其目標要在決定句子之間的關(guān)系之前,把每句話編碼為固定長度的矢量表達(還有其他方式,比如注意力模型)。

數(shù)據(jù)集包含機器生成的語法樹( syntactic parse trees),后者把每句話里的詞組合為短語和子句,每一個都有獨立涵義,并且有兩個詞或 sub-phrases 組成。許多語言學家認為,人類理解語言,是通過把涵義以層級(hierarchical)方式組合起來,就像這樣的樹狀結(jié)構(gòu)。因此,創(chuàng)建一個以同樣方式運作的神經(jīng)網(wǎng)絡(luò)或許是必要的。下面的例子是一個數(shù)據(jù)集里的句子,它的語法樹以括號結(jié)構(gòu)表示:

  ( ( The church ) ( ( has ( cracks ( in ( the ceiling ) ) ) ) . ) )

用支持語法樹結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò)對這個句子編碼,方法之一是創(chuàng)建一個神經(jīng)網(wǎng)絡(luò)層 Reduce,把詞組(以 GloVe 這樣的 word embedding 來表示)或短語組合起來,然后將這一層循環(huán)應(yīng)用,把上一個 Reduce 操作的結(jié)果,作為句子的編碼:

X = Reduce(“the”, “ceiling”)
Y = Reduce(“in”, X)
... etc.

但如果,我想讓神經(jīng)網(wǎng)絡(luò)以更“人性化”的方式運作呢?能從左到右閱讀,保持語境,同時使用語法樹把短語組合起來?或者,如果我想要訓(xùn)練一個神經(jīng)網(wǎng)絡(luò),讓它在看到這句子時,基于讀到的詞語創(chuàng)建它自己的語法樹?這是一個同樣的語法樹,只是寫出來的方式稍稍有區(qū)別:

  The church ) has cracks in the ceiling ) ) ) ) . ) )

第三種方法,仍然是一回事:

WORDS:  The church   has cracks in the ceiling         .
PARSES: S   S      R S   S      S  S   S       R R R R S R R

我所做的,僅僅是去除括號,用“S” 代表“shift”來標記詞語, 并用“R”代表“reduce”替代右括號?,F(xiàn)在,信息可作為操作堆棧(stack) 和類似堆棧的 buffer 的一系列指令從左讀到右,與上文描述的循環(huán)方式有同樣的結(jié)果:

  1. 將文本導(dǎo)入 buffer。

  2. 從 buffer 的首詞“The” pop 出去,把 push 入棧,這時“The”應(yīng)該在“church”前面。

  3. Pop 最上面的兩個堆棧值,應(yīng)用 Reduce,把結(jié)果 push 入棧。

  4. 從 buffer pop 出“has”,push 到入棧,隨后 “cracks”,再“in”,再“the”,再“ceiling”。

  5. 重復(fù)四次:pop 最前面的兩個堆棧值,應(yīng)用 Reduce,push 結(jié)果。

  6. 從緩存 pop 出“.”再 push 入棧。

  7. 重復(fù)兩次:pop 最前面的兩個堆棧值,應(yīng)用 Reduce,push 結(jié)果。

  8. Pop 剩下的堆棧值,作為句子編碼返回。

我還想維持語境,照顧到其他信息——句子中系統(tǒng)已讀取的部分,并在句子的之后部分上進行 Reduce 操作。所以,我將把兩個參數(shù)(two-argument)的 Reduce 函數(shù),用三個參數(shù)的函數(shù)來替代,后者導(dǎo)入左子樹、右子樹短語以及當前語境狀態(tài)。該狀態(tài)由第二個神經(jīng)網(wǎng)絡(luò)層生成——一個名為 Tracker 的循環(huán)單位。給定現(xiàn)有句子語境狀態(tài),Tracker 在堆棧操作的每一步生成一個新狀態(tài)(讀取每個詞語和右括號之后),buffer 最頂端的 entry b 和堆棧中最頂端的兩個 entries s1、s2:

context[t+1] = Tracker(context[t], b, s1, s2)

可以想象一下用你最喜歡的編程語言寫這些東西:對于需要處理的每個句子,它會從 buffer 中加載下一個詞,運行 Tracker,檢查是否要 push 入?;蛘哌M行 Reduce,操作后不斷重復(fù),直到整個句子處理完畢。當應(yīng)用在單個句子上面,這個過程由大且復(fù)雜的深度神經(jīng)網(wǎng)絡(luò)運行,網(wǎng)絡(luò)上的兩個可訓(xùn)練層一遍遍按照 stack manipulation 規(guī)定的方式執(zhí)行。

但如果你對 TensorFlow、Theano 等傳統(tǒng)深度學習框架很熟悉,你就知道執(zhí)行這類動態(tài)過程有多么費勁。這值得我們花點時間多想想,為什么它們處理這種任務(wù)力不從心,以及 PyTorch 是否能提供不一樣的東西。

圖理論

從原理到實戰(zhàn) 英偉達教你用PyTorch搭建RNN(上)

本質(zhì)上,深度神經(jīng)網(wǎng)路只是有海量參數(shù)的復(fù)雜函數(shù)。深度學習的目標也僅僅是通過計算 partial derivatives(梯度)、衡量損失來優(yōu)化這些參數(shù)。如果該函數(shù)以計算圖結(jié)構(gòu)來表示,反著運行能去除計算梯度的不必要工作。所有現(xiàn)代深度學習框架都是基于這一反向傳播概念,作為結(jié)果,每個框架都需要找到一種方式來表示計算圖。

大多數(shù)的主流深度學習框架,比如 TensorFlow、Theano、Keras 以及 Torch7 的 nngraph 算法庫,它們的計算圖都是事先創(chuàng)建好的靜態(tài)物體。該圖由看起來像是數(shù)學表達的代碼來定義,但它的變量其實是還沒有賦予任何數(shù)值的占位符(placeholder)。由占位符標量組成的圖,編譯為一個函數(shù),然后重復(fù)在訓(xùn)練數(shù)據(jù) batch 上運行,生成輸出和梯度。

這種靜態(tài)計算圖在 CNN 上的效果很好,后者的結(jié)構(gòu)一般是固定的。但對于許多應(yīng)用,開發(fā)者需要讓神經(jīng)網(wǎng)絡(luò)圖的機構(gòu)能隨數(shù)據(jù)修改。在自然語言處理中,研究人員通常希望把時間遞歸神經(jīng)網(wǎng)絡(luò)展開,最好輸入有多少詞,就有多少時間步(timestep)。上文提到的 SPINN 模型的 stack manipulation,非常倚賴控制流,比如“for”和“if”statement,來定義某個特定句子的計算圖結(jié)構(gòu)。在更復(fù)雜的例子里,你也許想要搭建結(jié)構(gòu)取決于子網(wǎng)絡(luò)輸出的模型。

有的想法可以被硬塞進靜態(tài)圖系統(tǒng),但不是全部 ,而且?guī)缀蹩偸且愿愕耐该鞫?、看不懂的代碼作為代價??蚣苄枰o計算圖添加代表了編程基本指令(loops and conditionals)的特殊節(jié)點,用戶需要學習、使用這些節(jié)點,而不是程序語言中的 “for”和“if” statement。這是因為任何程序員使用的控制流 statement  均只能使用一次,在創(chuàng)建圖時寫死(hard coding)一條計算通道。

比如說,詞語(從初始狀態(tài) h0 開始)中的矢量上,運行一個時間遞歸神經(jīng)網(wǎng)絡(luò)(rnn_unit)需要 tf.while_loop,一個特殊的控制流節(jié)點。在 TensorFlow 運行時獲取詞語長度需要一個額外特殊節(jié)點,這是由于代碼運行的時候它只是一個占位符。

# TensorFlow
# (this code runs once, during model initialization)
# “words” is not a real list (it’s a placeholder variable) so
# I can’t use “l(fā)en”
cond = lambda i, h: i < tf.shape(words)[0]
cell = lambda i, h: rnn_unit(words[i], h)
i = 0
_, h = tf.while_loop(cond, cell, (i, h0))

一個在根本上與之區(qū)別的方式,是動態(tài)計算圖,這在幾十年前的學界就已展開研究,又被稱為“define-by-run”。哈佛大學研發(fā)出來的 Kayak 、autograd,以及研究導(dǎo)向的框架 Chainer and DyNet 都基于動態(tài)計算圖。在這樣的框架中,計算圖在運行時才被創(chuàng)建出來或重新創(chuàng)建。進行前饋通道運算的代碼,也為反向傳播創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu)。該方式生成更直觀的代碼,因為控制流使用標準的“for”和“if”來寫。修補漏洞也變得更簡單,因為運行時的斷點、堆棧蹤跡(stack trace)讓你直接找到寫的代碼,而不是執(zhí)行引擎里的編譯函數(shù)。同樣變量長度的時間遞歸神經(jīng)網(wǎng)絡(luò),可用簡單的 Python “for”循環(huán)在動態(tài)框架里實現(xiàn)。

# PyTorch (also works in Chainer)
# (this code runs on every forward pass of the model)
# “words” is a Python list with actual values in it
h = h0
for word in words:
   h = rnn_unit(word, h)

PyTorch  是第一個在性能、靈活性上媲美靜態(tài)圖框架的 “define-by-run”深度學習框架。這使它適合于開發(fā)幾乎所有模型,從標準的卷積網(wǎng)絡(luò)到最離譜的強化學習想法。下篇中,我們將一起看看 SPINN 的代碼實現(xiàn)。

未完待續(xù),請關(guān)注雷鋒網(wǎng)后續(xù)文章。

雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。

從原理到實戰(zhàn) 英偉達教你用PyTorch搭建RNN(上)

分享:
相關(guān)文章

用愛救世界
當月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個人簡介
為了您的賬戶安全,請驗證郵箱
您的郵箱還未驗證,完成可獲20積分喲!
請驗證您的郵箱
立即驗證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說