自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為Go語言設(shè)計的機器學(xué)習(xí)庫Gorgonia:對標(biāo)TensorFlow與Theano

開發(fā) 開發(fā)工具 機器學(xué)習(xí)
Gorgonia 是一個促進(jìn)在 Go 中進(jìn)行機器學(xué)習(xí)的庫,旨在更容易地編寫與評估涉及多維數(shù)組的數(shù)學(xué)方程。具體而言,Gorgonia 像 Theano 一樣相當(dāng)?shù)图?但又像 Tensorflow 一樣具有更高目標(biāo)。

[[184558]]

Gorgonia 是一個促進(jìn)在 Go 中進(jìn)行機器學(xué)習(xí)的庫,旨在更容易地編寫與評估涉及多維數(shù)組的數(shù)學(xué)方程。如果這聽起來很像 Theano 或者 TensorFlow,原因是三者的想法非常相似。具體而言,Gorgonia 像 Theano 一樣相當(dāng)?shù)图?但又像 Tensorflow 一樣具有更高目標(biāo)。

項目地址:https://github.com/chewxy/gorgonia

項目介紹:https://blog.chewxy.com/2016/09/19/gorgonia/

  • 可執(zhí)行自動微分
  • 可執(zhí)行符號微分
  • 可執(zhí)行梯度下降優(yōu)化
  • 可執(zhí)行數(shù)值穩(wěn)定
  • 提供了許多便利功能,以助于創(chuàng)建神經(jīng)網(wǎng)絡(luò)
  • 非???與 Theano 和 Tensorflow 的速度相當(dāng))
  • 支持 CUDA / GPGPU 計算(OpenCL 尚不支持,需發(fā)送拉取請求)
  • 將支持分布式計算

一、為何選擇 Gorgonia?

Gorgonia 的使用主要方便了開發(fā)者。如果你使用 Go 廣泛地堆棧,便可以在熟悉而舒適的環(huán)境中創(chuàng)建生產(chǎn)就緒的機器學(xué)習(xí)系統(tǒng)。

機器學(xué)習(xí)/人工智能通?;\統(tǒng)地分為兩個階段:(a)建立多種模型并測試、再測試的試驗階段,(b)以及模型在測試與試用之后被部署的部署階段。這兩個階段不可或缺且作用各異,就像數(shù)據(jù)科學(xué)家和數(shù)據(jù)工程師之間的區(qū)別。

原則上這兩個階段使用的工具也不同:實驗階段通常使用 Python / Lua(使用 Theano,Torch 等),而后這個模型會使用性能更高的語言來重新編寫,如 C++(使用 dlib、mlpack 等)。當(dāng)然,如今差距正在慢慢縮短,人們也經(jīng)常會進(jìn)行工具共享,比如 Tensorflow 便可用來填補差距。

而 Gorgonia 的目的,卻是在 Go 環(huán)境中完成相同的事情。目前 Gorgonia 性能相當(dāng)高,其速度與 Theano 和 Tensorflow 相當(dāng)(由于目前 Gorgonia 存在 一個 CUDA 缺陷,所以還未完成官方基準(zhǔn)測試;另外,因為實現(xiàn)可能會稍有不同,所以很難去比較一個精確的以牙還牙模型)。

二、安裝

安裝包是 go-get 的: go get -u github.com/chewxy/gorgonia.

Gorgonia 所使用的依賴很少且都很穩(wěn)定,所以目前不需要代管工具。下表為 Gorgonia 所調(diào)用的外部軟件包列表,并按照它所依賴的順序進(jìn)行了排列(已省略子軟件包):

 Gorgonia 所調(diào)用的外部軟件包列表

三、保持更新

Gorgonia 的項目有一個郵件列表和 Twitter 帳戶,官方更新和公告會發(fā)布到這兩個網(wǎng)站:

  • https://groups.google.com/forum/#!forum/gorgonia
  • https://twitter.com/gorgoniaML

四、用法

Gorgonia 通過創(chuàng)建計算圖來工作,而后將其執(zhí)行。請把它當(dāng)作一種僅限于數(shù)學(xué)函數(shù)方面的編程語言;事實上,這應(yīng)當(dāng)作為用戶思考的主要實例。它創(chuàng)建的計算圖是一個 AST。

微軟 CNTK 的 BrainScript 可能是用來說明計算圖的構(gòu)建與運行并不相同的最佳實例,所以用戶對于這二者,應(yīng)當(dāng)運用不同的思維模式。

雖然 Gorgonia 的實現(xiàn)并不像 CNTK 的 BrainScript 那樣強制性分離思維,但語法確實略有裨益。

此處舉出一個實例——若要定義一個數(shù)學(xué)表達(dá)式 z = x + y,應(yīng)當(dāng)這樣做:

  1. package mainimport (    "fmt" 
  2.     "log" 
  3.  
  4.     . "github.com/chewxy/gorgonia")func main() {    g :NewGraph()    var x, y, z *Node    var err error 
  5.  
  6.     // define the expression 
  7.     x = NewScalar(g, Float64, WithName("x")) 
  8.     y = NewScalar(g, Float64, WithName("y")) 
  9.     z, err = Add(x, y)    if err != nil { 
  10.         log.Fatal(err) 
  11.     }    // compile into a program 
  12.     prog, locMap, err :Compile(g)    if err != nil { 
  13.         log.Fatal(err) 
  14.     }    // create a VM to run the program on 
  15.     machine :NewTapeMachine(prog, locMap)    // set initial values then run 
  16.     Let(x, 2.0)    Let(y, 2.5)    if machine.RunAll() != nil { 
  17.         log.Fatal(err) 
  18.     } 
  19.  
  20.     fmt.Printf("%v", z.Value())    // Output: 4.5} 

你可能會發(fā)現(xiàn),它比其他類似的軟件包更顯冗長。如 Gorgonia 并未編譯為可調(diào)用的函數(shù),而是特地編譯為需要TapeMachine 來運行的program;此外它還需要手動調(diào)用一個 Let(...)。

作者卻認(rèn)為這是好事——能夠?qū)⑷说乃季S轉(zhuǎn)變?yōu)闄C器的思維。它在我們想查清哪里出錯的時候很有幫助。

五、虛擬內(nèi)存系統(tǒng)

當(dāng)前版本的 Gorgonia 有兩個虛擬內(nèi)存系統(tǒng):

  • TapeMachine
  • LispMachine

它們功能不同,采取的輸入也不同。TapeMachine 通常更善于執(zhí)行靜態(tài)表達(dá)式(即計算圖并不改變);由于其靜態(tài)特性,它適用于一次編寫,多次運行的表達(dá)式(如線性回歸,SVM 等)。

LispMachine 則是將圖形設(shè)為輸入,并直接在圖形的節(jié)點上執(zhí)行。如果圖形有所改變,只需新創(chuàng)建一個輕量級 LispMachine 來執(zhí)行便可。LispMachine 適于諸如創(chuàng)建大小不固定的循環(huán)神經(jīng)網(wǎng)絡(luò)這類的任務(wù)。

在 Gorgonia 發(fā)布之前存在第三個虛擬內(nèi)存,它基于堆棧,且與 TapeMachine 相似,但能夠更妥善地處理人工梯度。當(dāng)作者解決了所有的問題后,它也許就能重見天日。

六、微分

Gorgonia 執(zhí)行符號與自動微分,而這兩個過程存在細(xì)微差別。作者認(rèn)為這樣理解是最合適的:自動微分是在運行時所做的微分,與圖表的執(zhí)行同時發(fā)生;符號微分是在編寫階段所做的微分。

此處「運行時」當(dāng)然是指表達(dá)式圖的執(zhí)行,而非程序的實際運行。

通過介紹這兩個虛擬內(nèi)存系統(tǒng),便很容易理解 Gorgonia 如何執(zhí)行符號與自動微分。使用與上文相同的示例,讀者 能夠發(fā)現(xiàn)此處并沒有進(jìn)行微分。這次用 LispMachine 做一次嘗試吧:

  1. package mainimport (    "fmt" 
  2.     "log" 
  3.  
  4.     . "github.com/chewxy/gorgonia")func main() {    g :NewGraph()    var x, y, z *Node    var err error 
  5.  
  6.     // define the expression 
  7.     x = NewScalar(g, Float64, WithName("x")) 
  8.     y = NewScalar(g, Float64, WithName("y")) 
  9.     z, err = Add(x, y)    if err != nil { 
  10.         log.Fatal(err) 
  11.     }    // set initial values then run 
  12.     Let(x, 2.0)    Let(y, 2.5)    // by default, LispMachine performs forward mode and backwards mode execution 
  13.     m :NewLispMachine(g)    if m.RunAll() != nil { 
  14.         log.Fatal(err) 
  15.     } 
  16.  
  17.     fmt.Printf("z: %v\n", z.Value())    xgrad, err :x.Grad()    if err != nil { 
  18.         log.Fatal(err) 
  19.     } 
  20.     fmt.Printf("dz/dx: %v\n", xgrad)    ygrad, err :y.Grad()    if err != nil { 
  21.         log.Fatal(err) 
  22.     } 
  23.     fmt.Printf("dz/dy: %v\n", ygrad)    // Output: 
  24.     // z: 4.5 
  25.     // dz/dx: 1 
  26.     // dz/dy: 1} 

當(dāng)然,Gorgonia 同樣支持更傳統(tǒng)的的符號微分,比如在 Theano 中:

  1. package mainimport (    "fmt" 
  2.     "log" 
  3.  
  4.     . "github.com/chewxy/gorgonia")func main() {    g :NewGraph()    var x, y, z *Node    var err error 
  5.  
  6.     // define the expression 
  7.     x = NewScalar(g, Float64, WithName("x")) 
  8.     y = NewScalar(g, Float64, WithName("y")) 
  9.     z, err = Add(x, y)    if err != nil { 
  10.         log.Fatal(err) 
  11.     }    // symbolically differentiate z with regards to x and y 
  12.     // this adds the gradient nodes to the graph g 
  13.     var grads Nodes 
  14.     grads, err = Grad(z, x, y)    if err != nil { 
  15.         log.Fatal(err) 
  16.     }    // compile into a program 
  17.     prog, locMap, err :Compile(g)    if err != nil { 
  18.         log.Fatal(err) 
  19.     }    // create a VM to run the program on 
  20.     machine :NewTapeMachine(prog, locMap)    // set initial values then run 
  21.     Let(x, 2.0)    Let(y, 2.5)    if machine.RunAll() != nil { 
  22.         log.Fatal(err) 
  23.     } 
  24.  
  25.     fmt.Printf("z: %v\n", z.Value())    xgrad, err :x.Grad()    if err != nil { 
  26.         log.Fatal(err) 
  27.     } 
  28.     fmt.Printf("dz/dx: %v | %v\n", xgrad, grads[0])    ygrad, err :y.Grad()    if err != nil { 
  29.         log.Fatal(err) 
  30.     } 
  31.     fmt.Printf("dz/dy: %v | %v\n", ygrad, grads[1])    // Output: 
  32.     // z: 4.5 
  33.     // dz/dx: 1 | 1 
  34.     // dz/dy: 1 | 1} 

雖然人們在 Gorgonia 中,能嗅到支持 dualValue 存在條件下進(jìn)行正向模式微分的舊版痕跡,但其目前僅執(zhí)行反向模式自動微分(又名反向傳播)。正向模式微分也許在將來能夠回歸。

七、圖表

確實存在許多計算圖或表達(dá)式圖的有關(guān)說法,但它究竟是什么?請將它想象成你想要的數(shù)學(xué)表達(dá)式的 AST。此處為上述示例的圖形(但還有一個向量和一個標(biāo)量加法):

數(shù)學(xué)表達(dá)式的 AST

順便一提,Gorgonia 的圖形打印能力很強。此處為方程式 y = x² 及其導(dǎo)數(shù)的圖形示例:

方程式 y = x2 及其導(dǎo)數(shù)的圖形示例

圖形很容易閱讀。表達(dá)式從下往上進(jìn)行構(gòu)建,而導(dǎo)數(shù)是由上向下構(gòu)建的。因此每個節(jié)點的導(dǎo)數(shù)大致處于同一水平。

紅色輪廓的節(jié)點表示它們是根節(jié)點,而綠色輪廓則表示為葉節(jié)點,帶有黃色背景的節(jié)點表示為輸入節(jié)點,而虛線箭頭則表示哪個節(jié)點是指向節(jié)點的梯度節(jié)點。

具體而言,比如 c42011e840 (dy/dx) 便表示輸入 c42011e000(即 x)的梯度節(jié)點。

八、節(jié)點渲染

節(jié)點是這樣渲染的:

節(jié)點是這樣渲染的:

補充說明:

  • 如果它是輸入節(jié)點,則 Op 行不會顯示。
  • 如果沒有綁定到節(jié)點的值,將顯示為 NIL。但若有值和梯度存在,它將極盡所能顯示綁定到節(jié)點的值。

九、使用 CUDA

此外,還存在附加要求:

  • 需要 CUDA toolkit 8.0。安裝這個程序?qū)惭b nvcc 編譯器,這是使用 CUDA 運行代碼所必備的。
  • go install github.com/chewxy/gorgonia/cmd/cudagen。這是 cudagen 程序的安裝網(wǎng)址。運行 cudagen 將生成與 Gorgonia 有關(guān)的 CUDA 相關(guān)代碼。
  • 務(wù)必使用 UseCudaFor 選項,務(wù)必使代碼中的 CUDA 操作能夠手動啟用。
  • runtime.LockOSThread() 必須在虛擬內(nèi)存正在運行的主函數(shù)中調(diào)用。CUDA 需要線程親和性,因此必須鎖定 OS 線程。

1. 示例

所以,我們該如何使用 CUDA 呢?假設(shè)有一個文件 main.go:

  1. import (    "fmt" 
  2.     "log" 
  3.     "runtime" 
  4.  
  5.     T "github.com/chewxy/gorgonia" 
  6.     "github.com/chewxy/gorgonia/tensor")func main() {    g :T.NewGraph()    x :T.NewMatrix(g, T.Float32, T.WithName("x"), T.WithShape(100, 100))    y :T.NewMatrix(g, T.Float32, T.WithName("y"), T.WithShape(100, 100))    xpy :T.Must(T.Add(x, y))    xpy2 :T.Must(T.Tanh(xpy))    prog, locMap, _ :T.Compile(g)    m :T.NewTapeMachine(prog, locMap, T.UseCudaFor("tanh")) 
  7.  
  8.     T.Let(x, tensor.New(tensor.WithShape(100, 100), tensor.WithBacking(tensor.Random(tensor.Float32, 100*100)))) 
  9.     T.Let(y, tensor.New(tensor.WithShape(100, 100), tensor.WithBacking(tensor.Random(tensor.Float32, 100*100)))) 
  10.  
  11.     runtime.LockOSThread()    for i :0; i < 1000; i++ {        if err :m.RunAll(); err != nil { 
  12.             log.Fatalf("iteration: %d. Err: %v", i, err) 
  13.         } 
  14.     } 
  15.     runtime.UnlockOSThread() 
  16.  
  17.     fmt.Printf("%1.1f", xpy2.Value()) 

如果它正常運行:

go run main.go

CUDA 不會被使用。

如果程序要使用 CUDA 運行,那么必須進(jìn)行調(diào)用:

  1. go run main.go 

即便如此,也只有 tanh 函數(shù)使用 CUDA。

2. 解釋

使用 CUDA 的要求這么復(fù)雜,主要與其性能有關(guān)。正如 Dave Cheney 的名言:cgo 不是 Go。但不幸的是,使用 CUDA 必定需要 cgo;而若要使用 cgo,則需做出大量權(quán)衡。

因此,解決方案是將 CUDA 相關(guān)代碼嵌套于構(gòu)建標(biāo)記 cuda 中,以這樣的方式默認(rèn)未使用 cgo(好吧,只用了一點點,你仍然可以使用 cblas 或 blase)。

安裝 CUDA toolkit 8.0 的原因是:存在許多 CUDA 計算能力,為它們生成代碼將產(chǎn)生一個毫無益處的巨大二進(jìn)制。相反,用戶會傾向于為他們特定的計算能力編譯。

最后,要求制定使用 CUDA 操作的明確規(guī)范,是由于 cgo 調(diào)用的成本問題。目前為了實現(xiàn)批量的 cgo 調(diào)用而在進(jìn)行額外的努力,但是直到完成之前,該解決方案都會是特定操作的「升級」關(guān)鍵。

3. CUDA 支持的操作

迄今為止,只有極基本的簡單操作能夠支持 CDUA:

元素一元運算:

  • abs
  • sin
  • cos
  • exp
  • ln
  • log2
  • neg
  • square
  • sqrt
  • inv (reciprocal of a number)(數(shù)字的倒數(shù))
  • cube
  • tanh
  • sigmoid
  • log1p
  • expm1
  • softplus

元素二進(jìn)制操作——只有算術(shù)運算支持 CUDA:

  • add
  • sub
  • mul
  • div
  • pow

根據(jù)對作者個人項目的大量剖析,發(fā)現(xiàn)真正重要的是 tanh、sigmoid、expm1、exp 和 cube,即激活函數(shù)。其他使用 MKL + AVX 的操作正常運行,且并非造成神經(jīng)網(wǎng)絡(luò)緩慢的主因。

4. CUDA 的改進(jìn)

在一項次要的基準(zhǔn)測試中,CUDA 的謹(jǐn)慎使用(此情況通常調(diào)用 sigmoid)顯示出非 CUDA 代碼的大幅改進(jìn)(考慮到 CUDA 內(nèi)核十分樸素且未優(yōu)化):

BenchmarkOneMilCUDA-8 300 3348711 ns/op

BenchmarkOneMil-8 50 33169036 ns/op

十、API 的穩(wěn)定性

Gorgonia 的 API 如今并不穩(wěn)定,它將從 1.0 版本開始慢慢穩(wěn)定。

1.0 版本是測試覆蓋率達(dá)到 90%時所定義的,并且相關(guān)的 Tensor 方法已經(jīng)完成。

十一、路線圖

這是依照重要性排序所列出的 Gorgonia 的目標(biāo):

  • 80%以上的測試覆蓋率。目前 Gorgonia 的覆蓋率為 50%,tensor 為 80%。
  • 更高級的操作(如 einsum)。目前的 Tensor 操作符非常原始。
  • 軟件包中的 TravisCI。
  • 軟件包中的 Coveralls。
  • 清除測試。測試是多年積累的結(jié)果,妥當(dāng)?shù)刂貥?gòu)它們將大有裨益。若條件允許,使用表格驅(qū)動測試。
  • 提升性能,特別是應(yīng)當(dāng)重新分配,將系統(tǒng)類型的影響最小化。
  • 將 Op 界面從半輸出公開/更改為全輸出,以此提高 Op 的可擴展性(或者為擴展性創(chuàng)建一個 Compose 的 Op 類型)。這樣每個人都可以制作自定義的 Op。
  • 為了跟隨 CUDA 的實現(xiàn),重構(gòu) CuBLAS 以及 Blase 軟件包。
  • 分布式計算。嘗試多個機器上傳播作業(yè)并彼此通信已至少 3 次,但無一成功。
  • 更好地記錄做出某些決定的原因,并從宏觀上對 Gorgonia 進(jìn)行設(shè)計。
  • 高階導(dǎo)數(shù)優(yōu)化算法(LBFGS)
  • 無導(dǎo)數(shù)的優(yōu)化算法

十二、目標(biāo)

Gorgonia 的主要目標(biāo)是成為一個基于機器學(xué)習(xí)/圖形計算,能夠跨多臺機器進(jìn)行擴展的高性能庫。它應(yīng)將 Go(簡單的編譯和部署過程)的呼吁帶至機器學(xué)習(xí)領(lǐng)域。這條路還很漫長,然而我們已然邁出了第一步。

其次要目標(biāo)是為非標(biāo)準(zhǔn)的深度學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)相關(guān)事物提供一個探索平臺,其中包括 neo-hebbian 學(xué)習(xí)、角切割算法、進(jìn)化算法等。

顯然,由于你在 Github 上閱讀的可能性最大,Github 將構(gòu)建該軟件包工作流程的主要部分以完善該軟件包。

參見:CONTRIBUTING.md

十三、貢獻(xiàn)者與重要貢獻(xiàn)者

我們歡迎任何貢獻(xiàn)。但還有一類新的貢獻(xiàn)者,稱為重要貢獻(xiàn)者。

重要貢獻(xiàn)者是對庫的運作方式和/或其周圍環(huán)境有深刻理解的人。此處舉出重大貢獻(xiàn)者的例子:

  • 撰寫了大量與特定功能/方法的原因/機制,及不同部分相互影響的方式的有關(guān)文檔
  • 編寫代碼,并對 Gorgonia 更復(fù)雜的連接的部分進(jìn)行了測試
  • 編寫代碼和測試,并且至少接受 5 個拉取請求
  • 對軟件包的某些部分提供專家分析(比如你可能是優(yōu)化一個功能的浮點操作專家)
  • 至少回答了 10 個支持性問題

重要貢獻(xiàn)者列表將每月更新一次(如果有人使用 Gorgonia)。

十四、如何獲得支持

如今最好的支持方式,便是在 Github 上留言。

十五、常見問題

為什么在測試中似乎出現(xiàn)了 runtime.GC() 的隨機調(diào)用?

答案非常簡單:軟件包的設(shè)計使其以特定的方式使用 CUDA:具體而言,一個 CUDA 設(shè)備及其景況會綁定一個虛擬內(nèi)存,而不是軟件包。這意味著對于每個創(chuàng)建的虛擬內(nèi)存,其每一設(shè)備每一個虛擬內(nèi)存都會創(chuàng)建不同的 CUDA 景況。因此在其他可能正在使用 CUDA 的應(yīng)用程序中,所有操作都能夠正常運行(然而這需要進(jìn)行壓力測試)。

CUDA 的景況只有在虛擬內(nèi)存回收垃圾(經(jīng)由終結(jié)器函數(shù)的幫助)時才會被銷毀。在測試中大約會創(chuàng)建 100 個虛擬內(nèi)存,并且大多數(shù)垃圾回收是隨機的;當(dāng)景況被使用過多時,會導(dǎo)致 GPU 內(nèi)存耗盡。

因此,在任何可能使用 GPU 的測試結(jié)束時,會調(diào)用 runtime.GC() 來強制垃圾回收,以釋放 GPU 內(nèi)存。

人們在生產(chǎn)過程中不太可能啟動過多的虛擬內(nèi)存,因此這并不是問題。若有問題,請在 Github 上留言,我們會想辦法為虛擬內(nèi)存添加一個 Finish() 方法。

十六、許可

Gorgonia 根據(jù) Apache 2.0 的變體授權(quán)。其所有意圖與目的 Apache 2.0 的許可相同,除了重要貢獻(xiàn)者(如軟件包的商業(yè)支持者),其他人均不能直接從中獲得商業(yè)利潤。但從 Gorgonia 的衍生直接獲利是可行的(如在產(chǎn)品中使用 Gorgonia 作為庫)。所有人都可將 Gorgonia 用于商業(yè)目的(如用于業(yè)務(wù)軟件)。

各類其他版權(quán)聲明

這是在寫 Gorgonia 的過程中有所啟發(fā)和進(jìn)行改編的軟件包和庫(使用的 Go 軟件包已經(jīng)在上文做出了聲明):

【本文是51CTO專欄機構(gòu)機器之心的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2017-06-27 09:43:43

Python機器學(xué)習(xí)

2017-07-05 14:21:30

框架TensorFlowTheano

2017-03-01 13:36:41

TensorFlowTheano框架

2020-02-25 15:04:48

深度學(xué)習(xí)編程人工智能

2024-12-13 16:28:43

2023-03-28 08:29:52

2017-03-16 08:46:43

TensorFlow安裝入門

2018-03-15 11:50:53

機器學(xué)習(xí)入門Tensorflow

2013-03-22 10:55:06

Go

2017-11-29 08:50:01

2023-04-12 08:43:25

2022-04-26 09:23:07

Hare編程語言C

2024-09-29 16:04:14

2021-11-02 09:40:50

TensorFlow機器學(xué)習(xí)人工智能

2021-07-30 07:28:15

WorkerPoolGo語言

2021-04-07 09:02:49

Go 語言變量與常量

2021-04-13 07:58:42

Go語言函數(shù)

2020-05-19 14:29:50

機器學(xué)習(xí)TensorFlow

2020-08-25 10:30:59

TensorFlow數(shù)據(jù)機器學(xué)習(xí)

2017-03-02 08:28:09

科技新聞早報
點贊
收藏

51CTO技術(shù)棧公眾號