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
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 througharma::mat. - JsonCpp (
<jsoncpp/json/json.h>, linked-ljsoncpp) — project files (*.prj) and layer weight metadata serialize to/fromJson::Value. - JUCE (vendored under
juce/, only needed for theGUItarget) 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 throughtoJson()/fromJson().Layer(Layer.hpp/cpp) — wraps anRbmwith 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 rawnext/prevpointers (notstd::vector);root()walks to the first layer. Per-layer weights persist as separate<prj>.Layer.<id>.{w,bh,bv}.datfiles (weightsLoad/weightsSave), independent from the JSON project file.AStack(AStack.hpp/cpp) — abstract base owning theLayerlinked 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). Declarestrain()as pure virtual — subclasses decide how data flows between layers.DeepStack— classic layer-wise DBN:upPass/downPass/upDownPasspropagate 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_forwardadvances the recurrent state one timestep;v_to_vc/vc_to_vpack/unpack the visible+context vector. Used bypoet.cppfor text generation.
StackCreator(StackCreator.hpp/cpp) — serializes/deserializes anAStack(and itsLayers) to/from a<name>.prjJSON file. Readsstack.typeto decide whether to instantiate aDeepStackorRnnStack. Accepts an optionalLayerConstructorcallback so callers (e.g. the GUI) can substitute their ownLayersubclass (seeRbmComponent) 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.cpp—TESTtarget; exercisesDeepStackdirectly (build/train/save a small DBN, or load an existing one, depending onCREATE_TEST/TRAIN_TESTcompile-time flags).source/poet.cpp—POETtarget; loads anRnnStackproject (defaultpoet_2v_5s) and dispatches onargv[1]:c(reate)/r(eset weights)/t(rain, optionally with a training-text path inargv[2])/f(orward-generate text, optional seed string inargv[2]). Training periodically calls back intoforward()to sample generated text as a progress check.source/gui.cpp+MainComponent— JUCE app entry point;MainComponentimplementsLayerConstructorto buildRbmComponentlayers (interactiveLayersubclass with sliders/toggles bound toRbm::Params) and drives training via theRbm::IListenerprogress callback, mirroring whatRbmListenerdoes 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 (viaStackCreator).<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.