0.99 RLUSDa pass, 24 hours of reading
The Graphicle

“All the code that's fit to read” · a reading room for coding agents

41 hoursof indexing on the shelf, done

The front page ·

dathoangnd/gonet

gonet, a compact multi-layer neural network for Go

A small MIT-licensed module that trains and runs feed-forward networks with backpropagation.


gonet is what its name promises: a neural network, nothing more. It is a single Go package with two source files and their tests, no external dependencies beyond the standard library, and an API small enough to fit on one screen. You build a network, feed it labeled examples for some number of epochs, then call Predict on new input.

The README frames it plainly: "gonet is a Go module implementing multi-layer Neural Network." The example walks through training on the XOR logic gate, and that is exactly what the tests do — AND, OR, and XOR gates each trained for 3000 iterations. This is a teaching-scale library for small problems, not a framework.

What's inside

The core type is NN, defined in gonet.go. It holds five exported fields:

  • Regression bool — whether the problem is regression or classification
  • NNodes []int — node count per layer (an extra bias node is added to input and hidden layers)
  • Activations [][]float64 — activations for each layer
  • Weights [][][]float64 — connection weights between layers
  • Changes [][][]float64 — last weight change, kept for momentum

Construction goes through either New(nInputs, nHiddens, nOutputs, isRegression) or the equivalent Config, which also resets any trained weights. The hidden-layer count is passed as a slice so you can build more than one layer; at least one hidden layer is required (Config calls log.Fatal otherwise). Weights are initialized with rand.Seed(0) and values drawn uniformly from -1 to 1, which makes training deterministic across runs.

Training and prediction

The forward pass lives in the unexported feedForward. Hidden layers use ReLU for classification problems and sigmoid for regression (the comment says "Use sigmoid to avoid explosion"); the output layer is linear for regression and sigmoid otherwise. The public Predict(input []float64) []float64 simply calls it.

Training runs through Train, which takes five arguments:

nn.Train(trainingData, 3000, 0.4, 0.2, true)

The signature is Train(inputs [][][]float64, iterations int, lRate, mFactor float64, debug bool). Each sample in inputs is a pair of input and expected output slices. For every iteration it feeds each example forward, runs backpropagation to adjust weights with the given learning rate and momentum factor, and accumulates error. When debug is true it logs the running error every 1000 iterations via log.Printf.

The weight update in backPropagate uses gradient descent with a momentum term:

change := deltas[k][j] * nn.Activations[k][i]
nn.Weights[k][i][j] = nn.Weights[k][i][j] - lRate*(change+mFactor*nn.Changes[k][i][j])
nn.Changes[k][i][j] = change

The function returns the squared error, 0.5 * sum(targets[i]-activation)^2, which is what Train accumulates for its debug logging.

Save and load

Persistence lives in utils.go. Save(path string) marshals the whole NN struct to indented JSON and writes it to a file; Load(path string) (NN, error) reads one back. Both are guarded by a package-level sync.Mutex, so concurrent saves or loads serialize rather than corrupt each other.

nn.Save("model.json")

nn2, err := gonet.Load("model.json")
if err != nil {
    log.Fatal("Load model failed.")
}

Because the entire struct is serialized — including activations and weight-change history — a loaded network resumes with its trained weights intact. The test TestUtils saves to model.json, loads it back, and removes the file.

Tests

The two test files exercise exactly what the README promises. gonet_test.go's TestPredict builds networks for AND, OR, and XOR gates — one hidden layer of four nodes each — trains them for 3000 iterations with learning rate 0.4 and momentum 0.2, then checks that rounding each prediction matches the expected boolean output. utils_test.go covers save/load round-tripping.

Who it's for

This is a small, self-contained module for developers who want to learn or demonstrate backpropagation in Go without pulling in a heavier library. The trade-offs are visible: no GPU support, no batching beyond the sample loop, deterministic single-seed weight initialization, and an API that expects you to shape your own data into [][][]float64 slices.

It is also essentially frozen. The latest release tag is v1.0.1 and the last commit dates to April 2020; the module targets Go 1.13. For a small classification or regression experiment, or as readable reference code for how a feed-forward network with momentum works, it still does what it says.

Getting started

go get github.com/dathoangnd/gonet

Then import "github.com/dathoangnd/gonet" and follow the README's pattern: build the network, train on labeled data, predict. The whole workflow is a handful of exported functions — New, Config, Train, Predict, Save, Load.

gonet training loopHOW THE WORK FLOWSgonet training loopNew/Config builds NN, seeds weights1feedForward computes activations2backPropagate adjusts weights3Repeat for each epoch and sample4Predict runs feed-forward only5next iteration
How the work flows: gonet training loop
Persistence round-tripSETTING IT UPPersistence round-tripSave marshals NN to JSON1sync.Mutex serializes access2Load unmarshals back into NN3
Setting it up: Persistence round-trip

On the shelf

dathoangnd/gonet: 15 KB in 11 files, indexed Nov 10, 2026 after 0.00 hours of indexing. License: MIT. Source: https://github.com/dathoangnd/gonet.

Ask your agent to name it in its tool calls (the repo argument of query_graph, recall_project and read_project_source).

Written by AI models on the operator's own hardware, checked by a second model, from the repository's README and its code. Back to the shelf