成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為Go語言設計的機器學習庫Gorgonia:對標TensorFlow與Theano

開發 開發工具 機器學習
Gorgonia 是一個促進在 Go 中進行機器學習的庫,旨在更容易地編寫與評估涉及多維數組的數學方程。具體而言,Gorgonia 像 Theano 一樣相當低級;但又像 Tensorflow 一樣具有更高目標。

[[184558]]

Gorgonia 是一個促進在 Go 中進行機器學習的庫,旨在更容易地編寫與評估涉及多維數組的數學方程。如果這聽起來很像 Theano 或者 TensorFlow,原因是三者的想法非常相似。具體而言,Gorgonia 像 Theano 一樣相當低級;但又像 Tensorflow 一樣具有更高目標。

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

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

  • 可執行自動微分
  • 可執行符號微分
  • 可執行梯度下降優化
  • 可執行數值穩定
  • 提供了許多便利功能,以助于創建神經網絡
  • 非常快(與 Theano 和 Tensorflow 的速度相當)
  • 支持 CUDA / GPGPU 計算(OpenCL 尚不支持,需發送拉取請求)
  • 將支持分布式計算

一、為何選擇 Gorgonia?

Gorgonia 的使用主要方便了開發者。如果你使用 Go 廣泛地堆棧,便可以在熟悉而舒適的環境中創建生產就緒的機器學習系統。

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

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

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

二、安裝

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

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

 Gorgonia 所調用的外部軟件包列表

三、保持更新

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

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

四、用法

Gorgonia 通過創建計算圖來工作,而后將其執行。請把它當作一種僅限于數學函數方面的編程語言;事實上,這應當作為用戶思考的主要實例。它創建的計算圖是一個 AST。

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

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

此處舉出一個實例——若要定義一個數學表達式 z = x + y,應當這樣做:

  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} 

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

作者卻認為這是好事——能夠將人的思維轉變為機器的思維。它在我們想查清哪里出錯的時候很有幫助。

五、虛擬內存系統

當前版本的 Gorgonia 有兩個虛擬內存系統:

  • TapeMachine
  • LispMachine

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

LispMachine 則是將圖形設為輸入,并直接在圖形的節點上執行。如果圖形有所改變,只需新創建一個輕量級 LispMachine 來執行便可。LispMachine 適于諸如創建大小不固定的循環神經網絡這類的任務。

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

六、微分

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

此處「運行時」當然是指表達式圖的執行,而非程序的實際運行。

通過介紹這兩個虛擬內存系統,便很容易理解 Gorgonia 如何執行符號與自動微分。使用與上文相同的示例,讀者 能夠發現此處并沒有進行微分。這次用 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} 

當然,Gorgonia 同樣支持更傳統的的符號微分,比如在 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 存在條件下進行正向模式微分的舊版痕跡,但其目前僅執行反向模式自動微分(又名反向傳播)。正向模式微分也許在將來能夠回歸。

七、圖表

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

數學表達式的 AST

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

方程式 y = x2 及其導數的圖形示例

圖形很容易閱讀。表達式從下往上進行構建,而導數是由上向下構建的。因此每個節點的導數大致處于同一水平。

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

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

八、節點渲染

節點是這樣渲染的:

節點是這樣渲染的:

補充說明:

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

九、使用 CUDA

此外,還存在附加要求:

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

1. 示例

所以,我們該如何使用 CUDA 呢?假設有一個文件 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 運行,那么必須進行調用:

  1. go run main.go 

即便如此,也只有 tanh 函數使用 CUDA。

2. 解釋

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

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

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

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

3. CUDA 支持的操作

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

元素一元運算:

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

元素二進制操作——只有算術運算支持 CUDA:

  • add
  • sub
  • mul
  • div
  • pow

根據對作者個人項目的大量剖析,發現真正重要的是 tanh、sigmoid、expm1、exp 和 cube,即激活函數。其他使用 MKL + AVX 的操作正常運行,且并非造成神經網絡緩慢的主因。

4. CUDA 的改進

在一項次要的基準測試中,CUDA 的謹慎使用(此情況通常調用 sigmoid)顯示出非 CUDA 代碼的大幅改進(考慮到 CUDA 內核十分樸素且未優化):

BenchmarkOneMilCUDA-8 300 3348711 ns/op

BenchmarkOneMil-8 50 33169036 ns/op

十、API 的穩定性

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

1.0 版本是測試覆蓋率達到 90%時所定義的,并且相關的 Tensor 方法已經完成。

十一、路線圖

這是依照重要性排序所列出的 Gorgonia 的目標:

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

十二、目標

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

其次要目標是為非標準的深度學習和神經網絡相關事物提供一個探索平臺,其中包括 neo-hebbian 學習、角切割算法、進化算法等。

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

參見:CONTRIBUTING.md

十三、貢獻者與重要貢獻者

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

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

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

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

十四、如何獲得支持

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

十五、常見問題

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

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

CUDA 的景況只有在虛擬內存回收垃圾(經由終結器函數的幫助)時才會被銷毀。在測試中大約會創建 100 個虛擬內存,并且大多數垃圾回收是隨機的;當景況被使用過多時,會導致 GPU 內存耗盡。

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

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

十六、許可

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

各類其他版權聲明

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

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

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

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2017-06-27 09:43:43

Python機器學習

2017-07-05 14:21:30

框架TensorFlowTheano

2020-02-25 15:04:48

深度學習編程人工智能

2017-03-01 13:36:41

TensorFlowTheano框架

2024-12-13 16:28:43

2023-03-28 08:29:52

2018-03-15 11:50:53

機器學習入門Tensorflow

2017-03-16 08:46:43

TensorFlow安裝入門

2013-03-22 10:55:06

Go

2023-04-12 08:43:25

2017-11-29 08:50:01

2022-04-26 09:23:07

Hare編程語言C

2024-09-29 16:04:14

2020-08-25 10:30:59

TensorFlow數據機器學習

2021-11-02 09:40:50

TensorFlow機器學習人工智能

2021-07-30 07:28:15

WorkerPoolGo語言

2021-04-13 07:58:42

Go語言函數

2021-04-07 09:02:49

Go 語言變量與常量

2020-05-19 14:29:50

機器學習TensorFlow

2020-12-07 10:09:43

機器學習金融行業深度學習
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久xx| 久久99蜜桃综合影院免费观看 | 亚洲精品一区二区三区中文字幕 | 天天干人人 | 欧美亚洲在线 | 亚洲成人av | 国产剧情一区二区三区 | 久久久久久久av | 一级大片免费 | 日韩一区二区三区在线视频 | 国产综合网址 | 天天插天天操 | 国产精品亚洲第一区在线暖暖韩国 | 二区国产| 99久久久国产精品 | 久久国产精品视频观看 | 日韩精品一区二区三区视频播放 | 日本精品在线一区 | 国产精品久久久久久久久免费相片 | 色片在线观看 | 久久久免费电影 | 欧美精品一级 | 成人免费毛片片v | 欧美精品一区二区三区在线 | 色在线免费视频 | www.久久国产精品 | 国产欧美一区二区三区国产幕精品 | 久久久久久久香蕉 | 成人a视频片观看免费 | 国产精品久久久爽爽爽麻豆色哟哟 | 一区二区三区四区国产 | 亚洲精品久久久久久久久久吃药 | 欧美日韩国产高清 | 日韩av一区二区在线观看 | www中文字幕| 91在线观 | www.玖玖玖 | av片免费观看 | 久久久久久久一区二区三区 | 久草新在线 | 国产精品久久av |