-
Notifications
You must be signed in to change notification settings - Fork 360
(draft) feat: add LeWM, an action-conditioned latent world model trained with SIGReg #2032
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 13 commits
0a26e73
9021781
fea0671
44af827
810f111
4eea61f
642c432
55ee663
9819388
96e063e
f9e4a51
5b088b0
4ec5312
b640f07
60c1b22
623af45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| .. _lewm: | ||
|
|
||
| LeWM | ||
| ==== | ||
|
|
||
| LeWM [0]_ is a latent world model. It predicts the embedding of the next frame | ||
| from the embeddings of the past frames and the actions that were taken, and it | ||
| never reconstructs pixels. The encoder is trained from pixels together with the | ||
| predictor. SIGReg [1]_ keeps the embeddings close to an isotropic Gaussian, | ||
| which is what prevents collapse, so LeWM needs no stop-gradient, no teacher | ||
| network and no exponential moving average. | ||
|
|
||
| This is the self-supervised idea with one more axis. An SSL method predicts the | ||
| embedding of one view from another view. A world model predicts the embedding | ||
| of the next frame from the past ones, given what the agent did. | ||
|
|
||
| .. warning:: | ||
|
|
||
| LeWM and the ``world_model`` modules are experimental. Their shapes and | ||
| signatures may change in a minor release. | ||
|
|
||
| Key Components | ||
| -------------- | ||
|
|
||
| - **Encoder**: Any image encoder maps a frame to an embedding. The example uses | ||
| a ViT-tiny with a :class:`lightly.models.modules.LeWMProjectionHead` on the | ||
| class token. | ||
| - **Action encoder**: :class:`lightly.models.modules.ActionEncoder` maps a | ||
| low-dimensional action vector to the width of the predictor. | ||
| - **Predictor**: :class:`lightly.models.modules.LatentDynamicsPredictor` is a | ||
| causal transformer over frames. The action at frame ``t`` conditions every | ||
| block through AdaLN-Zero. It is action-conditioned and causal by default; | ||
| ``conditional=False`` gives an actionless predictor and ``causal=False`` a | ||
| bidirectional one, both built from | ||
| :class:`lightly.models.modules.PredictorBlock`. | ||
| - **Loss**: :class:`lightly.loss.LeWMLoss` adds a next-embedding prediction | ||
| term and :class:`lightly.loss.SIGReg`. The weight of the SIGReg term is the | ||
| only hyperparameter that needs tuning. | ||
|
|
||
| The shape contract | ||
| ------------------ | ||
|
|
||
| The predictor reads and returns:: | ||
|
|
||
| embeddings (B, T, D) | ||
| action_emb (B, T, D) | ||
|
|
||
| ``B`` is the batch, ``T`` the frames of one clip and ``D`` the width. Entry | ||
| ``t`` of the output predicts frame ``t + 1``, and ``action_emb[:, t]`` is the | ||
| action taken **at** frame ``t``. A shape check cannot catch a phase error, so a | ||
| training step reads:: | ||
|
|
||
| predicted = predictor(emb[:, :-1], action_emb=action_emb[:, :-1]) | ||
| target = emb[:, 1:] | ||
|
|
||
| Good to Know | ||
| ------------ | ||
|
|
||
| - **Same regularizer as LeJEPA**: LeWM is LeJEPA over time, with actions. Both | ||
| methods use the same :class:`lightly.loss.SIGReg` class. | ||
| - **The encoder is interchangeable**: The predictor reads embeddings, not | ||
| images, so any backbone works, and a frozen pretrained encoder is | ||
| interchangeable with one trained from scratch. A frozen encoder also cannot | ||
| collapse, because its targets cannot move. | ||
| - **Planning is out of scope**: | ||
| :meth:`lightly.models.modules.LatentDynamicsPredictor.rollout` feeds the | ||
| model its own predictions, which is how a planner scores candidate action | ||
| sequences. The planner itself needs an environment and an episode, so it | ||
| belongs to a control library rather than here. | ||
|
|
||
| .. note:: | ||
|
|
||
| A projection head that ends in ``BatchNorm`` behaves differently in train | ||
| and eval mode, and planning runs in eval mode. Check that the embeddings | ||
| agree between the two modes before trusting a rollout. | ||
|
|
||
| Reference: | ||
|
|
||
| .. [0] `LeWorldModel, 2026 <https://arxiv.org/abs/2603.19312>`_ | ||
| .. [1] `LeJEPA, 2025 <https://arxiv.org/abs/2511.08544>`_ | ||
|
|
||
| .. note:: | ||
|
|
||
| LeWM requires `TIMM <https://github.com/huggingface/pytorch-image-models>`_ | ||
| to be installed | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| pip install "lightly[timm]" | ||
|
|
||
| .. tabs:: | ||
| .. tab:: PyTorch | ||
|
|
||
| .. image:: https://img.shields.io/badge/Open%20in%20Colab-blue?logo=googlecolab&label=%20&labelColor=5c5c5c | ||
| :target: https://colab.research.google.com/github/lightly-ai/lightly/blob/master/examples/notebooks/pytorch/lewm.ipynb | ||
|
|
||
| The example generates its own trajectories, so it runs without an | ||
| environment or a recorded dataset. It can be run from the command line | ||
| with:: | ||
|
|
||
| python lightly/examples/pytorch/lewm.py | ||
|
|
||
| .. literalinclude:: ../../../examples/pytorch/lewm.py | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,3 +24,16 @@ lightly.models | |
| -------- | ||
| .. automodule:: lightly.models.modules.heads | ||
| :members: | ||
|
|
||
| .world_model | ||
| ------------ | ||
| .. automodule:: lightly.models.modules.world_model | ||
|
|
||
| .. autoclass:: lightly.models.modules.world_model.conditioning.ActionEncoder | ||
| :members: | ||
|
|
||
| .. autoclass:: lightly.models.modules.world_model.predictor.LatentDynamicsPredictor | ||
| :members: | ||
|
|
||
| .. autoclass:: lightly.models.modules.world_model.predictor.PredictorBlock | ||
| :members: | ||
|
Comment on lines
+27
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: printf '%s\n' '--- repository conventions ---'
find /tmp/coderabbit-repo-knowledge/lightly-ai-lightly-f16fc44d -maxdepth 2 -type f -name '*.md' -print
printf '%s\n' '--- docs README ---'
sed -n '1,220p' docs/README.md
printf '%s\n' '--- target documentation ---'
sed -n '1,100p' docs/source/lightly.models.rst
printf '%s\n' '--- referenced modules and classes ---'
rg -n --glob '*.py' 'class (ActionEncoder|LatentDynamicsPredictor|PredictorBlock)\b|(^|\s)ActionEncoder\b|(^|\s)LatentDynamicsPredictor\b|(^|\s)PredictorBlock\b' lightly
printf '%s\n' '--- relevant file status ---'
git status --short -- docs/source/lightly.models.rst docs/README.mdRepository: lightly-ai/lightly Length of output: 5551 🏁 Script executed: printf '%s\n' '--- scoped docs convention ---'
cat /tmp/coderabbit-repo-knowledge/lightly-ai-lightly-f16fc44d/conventions/docs-source.md
printf '%s\n' '--- world_model package ---'
cat -n lightly/models/modules/world_model/__init__.py
printf '%s\n' '--- conditioning declarations ---'
sed -n '1,90p' lightly/models/modules/world_model/conditioning.py
printf '%s\n' '--- predictor declarations ---'
sed -n '1,190p' lightly/models/modules/world_model/predictor.py
printf '%s\n' '--- docs build configuration references ---'
rg -n 'autodoc|napoleon|intersphinx|html-noplot|docs/source|lightly.models' docs -g '*.py' -g '*.rst' -g 'Makefile' -g '*.md'Repository: lightly-ai/lightly Length of output: 19768 Run the documented Sphinx build. Run 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Please align the LeWM documentation with the shipped API and example: describe the predictor as reading embeddings and actions and returning predicted embeddings; scope the TIMM requirement to the PyTorch example; and change the invocation to
python examples/pytorch/lewm.py.📍 Affects 1 file
docs/source/examples/lewm.rst#L43-L46(this comment)docs/source/examples/lewm.rst#L82-L85docs/source/examples/lewm.rst#L101-L101🤖 Prompt for AI Agents