Files
Rbm/CLAUDE.md
T
jensandClaude Sonnet 5 33a0647a51 Add CLAUDE.md with build commands and architecture overview
Documents the PRJ/CONFIG-based Makefile build, external deps
(Armadillo, JsonCpp, JUCE), and the Rbm/Layer/AStack (DeepStack/RnnStack)
core architecture plus the three entry points (main.cpp, poet.cpp, gui.cpp).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019113s2pJdTtsUqsBdFgQAk
2026-07-26 23:04:43 +02:00

6.0 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

C++11 library and set of executables implementing Restricted Boltzmann Machines (RBMs), stacked into deep belief networks (DeepStack) or recurrent structures (RnnStack) for character-level text generation ("poet"). There are three build targets sharing the same core sources: a JUCE-based desktop GUI (GUI), a console test harness (TEST), and a text-generation CLI (POET).

Build

Build system is a hand-written Makefile (no CMake). Select the target with PRJ and the build flavor with CONFIG:

make PRJ=POET CONFIG=release   # builds build/release/poet.elf (default PRJ=POET, CONFIG=release)
make PRJ=TEST CONFIG=debug     # builds build/debug/test.elf
make PRJ=GUI                   # builds build/release/rbm.elf, also builds the JUCE static lib first
make clean                     # removes build/${CONFIG}

The GUI target additionally depends on juce/build/${CONFIG}/libjuce.a, built via make -C juce (uses juce/Makefile, juce/pkg.mk, juce/JUCE-3.1.1.mk against the vendored juce/JUCE-3.1.1 source tree). install copies build/release/rbm.elf to ${HOME}/bin.

Object/dependency files land in build/${CONFIG}/; .d files are auto-included for header dependency tracking. There is no separate lint or test-runner command — TEST_CXX_SRCS builds main.cpp into test.elf, which is a manual smoke-test program (load a project, train, print matrices), not a unit test suite. Run it directly to sanity-check core behavior:

make PRJ=TEST CONFIG=debug && ./build/debug/test.elf

External dependencies (system-installed, not vendored)

  • Armadillo (<armadillo>, linked -larmadillo) — all matrix/vector math goes through arma::mat.
  • JsonCpp (<jsoncpp/json/json.h>, linked -ljsoncpp) — project files (*.prj) and layer weight metadata serialize to/from Json::Value.
  • JUCE (vendored under juce/, only needed for the GUI target) plus its Linux deps: freetype, X11, Xinerama, Xext, GL, pthread, dl, rt.

Architecture

Core RBM hierarchy

  • Rbm (Rbm.hpp/cpp) — a single restricted Boltzmann machine: visible/hidden units, weights (m_whv), biases (m_bh, m_bv), Params (learning rate, momentum, Gibbs sampling options, etc.), and the contrastive-divergence training step (cd, cd_hinton, cd_jens, ...). Params and trained state round-trip through toJson()/fromJson().
  • Layer (Layer.hpp/cpp) — wraps an Rbm with 2D visible geometry (numVisibleX/Y, for image-like data) plus an optional context block (numContext, used by the RNN stack to feed in previous state). Layers form an intrusive doubly-linked list via raw next/prev pointers (not std::vector); root() walks to the first layer. Per-layer weights persist as separate <prj>.Layer.<id>.{w,bh,bv}.dat files (weightsLoad/weightsSave), independent from the JSON project file.
  • AStack (AStack.hpp/cpp) — abstract base owning the Layer linked list for a named project ("stack"). Handles layer add/remove, weight init/load/save for the whole stack, and the training-batch matrix (m_trainingBatch, loaded from *.training.dat). Declares train() as pure virtual — subclasses decide how data flows between layers.
    • DeepStack — classic layer-wise DBN: upPass/downPass/upDownPass propagate a sample through the full stack; train() greedily trains each layer on the representation produced by the layers below.
    • RnnStack — treats the stack as a recurrent cell operating on one-hot character codes (NUM_CODES = 37: space + a-z + 0-9). step_forward advances the recurrent state one timestep; v_to_vc/vc_to_v pack/unpack the visible+context vector. Used by poet.cpp for text generation.
  • StackCreator (StackCreator.hpp/cpp) — serializes/deserializes an AStack (and its Layers) to/from a <name>.prj JSON file. Reads stack.type to decide whether to instantiate a DeepStack or RnnStack. Accepts an optional LayerConstructor callback so callers (e.g. the GUI) can substitute their own Layer subclass (see RbmComponent) when building layers from JSON.
  • RnnTextHelper / Matutils (matutils.hpp) — character <-> one-hot vector encoding (char2vec/vec2char, ch2idx/idx2ch), training-batch construction from text files, and small Armadillo helpers (sample, prob, normalize, uniform) used by the CD training routines.

Entry points

  • source/main.cppTEST target; exercises DeepStack directly (build/train/save a small DBN, or load an existing one, depending on CREATE_TEST/TRAIN_TEST compile-time flags).
  • source/poet.cppPOET target; loads an RnnStack project (default poet_2v_5s) and dispatches on argv[1]: c(reate)/r(eset weights)/t(rain, optionally with a training-text path in argv[2])/ f(orward-generate text, optional seed string in argv[2]). Training periodically calls back into forward() to sample generated text as a progress check.
  • source/gui.cpp + MainComponent — JUCE app entry point; MainComponent implements LayerConstructor to build RbmComponent layers (interactive Layer subclass with sliders/toggles bound to Rbm::Params) and drives training via the Rbm::IListener progress callback, mirroring what RbmListener does in the CLI tools.

Project files on disk

Each named project <name> (e.g. mnist, poet_2v_5s, context99 — see the many *.prj files at repo root, mostly saved experiment artifacts) consists of:

  • <name>.prj — JSON describing the stack type and layer geometry (via StackCreator).
  • <name>.training.dat — the training batch matrix.
  • <name>.Layer.<id>.w.dat / .bh.dat / .bv.dat — per-layer weights/biases (Armadillo binary/text format).

These root-level .dat/.prj/.txt files are experiment data and generated artifacts, not something to edit by hand; treat them as fixtures unless a task specifically concerns training data or saved models.