Go 向けに設計された機械学習ライブラリ Gorgonia: TensorFlow や Theano のライバル

Go 向けに設計された機械学習ライブラリ Gorgonia: TensorFlow や Theano のライバル

[[184558]]

Gorgonia は、Go での機械学習を容易にし、多次元配列を含む数式の記述と評価を容易にするライブラリです。これが Theano や TensorFlow によく似ているように思えるのは、これら 3 つの背後にある考え方が非常に似ているためです。具体的には、Gorgonia は Theano のようにかなり低レベルですが、Tensorflow のようにより高い目標を持っています。

プロジェクトアドレス: https://github.com/chewxy/gorgonia

プロジェクト紹介: https://blog.chewxy.com/2016/09/19/gorgonia/

  • 自動微分化が実行可能
  • 実行可能な記号微分
  • 勾配降下法による最適化を実行できる
  • 実行可能な数値安定性
  • ニューラルネットワークの作成に役立つ多くの便利な関数を提供します
  • 非常に高速(TheanoやTensorflowに匹敵)
  • CUDA / GPGPU コンピューティングをサポート (OpenCL はまだサポートされていないため、プル リクエストを送信する必要があります)
  • 分散コンピューティングをサポートする

1. Gorgonia を選ぶ理由

Gorgonia の使用は主に開発者の利便性のためです。 Go スタックを広範に使用すると、使い慣れた快適な環境で本番環境に対応した機械学習システムを作成できます。

機械学習/AI は、多くの場合、(a) 複数のモデルを構築してテストと再テストを行うパイロット フェーズと、(b) テストと試行後にモデルを展開する展開フェーズの 2 つのフェーズに大別されます。これら 2 つの段階は不可欠であり、データ サイエンティストとデータ エンジニアの違いと同様に、異なる機能を持っています。

原則として、これら 2 つのフェーズで使用されるツールも異なります。実験フェーズでは通常、Python/Lua (Theano、Torch などを使用) が使用され、その後、モデルは C++ (dlib、mlpack などを使用) などのより高性能な言語で書き直されます。もちろん、最近ではそのギャップは徐々に縮まってきており、ギャップを埋めるために使用できる Tensorflow などのツールを共有する人が増えています。

Gorgonia の目的は、Go 環境で同じことを実現することです。現在、Gorgonia は非常に高性能で、速度は Theano や Tensorflow に匹敵します (現在の CUDA バグのため、Gorgonia の公式ベンチマークはまだ実行されていません。また、実装が若干異なる可能性があるため、正確な比較モデルを比較することは困難です)。

2. インストール

インストール パッケージは go-get です: go get -u github.com/chewxy/gorgonia。

Gorgonia は依存関係が少なく安定しているため、現時点ではホスティング ツールは必要ありません。次の表は、Gorgonia によって呼び出される外部パッケージを、依存する順序で並べたリストです (サブパッケージは省略)。

3. 最新情報を入手する

Gorgonia プロジェクトにはメーリング リストと Twitter アカウントがあり、公式の更新情報やお知らせが投稿されます。

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

IV. 使用法

Gorgonia は計算グラフを作成し、それを実行することで動作します。数学関数に限定されたプログラミング言語として考えてください。実際、これはユーザーが考えるべき主な例であるはずです。作成される計算グラフは AST です。

Microsoft CNTK の BrainScript は、計算グラフの構築と実行は同じではないため、ユーザーはこの 2 つに対して異なる思考パターンを使用する必要があることを示す最適な例かもしれません。

Gorgonia の実装では CNTK の BrainScript のように思考の分離を強制しませんが、構文は少し役立ちます。

次に例を示します。数式 z = x + y を定義する場合は、次のようにします。

  1. パッケージ mainimport ( "fmt"
  2. "ログ"
  3.  
  4. . "github.com/chewxy/gorgonia")func main() { g : = NewGraph () var x, y, z *Node var err error
  5.  
  6. // 式を定義する
  7. x = NewScalar (g、Float64、WithName("x"))
  8. y = NewScalar (g、Float64、WithName("y"))
  9. z, err = err != nil の場合は (x, y)を加算します{
  10. ログ.致命的(エラー)
  11. } // プログラムにコンパイルする
  12. prog, locMap, err : =コンパイル(g) if err != nil {
  13. ログ.致命的(エラー)
  14. } // プログラムを実行するためのVMを作成する
  15. machine : = NewTapeMachine (prog, locMap) // 初期値を設定して実行
  16. let(x, 2.0) let(y, 2.5) if machine.RunAll() != nil {
  17. ログ.致命的(エラー)
  18. }
  19.  
  20. fmt.Printf("%v", z.Value()) // 出力: 4.5}

他の同様のパッケージよりも冗長であると思われるかもしれません。たとえば、Gorgonia は呼び出し可能な関数にコンパイルされるのではなく、TapeMachine の実行を必要とするプログラムに特別にコンパイルされます。さらに、Let(...) を手動で呼び出す必要もあります。

著者は、これは良いことだと考えています。人間の思考を機械の思考に変換できるからです。何が間違っていたのかを知りたいときに役立ちます。

5. 仮想メモリシステム

Gorgonia の現在のバージョンには 2 つの仮想メモリ システムがあります。

  • テープマシン
  • Lispマシン

それらは機能が異なり、異なる入力を受け取ります。 TapeMachine は一般に、静的な式 (つまり、計算グラフが変更されない式) を実行するのに優れています。静的な性質のため、一度記述して何度も実行する式 (線形回帰、SVM など) に適しています。

LispMachine はグラフを入力として受け取り、グラフのノード上で直接実行します。グラフィックが変更された場合は、新しい Lightweight LispMachine を作成して実行するだけです。 LispMachine は、可変サイズの再帰型ニューラル ネットワークの作成などのタスクに適しています。

Gorgonia がリリースされる前は、スタックベースで TapeMachine に似ていたが、人工的な勾配をより適切に処理できる 3 番目の仮想メモリがありました。著者がすべての問題点を解決すれば、ついに日の目を見ることになるかもしれない。

6. 差別化

Gorgonia は記号微分と自動微分の両方を実行しますが、これら 2 つのプロセスは微妙に異なります。著者は、次のように理解するのが最も適切であると考えています。自動微分は実行時に実行される微分であり、グラフの実行と同時に発生します。記号微分は書き込み段階で実行される微分です。

ここで、「ランタイム」とは、もちろん、プログラムの実際の実行ではなく、式グラフの実行を指します。

これら 2 つの仮想メモリ システムを導入すると、Gorgonia が記号微分と自動微分をどのように実行するかを簡単に理解できます。上記と同じ例を使用すると、ここでは微分化が行われていないことがわかります。今回はLispMachineで試してみましょう:

  1. パッケージ mainimport ( "fmt"
  2. "ログ"
  3.  
  4. . "github.com/chewxy/gorgonia")func main() { g : = NewGraph () var x, y, z *Node var err error
  5.  
  6. // 式を定義する
  7. x = NewScalar (g、Float64、WithName("x"))
  8. y = NewScalar (g、Float64、WithName("y"))
  9. z, err = err != nil の場合は (x, y)を加算します{
  10. ログ.致命的(エラー)
  11. } // 初期値を設定して実行
  12. Let(x, 2.0) Let(y, 2.5) // デフォルトでは、LispMachineは順方向モードと逆方向モードの実行を実行します
  13. m : = NewLispMachine (g) m.RunAll() != nil の場合 {
  14. ログ.致命的(エラー)
  15. }
  16.  
  17. fmt.Printf("z: %v\n", z.Value()) xgrad, err : = x .Grad() err != nil の場合 {
  18. ログ.致命的(エラー)
  19. }
  20. fmt.Printf("dz/dx: %v\n", xgrad) ygrad, err : = y .Grad() err != nil の場合 {
  21. ログ.致命的(エラー)
  22. }
  23. fmt.Printf("dz/dy: %v\n", ygrad) // 出力:
  24. // 高さ: 4.5
  25. // dz/dx: 1
  26. // dz/dy: 1}

もちろん、Gorgonia は Theano のような、より伝統的な記号微分化もサポートしています。

  1. パッケージ mainimport ( "fmt"
  2. "ログ"
  3.  
  4. . "github.com/chewxy/gorgonia")func main() { g : = NewGraph () var x, y, z *Node var err error
  5.  
  6. // 式を定義する
  7. x = NewScalar (g、Float64、WithName("x"))
  8. y = NewScalar (g、Float64、WithName("y"))
  9. z, err = err != nil の場合は (x, y)を加算します{
  10. ログ.致命的(エラー)
  11. } // x と y に関して z を記号的に微分する
  12. // これはグラフ g に勾配ノードを追加します
  13. var grads ノード
  14. grads, err = Grad (z, x, y) err != nil の場合 {
  15. ログ.致命的(エラー)
  16. } // プログラムにコンパイルする
  17. prog, locMap, err : =コンパイル(g) if err != nil {
  18. ログ.致命的(エラー)
  19. } // プログラムを実行するためのVMを作成する
  20. machine : = NewTapeMachine (prog, locMap) // 初期値を設定して実行
  21. let(x, 2.0) let(y, 2.5) if machine.RunAll() != nil {
  22. ログ.致命的(エラー)
  23. }
  24.  
  25. fmt.Printf("z: %v\n", z.Value()) xgrad, err : = x .Grad() err != nil の場合 {
  26. ログ.致命的(エラー)
  27. }
  28. fmt.Printf("dz/dx: %v | %v\n", xgrad, grads[0]) ygrad, err : = y .Grad() err != nil の場合 {
  29. ログ.致命的(エラー)
  30. }
  31. fmt.Printf("dz/dy: %v | %v\n", ygrad, grads[1]) // 出力:
  32. // 高さ: 4.5
  33. // dz/dx: 1 | 1
  34. // dz/dy: 1 | 1}

Gorgonia には、dualValue が存在する場合に順方向モードの微分化をサポートする古いバージョンの痕跡がありますが、現在は逆方向モードの自動微分化 (別名バックプロパゲーション) のみを実行します。将来的には、フォワードモードの差別化が復活する可能性があります。

7. チャート

計算グラフや表現グラフについてはよく話題になりますが、それは正確には何でしょうか? 必要な数式の AST と考えてください。上記の例のグラフを以下に示します (ただし、ベクトルが 1 つ追加され、スカラーが 1 つ追加されています)。

ちなみに、Gorgonia はグラフィック印刷がとても得意です。以下は方程式 y = x² とその導関数のグラフの例です。

グラフィックは読みやすいです。式は下から上に構築されますが、導関数は上から下に構築されます。したがって、各ノードの導関数はほぼ同じレベルになります。

赤いアウトラインのノードはルート ノードであることを示し、緑のアウトラインのノードはリーフ ノード、黄色の背景のノードは入力ノードであり、破線の矢印はどのノードがそのノードを指しているグラデーション ノードであるかを示します。

具体的には、たとえば、c42011e840 (dy/dx) は、入力 c42011e000 (つまり x) の勾配ノードを表します。

8. ノードレンダリング

ノードは次のようにレンダリングされます。

追加メモ:

  • 入力ノードの場合、Op 行は表示されません。
  • ノードに値がバインドされていない場合は、NIL として表示されます。ただし、値とグラデーションが存在する場合は、ノードにバインドされた値を表示するように最善を尽くします。

9. CUDAの使用

さらに、追加の要件があります。

  • CUDA ツールキット 8.0 が必要です。このプログラムをインストールすると、CUDA を使用してコードを実行するために必要な nvcc コンパイラがインストールされます。
  • github.com/chewxy/gorgonia/cmd/cudagen をインストールしてください。これは cudagen プログラムのインストール URL です。 cudagen を実行すると、Gorgonia に関連付けられた CUDA 関連のコードが生成されます。
  • コード内で CUDA 操作を手動で有効にするには、常に UseCudaFor オプションを使用します。
  • 仮想メモリが実行されているメイン関数からruntime.LockOSThread() を呼び出す必要があります。 CUDA ではスレッド アフィニティが必要なので、OS スレッドをロックする必要があります。

1. 例

では、CUDA はどのように使用すればいいのでしょうか? main.go というファイルがあるとします。

  1. インポート ( "fmt"
  2. "ログ"
  3. "ランタイム"
  4.  
  5. T "github.com/chewxy/gorgonia"
  6. , _ : = 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, テンソル.New(テンソル.WithShape(100, 100), テンソル.WithBacking(テンソル.Random(テンソル.Float32, 100*100))))
  10.  
  11. i : = 0 の場合、runtime.LockOSThread() ; i <   1000 ; i++ { err : = m .RunAll(); err != nil {
  12. log.Fatalf("反復: %d。エラー: %v", i, err)
  13. }
  14. }
  15. ランタイム.OSThread のロックを解除します。
  16.  
  17. fmt.Printf("%1.1f", xpy2.Value())
  18. }

正常に動作する場合:

main.go を実行します

CUDAは使用されません。

プログラムを CUDA を使用して実行するには、以下を呼び出す必要があります。

  1. main.go を実行します

それでも、CUDA を使用するのは tanh 関数だけです。

2. 説明

CUDA を使用するための要件は非常に複雑で、主にそのパフォーマンスに関連しています。 Dave Cheney の有名な言葉に「cgo は Go ではない」というのがあります。残念ながら、CUDA を使用するには cgo が必要であり、cgo を使用するといくつかのトレードオフが伴います。

したがって、解決策は、CUDA 関連コードをビルド フラグ cuda 内にネストすることです。この方法では、cgo はデフォルトでは使用されません (まあ、少しだけですが、cblas または blase は引き続き使用できます)。

CUDA ツールキット 8.0 をインストールする理由は、CUDA には多くのコンピューティング機能があり、それらのコードを生成するとメリットのない巨大なバイナリが生成されるためです。代わりに、ユーザーは特定のコンピューティング機能に合わせてコンパイルする傾向があります。

最後に、CUDA 操作の使用を明示的に指定する必要があるのは、cgo 呼び出しのコストのためです。現在、cgo 呼び出しのバッチ処理を可能にするための追加作業が進行中ですが、それが完了するまで、このソリューションは特定の操作の「アップグレード」キーになります。

3. CUDAでサポートされている操作

これまでのところ、CDUA でサポートされているのは非常に基本的な単純な操作のみです。

要素ごとの単項演算:

  • 腹筋
  • コス
  • 経験
  • ログ2
  • 否定的
  • 四角
  • 平方根
  • inv(数の逆数)
  • キューブ
  • タン
  • シグモイド
  • ログ1p
  • 式1
  • ソフトプラス

要素ごとのバイナリ演算 - CUDA では算術演算のみがサポートされています。

  • 追加
  • サブ
  • マル
  • 分割
  • 捕虜

著者の個人プロジェクトを多数分析した結果、本当に重要なのは tanh、sigmoid、expm1、exp、cube、つまり活性化関数であることがわかりました。 MKL + AVX を使用したその他の操作は正常に動作し、ニューラル ネットワークの速度低下の主な原因ではありません。

4. CUDAの改善

マイナーなベンチマークでは、CUDA を慎重に使用すると (この場合は sigmoid の呼び出し)、非 CUDA コードに比べて大幅な改善が見られます (CUDA カーネルは非常に素朴で最適化されていないことを考慮すると)。

ベンチマークOneMilCUDA-8 300 3348711 ns/op

ベンチマークOneMil-8 50 33169036 ns/op

10. APIの安定性

Gorgonia の API は現在安定していませんが、バージョン 1.0 から徐々に安定していきます。

バージョン 1.0 は、テスト カバレッジが 90% に達し、関連する Tensor メソッドが完了したときに定義されます。

11. ロードマップ

ゴルゴニアの目標は重要度順に次のとおりです。

  • テストカバレッジは 80% 以上です。現在、Gorgonia のカバー率は 50%、tensor のカバー率は 80% です。
  • より高度な操作 (einsum など)。現在のテンソル演算子は非常に原始的です。
  • TravisCI のパッケージ。
  • パッケージ内のカバーオール。
  • テストをクリアしました。テストは長年の蓄積の結果であり、適切にリファクタリングすると大きなメリットが得られます。可能な場合はテーブル駆動型テストを使用します。
  • 特にパフォーマンスの向上は、システム タイプの影響を最小限に抑えるために再割り当てする必要があります。
  • Op インターフェースをセミエクスポートからフルエクスポートに公開/変更して、Op の拡張性を高めます (または、拡張性のために Compose Op タイプを作成します)。この方法で誰でもカスタム Op を作成できます。
  • CuBLAS および Blase パッケージは、CUDA 実装に従うようにリファクタリングされました。
  • 分散コンピューティング。ジョブを複数のマシンに分散し、それらのマシンが相互に通信するように少なくとも 3 回試みましたが、どれも機能しませんでした。
  • 特定の決定が行われた理由をより適切に文書化し、Gorgonia を高レベルで設計します。
  • 高階微分最適化アルゴリズム (LBFGS)
  • 導関数を使わない最適化アルゴリズム

12. 目的

Gorgonia の主な目標は、複数のマシンにまたがって拡張できる、機械学習/グラフ コンピューティング用の高性能ライブラリになることです。 Go の魅力 (シンプルなコンパイルとデプロイメントのプロセス) を機械学習の分野にもたらすはずです。道のりはまだ長いですが、私たちは最初の一歩を踏み出しました。

2 番目の目標は、ネオヘブ学習、コーナーカットアルゴリズム、進化アルゴリズムなど、非標準のディープラーニングとニューラルネットワーク関連の探索プラットフォームを提供することです。

明らかに、この記事を Github で読んでいる可能性が高いので、パッケージを完成させるために Github がパッケージ ワークフローの主要部分を構築することになります。

参照: CONTRIBUTING.md

13. 貢献者と重要な貢献者

あらゆる貢献を歓迎します。しかし、重要な貢献者と呼ばれる新しい貢献者のカテゴリーがあります。

重要な貢献者とは、図書館の仕組みやその周囲の環境について深い理解を持つ人々です。重要な貢献者の例をいくつか挙げます。

  • 特定の機能やメソッドの理由や仕組み、またさまざまな部分がどのように相互作用するかについて、詳細なドキュメントを作成しました。
  • Gorgoniaのより複雑な接続のいくつかをコードで記述しテストしました
  • コードとテストを書いて、少なくとも5つのプルリクエストを受け入れる
  • パッケージの一部について専門的な分析を提供する(たとえば、関数内の浮動小数点演算の最適化の専門家であるなど)
  • 少なくとも10件のサポート質問に回答しました

注目すべき貢献者のリストは毎月更新されます (Gorgonia を使用している人がいる場合)。

14. サポートを受ける方法

現時点で私たちをサポートする最善の方法は、Github にコメントを残すことです。

15. よくある質問

テストでruntime.GC()へのランダムな呼び出しが表示されるのはなぜですか?

答えは非常に簡単です。ソフトウェア パッケージは、CUDA を特定の方法で使用するように設計されています。具体的には、CUDA デバイスとそのコンテキストは、ソフトウェア パッケージではなく仮想メモリにバインドされます。つまり、作成された仮想メモリごとに、デバイスと仮想メモリごとに異なる CUDA コンテキストが作成されることになります。したがって、CUDA を使用している可能性のある他のアプリケーションでもすべて正常に動作するはずです (ただし、ストレス テストが必要になります)。

CUDA コンテキストは、仮想メモリがガベージ コレクションされたときのみ破棄されます (ファイナライザー関数の助けを借りて)。テスト中、約 100 個の仮想メモリが作成され、ほとんどのガベージ コレクションはランダムに行われました。シーンが過度に使用されると、GPU メモリが枯渇することになります。

したがって、GPU を使用する可能性のあるテストの最後には、runtime.GC() が呼び出され、ガベージ コレクションが強制的に実行され、GPU メモリが解放されます。

実稼働環境では仮想メモリを過剰に有効にする可能性は低いため、これは問題にはなりません。ご質問がある場合は、Github にコメントを残してください。仮想メモリに Finish() メソッドを追加する方法を見つけます。

16. ライセンス

Gorgonia は Apache 2.0 のバリアントに基づいてライセンスされています。実質的には Apache 2.0 ライセンスと同一ですが、重要な貢献者 (パッケージの商業的サポーターなど) 以外は誰も直接利益を得ることができません。 Gorgonia の派生作品から直接利益を得ることは可能です (例: Gorgonia を製品のライブラリとして使用する)。誰でも Gorgonia を商用目的(ビジネス ソフトウェアなど)で使用できます。

その他著作権に関する注意事項

これらは、Gorgonia の作成プロセスでインスピレーションを得て適応されたパッケージとライブラリです (使用された Go パッケージは上記に記載されています)。

[この記事は、51CTOコラムニストのMachine Heart、WeChatパブリックアカウント「Machine Heart(id:almosthuman2014)」によるオリジナル翻訳です]

この著者の他の記事を読むにはここをクリックしてください

<<:  人工知能は企業の組織化の方法をどのように変えるのでしょうか?

>>:  相関ルール推奨アルゴリズムの原理と実装

ブログ    
ブログ    
ブログ    

推薦する

知っておくべき 19 の実用的なコンソール デバッグのヒント!

みなさんこんにちは、CUGGZです。ブラウザの開発者ツールは、DOM ツリー構造の表示、CSS スタ...

EU、生成AIツールの規制について暫定合意に達する:これまでで最も包括的な規則

12月9日、ワシントンポスト紙やエンガジェットなどの海外メディアの報道によると、世界各国がAIの急速...

CVPR 自動運転チャレンジで優勝したのはどのようなソリューションでしょうか?

道路は複雑で、車両の種類も多様で、歩行者も密集しています。これが都市部の道路交通の現状であり、自動運...

...

GAN は教師なし表現学習に使われており、その効果は今でも驚くべきものです...

全能の GAN がまたひとつの丘を征服しました。近年、DeepMindが提案したBigGANなど、G...

ビッグデータ、クラウドコンピューティング、人工知能は密接に結びついている

今の時代、どんな製品の開発にも実は学習プロセスが必要です。人工知能技術が急速に進歩したのは、まさに各...

AIチップブラックテクノロジーインベントリ

ビッグデータとディープラーニングの利用が増えるにつれて、基盤となるハードウェアとチップに新たな要件が...

ドライバーの状態行動を識別できる監視システムは、実際には十分に正確で信頼できるものではない

ドライバーモニタリングシステム(DMS)は、近年、自動車市場で注目を集めています。 DMS の出現に...

人工知能に関してどのような基礎教育が必要でしょうか?

人工知能の基礎教育を強化することは、将来の社会の発展に備えるための避けられない選択であり、要件です。...

オープンソースモデル「幻覚」はより深刻です。これは3段階の幻覚検出キットです

大規模モデルには、幻覚を生成するという致命的な問題が長い間存在していました。データセットの複雑さによ...

AI テクノロジーは二酸化炭素排出量とどのような関係があるのでしょうか?

現在、世界のビジネスで大きな波を起こしている大きなトレンドが 2 つあります。 1 つ目は、企業が生...

聞いてください、トランスフォーマーはサポートベクターマシンです

Transformer は、学界で議論を巻き起こしたサポート ベクター マシン (SVM) の新しい...

お金は人を幸せにできるのでしょうか?機械学習を使って答えを見つける方法を教えます

機械学習システムを分類する 1 つの方法は、一般化の程度によって分類することです。ほとんどの機械学習...

...