forked from gorgonia/gorgonia.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.json
127 lines (127 loc) · 23.7 KB
/
index.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
[
{
"uri": "https://gorgonia.org/support/faq/",
"title": "FAQ",
"tags": [],
"description": "",
"content": " Why are there seemingly random runtime.GC() calls in the tests? The answer to this is simple - the design of the package uses CUDA in a particular way: specifically, a CUDA device and context is tied to a VM, instead of at the package level. This means for every VM created, a different CUDA context is created per device per VM. This way all the operations will play nicely with other applications that may be using CUDA (this needs to be stress-tested, however).\nThe CUDA contexts are only destroyed when the VM gets garbage collected (with the help of a finalizer function). In the tests, about 100 VMs get created, and garbage collection for the most part can be considered random. This leads to cases where the GPU runs out of memory as there are too many contexts being used.\nTherefore at the end of any tests that may use GPU, a runtime.GC() call is made to force garbage collection, freeing GPU memories.\nIn production, one is unlikely to start that many VMs, therefore it\u0026rsquo;s not really a problem. If there is, open a ticket on Github, and we\u0026rsquo;ll look into adding a Finish() method for the VMs.\n"
},
{
"uri": "https://gorgonia.org/about/",
"title": "Why use Gorgonia? ",
"tags": [],
"description": "",
"content": "The main reason to use Gorgonia is developer comfort. If you\u0026rsquo;re using a Go stack extensively, now you have access to the ability to create production-ready machine learning systems in an environment that you are already familiar and comfortable with.\nML/AI at large is usually split into two stages: the experimental stage where one builds various models, test and retest; and the deployed state where a model after being tested and played with, is deployed. This necessitate different roles like data scientist and data engineer.\nTypically the two phases have different tools: Python/Lua (using Theano, Torch, etc) is commonly used for the experimental stage, and then the model is rewritten in some more performant language like C++ (using dlib, mlpack etc). Of course, nowadays the gap is closing and people frequently share the tools between them. Tensorflow is one such tool that bridges the gap.\nGorgonia aims to do the same, but for the Go environment. Gorgonia is currently fairly performant - its speeds are comparable to Theano\u0026rsquo;s and Tensorflow\u0026rsquo;s CPU implementations. GPU implementations are a bit finnicky to compare due to the heavy cgo tax, but rest assured that this is an area of active improvement.\n"
},
{
"uri": "https://gorgonia.org/usage/vm/",
"title": "VM",
"tags": [],
"description": "",
"content": "There are two VMs in the current version of Gorgonia:\n TapeMachine LispMachine They function differently and take different inputs. The TapeMachine is useful for executing expressions that are generally static (that is to say the computation graph does not change). Due to its static nature, the TapeMachine is good for running expressions that are compiled-once-run-many-times (such as linear regression, SVM and the like).\nThe LispMachine on the other hand was designed to take a graph as an input, and executes directly on the nodes of the graph. If the graph change, simply create a new lightweight LispMachine to execute it on. The LispMachine is suitable for tasks such as creating recurrent neural networks without a fixed size.\nPrior to release of Gorgonia, there was a third VM - a stack based VM that is similar to TapeMachine but deals with artificial gradients better. It may see light of day again, once this author has managed to fix all the kinks.\n"
},
{
"uri": "https://gorgonia.org/usage/differenciation/",
"title": "Differentiation",
"tags": [],
"description": "",
"content": "Gorgonia performs both symbolic and automatic differentiation. There are subtle differences between the two processes. The author has found that it\u0026rsquo;s best to think of it this way - Automatic differentiation is differentiation that happens at runtime, concurrently with the execution of the graph, while symbolic differentiation is differentiation that happens during the compilation phase.\nRuntime of course, refers to the execution of the expression graph, not the program\u0026rsquo;s actual runtime.\nWith the introduction to the two VMs, it\u0026rsquo;s easy to see how Gorgonia can perform both symbolic and automatic differentiation. Using the same example as above, the reader should note that there was no differentiation done. Instead, let\u0026rsquo;s try with a LispMachine:\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; . \u0026#34;gorgonia.org/gorgonia\u0026#34; ) func main() { g := NewGraph() var x, y, z *Node var err error // define the expression \tx = NewScalar(g, Float64, WithName(\u0026#34;x\u0026#34;)) y = NewScalar(g, Float64, WithName(\u0026#34;y\u0026#34;)) z, err = Add(x, y) if err != nil { log.Fatal(err) } // set initial values then run \tLet(x, 2.0) Let(y, 2.5) // by default, LispMachine performs forward mode and backwards mode execution \tm := NewLispMachine(g) if m.RunAll() != nil { log.Fatal(err) } fmt.Printf(\u0026#34;z: %v\\n\u0026#34;, z.Value()) xgrad, err := x.Grad() if err != nil { log.Fatal(err) } fmt.Printf(\u0026#34;dz/dx: %v\\n\u0026#34;, xgrad) ygrad, err := y.Grad() if err != nil { log.Fatal(err) } fmt.Printf(\u0026#34;dz/dy: %v\\n\u0026#34;, ygrad) // Output: \t// z: 4.5 \t// dz/dx: 1 \t// dz/dy: 1 } Of course, Gorgonia also supports the more traditional symbolic differentiation like in Theano:\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; . \u0026#34;gorgonia.org/gorgonia\u0026#34; ) func main() { g := NewGraph() var x, y, z *Node var err error // define the expression \tx = NewScalar(g, Float64, WithName(\u0026#34;x\u0026#34;)) y = NewScalar(g, Float64, WithName(\u0026#34;y\u0026#34;)) z, err = Add(x, y) if err != nil { log.Fatal(err) } // symbolically differentiate z with regards to x and y \t// this adds the gradient nodes to the graph g \tvar grads Nodes grads, err = Grad(z, x, y) if err != nil { log.Fatal(err) } // create a VM to run the program on \tmachine := NewTapeMachine(g) // set initial values then run \tLet(x, 2.0) Let(y, 2.5) if machine.RunAll() != nil { log.Fatal(err) } fmt.Printf(\u0026#34;z: %v\\n\u0026#34;, z.Value()) xgrad, err := x.Grad() if err != nil { log.Fatal(err) } fmt.Printf(\u0026#34;dz/dx: %v | %v\\n\u0026#34;, xgrad, grads[0]) ygrad, err := y.Grad() if err != nil { log.Fatal(err) } fmt.Printf(\u0026#34;dz/dy: %v | %v\\n\u0026#34;, ygrad, grads[1]) // Output: \t// z: 4.5 \t// dz/dx: 1 | 1 :: float64{1} \t// dz/dy: 1 | 1 :: float64{1} } Currently Gorgonia only performs backwards mode automatic differentiation (aka backpropagation), although one may observe the vestiges of an older version which supported forwards mode differentiation in the existence of *dualValue. It may return in the future.\n"
},
{
"uri": "https://gorgonia.org/usage/graph/",
"title": "Graph",
"tags": [],
"description": "",
"content": " A lot has been said about a computation graph or an expression graph. But what is it exactly? Think of it as an AST for the math expression that you want. Here\u0026rsquo;s the graph for the examples (but with a vector and a scalar addition instead) above:\nBy the way, Gorgonia comes with nice-ish graph printing abilities. Here\u0026rsquo;s an example of a graph of the equation y = x² and its derivation:\nTo read the graph is easy. The expression builds from bottom up, while the derivations build from top down. This way the derivative of each node is roughly on the same level.\nRed-outlined nodes indicate that it\u0026rsquo;s a root node. Green outlined nodes indicate that they\u0026rsquo;re a leaf node. Nodes with a yellow background indicate that it\u0026rsquo;s an input node. The dotted arrows indicate which node is the gradient node for the pointed-to node.\nConcretely, it says that c42011e840 (dy/dx) is the gradient node of the input c42011e000 (which is x).\nNode Rendering A Node is rendered thusly:\n IDnode name :: type OP*op name :: type shape compilation metadata Value†Gradient Additional Notes If it\u0026rsquo;s an input node, then the Op row will not show up. If there are no Values bound to the node, it will show up as NIL. However, when there are values and gradients, it will try to as best as possible display the values bound to the node. "
},
{
"uri": "https://gorgonia.org/usage/cuda/",
"title": "CUDA ",
"tags": [],
"description": "",
"content": "Gorgonia comes with CUDA support out of the box. However, usage is specialized. To use CUDA, you must build your application with the build tag cuda, like so:\ngo build -tags='cuda' . Furthermore, there are some additional requirements:\n CUDA toolkit 9.0 is required. Installing this installs the nvcc compiler which is required to run your code with CUDA. Be sure to follow the post-installation steps go install gorgonia.org/gorgonia/cmd/cudagen. This installs the cudagen program. Running cudagen will generate the relevant CUDA related code for Gorgonia. Note that you will need a folder at src\\gorgonia.org\\gorgonia\\cuda modules\\target The CUDA ops must be manually enabled in your code with the UseCudaFor option. runtime.LockOSThread() must be called in the main function where the VM is running. CUDA requires thread affinity, and therefore the OS thread must be locked. Because nvcc only plays well with gcc version 6 and below (the current version is 7), this is also quite helpful:\nsudo ln -s /path/to/gcc-6 /usr/local/cuda-9.0/bin/gcc\n"
},
{
"uri": "https://gorgonia.org/getting-started/",
"title": "Installation",
"tags": [],
"description": "",
"content": " The package is go-gettable: go get -u gorgonia.org/gorgonia. Additionally, Gorgonia uses dep as its vendoring tool.\nThe current version is 0.8.x\nVersioning We use semver 2.0.0 for our versioning. Before 1.0, Gorgonia\u0026rsquo;s APIs are expected to change quite a bit. API is defined by the exported functions, variables and methods. For the developers\u0026rsquo; sanity, there are minor differences to semver that we will apply prior to version 1.0. They are enumerated below:\n The MINOR number will be incremented every time there is a deletrious break in API. This means any deletion, or any change in function signature or interface methods will lead to a change in MINOR number. Additive changes will NOT change the MINOR version number prior to version 1.0. This means that if new functionality were added that does not break the way you use Gorgonia, there will not be an increment in the MINOR version. There will be an increment in the PATCH version.\n Go Version Support Gorgonia aims to support 5 versions below the Master branch of Go. This means Gorgonia will support the current released version of Go, and up to 4 previous versions - providing something doesn\u0026rsquo;t break. Where possible a shim will be provided (for things like new sort APIs or math/bits which came out in Go 1.9).\nThe current version of Go is 1.9.2. The earliest version Gorgonia supports is Go 1.6.x.\nDependencies There are very few dependencies that Gorgonia uses - and they\u0026rsquo;re all pretty stable, so as of now there isn\u0026rsquo;t a need for vendoring tools. These are the list of external packages that Gorgonia calls, ranked in order of reliance that this package has (subpackages are omitted):\n Package Used For Vitality Notes Licence gonum/graph Sorting *ExprGraph Vital. Removal means Gorgonia will not work Development of Gorgonia is committed to keeping up with the most updated version gonum license (MIT/BSD-like) gonum/blas Tensor subpackage linear algebra operations Vital. Removal means Gorgonial will not work Development of Gorgonia is committed to keeping up with the most updated version gonum license (MIT/BSD-like) cu CUDA drivers Needed for CUDA operations Same maintainer as Gorgonia MIT/BSD-like math32 float32 operations Can be replaced by float32(math.XXX(float64(x))) Same maintainer as Gorgonia, same API as the built in math package MIT/BSD-like hm Type system for Gorgonia Gorgonia\u0026rsquo;s graphs are pretty tightly coupled with the type system Same maintainer as Gorgonia MIT/BSD-like vecf64 optimized []float64 operations Can be generated in the tensor/genlib package. However, plenty of optimizations have been made/will be made Same maintainer as Gorgonia MIT/BSD-like vecf32 optimized []float32 operations Can be generated in the tensor/genlib package. However, plenty of optimizations have been made/will be made Same maintainer as Gorgonia MIT/BSD-like set Various set operations Can be easily replaced Stable API for the past 1 year set licence (MIT/BSD-like) gographviz Used for printing graphs Graph printing is only vital to debugging. Gorgonia can survive without, but with a major (but arguably nonvital) feature loss Last update 12th April 2017 gographviz licence (Apache 2.0) rng Used to implement helper functions to generate initial weights Can be replaced fairly easily. Gorgonia can do without the convenience functions too rng licence (Apache 2.0) errors Error wrapping Gorgonia won\u0026rsquo;t die without it. In fact Gorgonia has also used goerrors/errors in the past. Stable API for the past 6 months errors licence (MIT/BSD-like) gonum/mat Compatibility between Tensor and Gonum\u0026rsquo;s Matrix Development of Gorgonia is committed to keeping up with the most updated version gonum license (MIT/BSD-like) testify/assert Testing Can do without but will be a massive pain in the ass to test testify licence (MIT/BSD-like) Keeping Updated Gorgonia\u0026rsquo;s project has a mailing list, as well as a Twitter account. Official updates and announcements will be posted to those two sites.\n"
},
{
"uri": "https://gorgonia.org/usage/",
"title": "Usage",
"tags": [],
"description": "",
"content": "Gorgonia works by creating a computation graph, and then executing it. Think of it as a programming language, but is limited to mathematical functions, and has no branching capability (no if/then or loops). In fact this is the dominant paradigm that the user should be used to thinking about. The computation graph is an AST.\nMicrosoft\u0026rsquo;s CNTK, with its BrainScript, is perhaps the best at exemplifying the idea that building of a computation graph and running of the computation graphs are different things, and that the user should be in different modes of thoughts when going about them.\nWhilst Gorgonia\u0026rsquo;s implementation doesn\u0026rsquo;t enforce the separation of thought as far as CNTK\u0026rsquo;s BrainScript does, the syntax does help a little bit.\nHere\u0026rsquo;s an example - say you want to define a math expression z = x + y. Here\u0026rsquo;s how you\u0026rsquo;d do it:\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; . \u0026#34;gorgonia.org/gorgonia\u0026#34; ) func main() { g := NewGraph() var x, y, z *Node var err error // define the expression \tx = NewScalar(g, Float64, WithName(\u0026#34;x\u0026#34;)) y = NewScalar(g, Float64, WithName(\u0026#34;y\u0026#34;)) z, err = Add(x, y) if err != nil { log.Fatal(err) } // create a VM to run the program on \tmachine := NewTapeMachine(g) // set initial values then run \tLet(x, 2.0) Let(y, 2.5) if machine.RunAll() != nil { log.Fatal(err) } fmt.Printf(\u0026#34;%v\u0026#34;, z.Value()) // Output: 4.5 } You might note that it\u0026rsquo;s a little more verbose than other packages of similar nature. For example, instead of compiling to a callable function, Gorgonia specifically compiles into a *program which requires a *TapeMachine to run. It also requires manual a Let(...) call.\nThe author would like to contend that this is a Good Thing - to shift one\u0026rsquo;s thinking to a machine-based thinking. It helps a lot in figuring out where things might go wrong.\nAdditionally, there are no support for branching - that is to say there are no conditionals (if/else) or loops. The aim is not to build a Turing-complete computer.\n"
},
{
"uri": "https://gorgonia.org/usage/cuda/example/",
"title": "Example",
"tags": [],
"description": "",
"content": " So how do we use CUDA? Say we\u0026rsquo;ve got a file, main.go:\nimport ( \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; \u0026#34;runtime\u0026#34; T \u0026#34;gorgonia.org/gorgonia\u0026#34; \u0026#34;gorgonia.org/tensor\u0026#34; ) func main() { g := T.NewGraph() x := T.NewMatrix(g, T.Float32, T.WithName(\u0026#34;x\u0026#34;), T.WithShape(100, 100)) y := T.NewMatrix(g, T.Float32, T.WithName(\u0026#34;y\u0026#34;), T.WithShape(100, 100)) xpy := T.Must(T.Add(x, y)) xpy2 := T.Must(T.Tanh(xpy)) m := T.NewTapeMachine(g, T.UseCudaFor(\u0026#34;tanh\u0026#34;)) T.Let(x, tensor.New(tensor.WithShape(100, 100), tensor.WithBacking(tensor.Random(tensor.Float32, 100*100)))) T.Let(y, tensor.New(tensor.WithShape(100, 100), tensor.WithBacking(tensor.Random(tensor.Float32, 100*100)))) runtime.LockOSThread() for i := 0; i \u0026lt; 1000; i++ { if err := m.RunAll(); err != nil { log.Fatalf(\u0026#34;iteration: %d. Err: %v\u0026#34;, i, err) } } runtime.UnlockOSThread() fmt.Printf(\u0026#34;%1.1f\u0026#34;, xpy2.Value()) } If this is run normally:\ngo run main.go CUDA will not be used.\nIf the program is to be run using CUDA, then this must be invoked:\ngo run -tags='cuda' And even so, only the tanh function uses CUDA.\nRationale The main reasons for having such complicated requirements for using CUDA is quite simply performance related. As Dave Cheney famously wrote, cgo is not Go. To use CUDA, cgo is unfortunately required. And to use cgo, plenty of tradeoffs need to be made.\nTherefore the solution was to nestle the CUDA related code in a build tag, cuda. That way by default no cgo is used (well, kind-of - you could still use cblas or blase).\nThe reason for requiring CUDA toolkit 8.0 is because there are many CUDA Compute Capabilities, and generating code for them all would yield a huge binary for no real good reason. Rather, users are encouraged to compile for their specific Compute Capabilities.\nLastly, the reason for requiring an explicit specification to use CUDA for which ops is due to the cost of cgo calls. Additional work is being done currently to implement batched cgo calls, but until that is done, the solution is keyhole \u0026ldquo;upgrade\u0026rdquo; of certain ops\n"
},
{
"uri": "https://gorgonia.org/usage/cuda/ops/",
"title": "Op's supported by CUDA",
"tags": [],
"description": "",
"content": "As of now, only the very basic simple ops support CUDA:\nElementwise unary operations:\n abs sin cos exp ln log2 neg square sqrt inv (reciprocal of a number) cube tanh sigmoid log1p expm1 softplus Elementwise binary operations - only arithmetic operations support CUDA:\n add sub mul div pow From a lot of profiling of this author\u0026rsquo;s personal projects, the ones that really matter are tanh, sigmoid, expm1, exp and cube - basically the activation functions. The other operations do work fine with MKL+AVX and aren\u0026rsquo;t the major cause of slowness in a neural network\n"
},
{
"uri": "https://gorgonia.org/usage/cuda/improvements/",
"title": "Improvements",
"tags": [],
"description": "",
"content": "In a trivial benchmark, careful use of CUDA (in this case, used to call sigmoid) shows impressive improvements over non-CUDA code (bearing in mind the CUDA kernel is extremely naive and not optimized):\nBenchmarkOneMilCUDA-8 300\t3348711 ns/op BenchmarkOneMil-8 50\t33169036 ns/op "
},
{
"uri": "https://gorgonia.org/contributing/",
"title": "Contributing",
"tags": [],
"description": "",
"content": " Obviously since you are most probably reading this on Github, Github will form the major part of the workflow for contributing to this package.\nSee also: CONTRIBUTING.md\nContributors and Significant Contributors All contributions are welcome. However, there is a new class of contributor, called Significant Contributors.\nA Significant Contributor is one who has shown deep understanding of how the library works and/or its environs. Here are examples of what constitutes a Significant Contribution:\n Wrote significant amounts of documentation pertaining to why/the mechanics of particular functions/methods and how the different parts affect one another Wrote code, and tests around the more intricately connected parts of Gorgonia Wrote code and tests, and have at least 5 pull requests accepted Provided expert analysis on parts of the package (for example, you may be a floating point operations expert who optimized one function) Answered at least 10 support questions. Significant Contributors list will be updated once a month (if anyone even uses Gorgonia that is).\n"
},
{
"uri": "https://gorgonia.org/copyright/",
"title": "Copyright",
"tags": [],
"description": "",
"content": " Licence Gorgonia is licenced under a variant of Apache 2.0. It\u0026rsquo;s for all intents and purposes the same as the Apache 2.0 Licence, with the exception of not being able to commercially profit directly from the package unless you\u0026rsquo;re a Significant Contributor (for example, providing commercial support for the package). It\u0026rsquo;s perfectly fine to profit directly from a derivative of Gorgonia (for example, if you use Gorgonia as a library in your product)\nEveryone is still allowed to use Gorgonia for commercial purposes (example: using it in a software for your business).\nVarious Other Copyright Notices These are the packages and libraries which inspired and were adapted from in the process of writing Gorgonia (the Go packages that were used were already declared above):\n Source How it\u0026rsquo;s Used Licence Numpy Inspired large portions. Directly adapted algorithms for a few methods (explicitly labelled in the docs) MIT/BSD-like. Numpy Licence Theano Inspired large portions. (Unsure: number of directly adapted algorithms) MIT/BSD-like Theano\u0026rsquo;s licence Caffe im2col and col2im directly taken from Caffe. Convolution algorithms inspired by the original Caffee methods Caffe Licence "
},
{
"uri": "https://gorgonia.org/support/",
"title": "Support",
"tags": [],
"description": "",
"content": "The best way of support right now is to open a ticket on Github.\n"
},
{
"uri": "https://gorgonia.org/",
"title": "About",
"tags": [],
"description": "",
"content": " Gorgonia is a library that helps facilitate machine learning in Go. Write and evaluate mathematical equations involving multidimensional arrays easily. If this sounds like Theano or TensorFlow, it\u0026rsquo;s because the idea is quite similar. Specifically, the library is pretty low-level, like Theano, but has higher goals like Tensorflow.\nGorgonia:\n Can perform automatic differentiation Can perform symbolic differentiation Can perform gradient descent optimizations Can perform numerical stabilization Provides a number of convenience functions to help create neural networks Is fairly quick (comparable to Theano and Tensorflow\u0026rsquo;s speed) Supports CUDA/GPGPU computation (OpenCL not yet supported, send a pull request) Will support distributed computing Goals The primary goal for Gorgonia is to be a highly performant machine learning/graph computation-based library that can scale across multiple machines. It should bring the appeal of Go (simple compilation and deployment process) to the ML world. It\u0026rsquo;s a long way from there currently, however, the baby steps are already there.\nThe secondary goal for Gorgonia is to provide a platform for exploration for non-standard deep-learning and neural network related things. This includes things like neo-hebbian learning, corner-cutting algorithms, evolutionary algorithms and the like.\n"
},
{
"uri": "https://gorgonia.org/_footer/",
"title": "",
"tags": [],
"description": "",
"content": ""
},
{
"uri": "https://gorgonia.org/categories/",
"title": "Categories",
"tags": [],
"description": "",
"content": ""
},
{
"uri": "https://gorgonia.org/tags/",
"title": "Tags",
"tags": [],
"description": "",
"content": ""
}]