Skip to content

Commit 9676282

Browse files
authored
adding model-only restoration to RL path (#107)
* adding a model only restore function to the RL path * adding clarification that target networks are reloaded as well when using load model * adding device awareness in save restore tests, fixing some relative directory path error in test * adding checkpoint_rl test to workflow script Signed-off-by: Thorsten Kurth <tkurth@nvidia.com>
1 parent 2e5ab5d commit 9676282

27 files changed

Lines changed: 759 additions & 25 deletions

.github/scripts/run_ci_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ cd /opt/torchfort/bin/tests/rl
1515
./test_distributions
1616
./test_replay_buffer
1717
./test_rollout_buffer
18+
./test_checkpoint_rl
1819
./test_off_policy --gtest_filter=*L0*
1920
./test_on_policy --gtest_filter=*L0*

docs/api/c_api.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,14 @@ torchfort_rl_off_policy_load_checkpoint
334334

335335
------
336336

337+
.. _torchfort_rl_off_policy_load_model-ref:
338+
339+
torchfort_rl_off_policy_load_model
340+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
341+
.. doxygenfunction:: torchfort_rl_off_policy_load_model
342+
343+
------
344+
337345

338346
Weights and Biases Logging
339347
--------------------------
@@ -483,6 +491,14 @@ torchfort_rl_on_policy_load_checkpoint
483491

484492
------
485493

494+
.. _torchfort_rl_on_policy_load_model-ref:
495+
496+
torchfort_rl_on_policy_load_model
497+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
498+
.. doxygenfunction:: torchfort_rl_on_policy_load_model
499+
500+
------
501+
486502

487503
Weights and Biases Logging
488504
--------------------------

docs/api/f_api.rst

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -534,11 +534,32 @@ torchfort_rl_off_policy_load_checkpoint
534534

535535
.. f:function:: torchfort_rl_off_policy_load_checkpoint(name, checkpoint_dir)
536536
537-
Restores a reinforcement learning system from a checkpoint.
537+
Restores a reinforcement learning system from a checkpoint.
538538
This method restores all models (policies, critics, target models if available) together with their corresponding optimizer and LR scheduler
539539
states. It also fully restores the state of the replay buffer, but not the current RNG seed.
540540
This function should be used in conjunction with :code:`torchfort_rl_off_policy_save_checkpoint`.
541-
541+
542+
:p character(:) name [in]: The name of system instance to use, as defined during system creation.
543+
:p character(:) checkpoint_dir [in]: A filesystem path to a directory which contains the checkpoint data to load.
544+
:r torchfort_result res: :code:`TORCHFORT_RESULT_SUCCESS` on success or error code on failure.
545+
546+
------
547+
548+
.. _torchfort_rl_off_policy_load_model-f-ref:
549+
550+
torchfort_rl_off_policy_load_model
551+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
552+
553+
.. f:function:: torchfort_rl_off_policy_load_model(name, checkpoint_dir)
554+
555+
Restores only the network weights of a reinforcement learning system from a checkpoint.
556+
In contrast to :code:`torchfort_rl_off_policy_load_checkpoint`, this method only restores the weights of the online policy and
557+
critic networks. For algorithms that use target networks (e.g. DDPG and TD3), the corresponding target networks are also restored,
558+
by re-initializing them from the loaded online networks so that they start consistent with the restored weights. The optimizers,
559+
LR schedulers, replay buffer, normalizer statistics and step counters are left in their freshly created state. This is intended for
560+
fine-tuning or transfer-learning workflows, where a pretrained model is used as the starting point for a new training run (e.g. with
561+
a modified reward function or new environment data). The checkpoint is the one produced by :code:`torchfort_rl_off_policy_save_checkpoint`.
562+
542563
:p character(:) name [in]: The name of system instance to use, as defined during system creation.
543564
:p character(:) checkpoint_dir [in]: A filesystem path to a directory which contains the checkpoint data to load.
544565
:r torchfort_result res: :code:`TORCHFORT_RESULT_SUCCESS` on success or error code on failure.
@@ -800,11 +821,31 @@ torchfort_rl_on_policy_load_checkpoint
800821

801822
.. f:function:: torchfort_rl_on_policy_load_checkpoint(name, checkpoint_dir)
802823
803-
Restores a reinforcement learning system from a checkpoint.
824+
Restores a reinforcement learning system from a checkpoint.
804825
This method restores all models (policies, critics, target models if available) together with their corresponding optimizer and LR scheduler
805826
states. It also fully restores the state of the rollout buffer, but not the current RNG seed.
806827
This function should be used in conjunction with :code:`torchfort_rl_on_policy_save_checkpoint`.
807-
828+
829+
:p character(:) name [in]: The name of system instance to use, as defined during system creation.
830+
:p character(:) checkpoint_dir [in]: A filesystem path to a directory which contains the checkpoint data to load.
831+
:r torchfort_result res: :code:`TORCHFORT_RESULT_SUCCESS` on success or error code on failure.
832+
833+
------
834+
835+
.. _torchfort_rl_on_policy_load_model-f-ref:
836+
837+
torchfort_rl_on_policy_load_model
838+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
839+
840+
.. f:function:: torchfort_rl_on_policy_load_model(name, checkpoint_dir)
841+
842+
Restores only the network weights of a reinforcement learning system from a checkpoint.
843+
In contrast to :code:`torchfort_rl_on_policy_load_checkpoint`, this method only restores the weights of the actor-critic network.
844+
The optimizer, LR scheduler, rollout buffer, normalizer statistics and step counters are left in their freshly created state. This is
845+
intended for fine-tuning or transfer-learning workflows, where a pretrained model is used as the starting point for a new training run
846+
(e.g. with a modified reward function or new environment data). The checkpoint is the one produced by
847+
:code:`torchfort_rl_on_policy_save_checkpoint`.
848+
808849
:p character(:) name [in]: The name of system instance to use, as defined during system creation.
809850
:p character(:) checkpoint_dir [in]: A filesystem path to a directory which contains the checkpoint data to load.
810851
:r torchfort_result res: :code:`TORCHFORT_RESULT_SUCCESS` on success or error code on failure.

docs/usage.rst

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,5 +351,34 @@ This function is only required if RL training from the checkpoint should be resu
351351

352352
istat = torchfort_load_model(model_name, policy_model_file);
353353

354-
can be used instead. The model instance should be created beforehand using the methods described in the :ref:`supervised_learning-ref` section.
354+
can be used instead. The model instance should be created beforehand using the methods described in the :ref:`supervised_learning-ref` section.
355+
356+
Fine-Tuning / Transfer Learning
357+
-------------------------------
358+
359+
Sometimes a previously trained system should be used as the *starting point* for a new training run, rather than fully resumed. A typical example is
360+
refining a policy with new environment data or a modified reward function. In this case restoring the full checkpoint is undesirable, because it would
361+
also restore the stale replay buffer, the optimizer momenta, the learning-rate schedule position and the training step counters of the previous run.
362+
363+
For this purpose, only the network weights can be restored from a checkpoint:
364+
365+
.. tabs::
366+
367+
.. code-tab:: fortran
368+
369+
istat = torchfort_rl_off_policy_load_model(system_name, directory_name)
370+
371+
.. code-tab:: c++
372+
373+
istat = torchfort_rl_off_policy_load_model(system_name, directory_name);
374+
375+
This loads only the weights of the online policy and critic networks from the checkpoint directory created by ``torchfort_rl_off_policy_save_checkpoint``.
376+
For algorithms that use target networks (e.g. DDPG and TD3), the corresponding target networks are also restored, by re-initializing them from the loaded
377+
online networks so that they start consistent with the restored weights. The optimizers, learning-rate schedulers, replay buffer, normalizer statistics and
378+
step counters remain in their freshly created state. Training then proceeds from the pretrained weights with a clean training history, so that newly
379+
collected transitions (e.g. generated under the modified reward function) are not mixed with stale experience. The system must be created beforehand with
380+
``torchfort_rl_off_policy_create_system`` using a network architecture matching the saved checkpoint.
381+
382+
On-policy systems provide the equivalent function ``torchfort_rl_on_policy_load_model``, which restores only the actor-critic network weights and leaves the
383+
optimizer, learning-rate scheduler, rollout buffer, normalizer statistics and step counters in their freshly created state.
355384

src/csrc/include/internal/model_pack.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "internal/base_loss.h"
2424
#include "internal/base_lr_scheduler.h"
2525
#include "internal/distributed.h"
26+
#include "internal/exceptions.h"
2627
#include "internal/model_state.h"
2728
#include "internal/model_wrapper.h"
2829
#ifdef ENABLE_GPU
@@ -51,4 +52,16 @@ struct ModelPack {
5152
void save_model_pack(const ModelPack& model_pack, const std::string& fname, bool save_optimizer = true);
5253
void load_model_pack(ModelPack& model_pack, const std::string& fname, bool load_optimizer = true);
5354

55+
// Re-point an optimizer at the given parameter tensors, e.g. after (re)loading model weights (for JIT
56+
// models a load replaces the underlying tensors, so the optimizer's references have to be refreshed).
57+
// TorchFort constructs optimizers with a single parameter group, so we update group 0 directly; this
58+
// avoids the deprecated torch::optim::Optimizer::parameters() accessor.
59+
inline void reset_optimizer_parameters(const std::shared_ptr<torch::optim::Optimizer>& optimizer,
60+
const std::vector<torch::Tensor>& parameters) {
61+
if (optimizer->param_groups().size() != 1) {
62+
THROW_NOT_SUPPORTED("reset_optimizer_parameters expects an optimizer with a single parameter group.");
63+
}
64+
optimizer->param_groups()[0].params() = parameters;
65+
}
66+
5467
} // namespace torchfort

src/csrc/include/internal/rl/off_policy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class RLOffPolicySystem {
6767
virtual void initSystemComm(MPI_Comm mpi_comm) = 0;
6868
virtual void saveCheckpoint(const std::string& checkpoint_dir) const = 0;
6969
virtual void loadCheckpoint(const std::string& checkpoint_dir) = 0;
70+
// load only the network weights (e.g. for fine-tuning), leaving optimizers,
71+
// LR schedulers, replay buffer and step counters in their freshly created state
72+
virtual void loadModel(const std::string& checkpoint_dir) = 0;
7073
virtual torch::Device modelDevice() const = 0;
7174
virtual torch::Device rbDevice() const = 0;
7275
virtual int getRank() const = 0;

src/csrc/include/internal/rl/off_policy/ddpg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ class DDPGSystem : public RLOffPolicySystem, public std::enable_shared_from_this
269269
// saving and loading
270270
void saveCheckpoint(const std::string& checkpoint_dir) const;
271271
void loadCheckpoint(const std::string& checkpoint_dir);
272+
void loadModel(const std::string& checkpoint_dir);
272273

273274
// info printing
274275
void printInfo() const;

src/csrc/include/internal/rl/off_policy/sac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ class SACSystem : public RLOffPolicySystem, public std::enable_shared_from_this<
400400
// saving and loading
401401
void saveCheckpoint(const std::string& checkpoint_dir) const;
402402
void loadCheckpoint(const std::string& checkpoint_dir);
403+
void loadModel(const std::string& checkpoint_dir);
403404

404405
// info printing
405406
void printInfo() const;

src/csrc/include/internal/rl/off_policy/td3.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class TD3System : public RLOffPolicySystem, public std::enable_shared_from_this<
302302
// saving and loading
303303
void saveCheckpoint(const std::string& checkpoint_dir) const;
304304
void loadCheckpoint(const std::string& checkpoint_dir);
305+
void loadModel(const std::string& checkpoint_dir);
305306

306307
// info printing
307308
void printInfo() const;

src/csrc/include/internal/rl/on_policy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class RLOnPolicySystem {
6969
virtual void initSystemComm(MPI_Comm mpi_comm) = 0;
7070
virtual void saveCheckpoint(const std::string& checkpoint_dir) const = 0;
7171
virtual void loadCheckpoint(const std::string& checkpoint_dir) = 0;
72+
// load only the network weights (e.g. for fine-tuning), leaving optimizers,
73+
// LR schedulers, rollout buffer and step counters in their freshly created state
74+
virtual void loadModel(const std::string& checkpoint_dir) = 0;
7275
virtual torch::Device modelDevice() const = 0;
7376
virtual torch::Device rbDevice() const = 0;
7477

0 commit comments

Comments
 (0)