Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/itsubaki/autograd/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you from a blank Go module to a working gradient computation.

Prerequisites

  • Go 1.23 or later
1

Install the package

go get github.com/itsubaki/autograd
The library has no external dependencies — go get pulls in only the autograd module itself.
2

Import the packages

The two packages you need for most tasks are variable and function:
import (
    F "github.com/itsubaki/autograd/function"
    "github.com/itsubaki/autograd/variable"
)
function re-exports everything from variable under a shorter alias. Importing it as F keeps call sites concise.
3

Create variables

Wrap scalar or multi-element values with variable.New:
x := variable.New(1.0)
variable.New accepts one or more float64 values. The result is a *variable.Variable holding a tensor of that shape.
4

Run a forward pass

Apply differentiable functions to build a computation:
x := variable.New(0.5)
y := F.Square(F.Exp(F.Square(x)))

fmt.Println(y) // variable(1.648721270700128)
Each function call records itself on the output variable. The computation graph grows as you compose functions.
5

Call Backward and read the gradient

Call Backward() on the output variable to propagate gradients back to every input:
x := variable.New(0.5)
y := F.Square(F.Exp(F.Square(x)))
y.Backward()

fmt.Println(x.Grad) // variable(3.297442541400256)
x.Grad is itself a *variable.Variable holding dy/dx evaluated at x = 0.5.

Composite function example

Real computations involve multiple inputs. Here is the Matyas function — a common test case for gradient-based optimizers:
matyas := func(x, y *variable.Variable) *variable.Variable {
    // 0.26(x^2 + y^2) - 0.48xy
    z0 := F.MulC(0.26, F.Add(F.Pow(2.0)(x), F.Pow(2.0)(y)))
    z1 := F.MulC(0.48, F.Mul(x, y))
    return F.Sub(z0, z1)
}

x := variable.New(1.0)
y := variable.New(1.0)
z := matyas(x, y)
z.Backward()

fmt.Println(x.Grad, y.Grad)
// variable(0.040000000000000036) variable(0.040000000000000036)
Backward() computes partial derivatives with respect to all leaf variables in a single pass. x.Grad holds ∂z/∂x and y.Grad holds ∂z/∂y.
Call x.Cleargrad() before each forward pass when reusing variables across training iterations. Otherwise gradients accumulate across steps.

Skipping graph construction with NoGrad

During inference or evaluation you do not need gradients. Wrap those sections with variable.Nograd() to skip building the computation graph entirely:
func() {
    defer variable.Nograd().End()

    // No computation graph is built inside this block.
    y := m.Forward(x)
    fmt.Println(y)
}()
variable.Nograd() returns a *Span. Calling .End() (via defer) re-enables graph construction when the function returns.
Use defer variable.Nograd().End() as the first line of any inference helper to ensure graph construction is always restored, even if the function returns early or panics.

Higher-order gradients

Pass variable.Opts{CreateGraph: true} to make the backward pass itself differentiable. This is required for second-order methods and higher-order derivative analysis:
x := variable.New(1.0)
y := F.Sin(x)
y.Backward(variable.Opts{CreateGraph: true})

fmt.Println(y)      // variable(0.8414709848078965)
fmt.Println(x.Grad) // variable(0.5403023058681398)  ← cos(1)

for range 5 {
    gx := x.Grad
    x.Cleargrad()
    gx.Backward(variable.Opts{CreateGraph: true})
    fmt.Println(x.Grad)
}
// variable(-0.8414709848078965)
// variable(-0.5403023058681398)
// variable(0.8414709848078965)
// variable(0.5403023058681398)
// variable(-0.8414709848078965)

What’s next

Gradient descent

Use gradients to minimize a loss function iteratively.

Deep learning

Build and train neural networks with layers, models, and optimizers.

Higher-order gradients

Implement Newton’s method and other second-order techniques.

Variable API

Full reference for the variable package.

Build docs developers (and LLMs) love