Repository: huggingface/trl
Pull request: Fix: RuntimeError: 'weight' must be 2-D issue
Fix #669

# Problem description

In ZeRO3, issues like #669 are caused by running `deepspeed.initialize` on only one of the two models passed to DPO_Trainer.

Most users use `.from_pretrained` to get the weight of the model, and inside from_pretrained is the code below.
```python
    if is_deepspeed_zero3_enabled():
        import deepspeed

        logger.info("Detected DeepSpeed ZeRO-3: activating zero.init() for this model")
        init_contexts = [deepspeed.zero.Init(config_dict_or_path=deepspeed_config())] + init_contexts
    elif load_in_8bit or low_cpu_mem_usage:
        init_contexts.append(init_empty_weights())

    with ContextManagers(init_contexts):
        model = cls(config, *model_args, **model_kwargs)
```
Models that don't use ZeRO3 don't matter, 
But most of the heavier models like LLM are run using ZeRO3, so `from_pretrained`, `is_deepspeed_zero3_enabled()` becomes True, it have to use the if statement.

But since ZeRO3 is parameter partitioning, does this mean that it need to use the `_partition_param` in `deepspeed.zero.Init` to divide the parameters in one layer by the number of GPUs?

At this time, the partitioned parameter is put into a `.ds_tensor`, and `parameter.data`(or weight, bias), where the original parameter was, is filled with a zero tensor of size 0.

So far, so good

The problem is that we need to do a `deepspeed.initialize` when training to load the partitioned parameters in `.ds_tensor`,
But ref_model didn't do `deepspeed.initialize`, so it can't load the `.ds_tensor`.

This causes an error like `RuntimeError: 'weight' must be {n}-D` because ref_model's `parameter.data` does not contain weight, as shown in the issue.

So to solve the issue, it need to `deepspeed.initialize` ref_model as well as model.

However, since `prepare_model` does not have a deepspeed wrapper, 
so it need to add the process of wrapping the model with deepspeed using `_prepare_deepspeed` to the init.

Problem statement:
DeepSpeed Zero3 dpo accured embedding weight error
i used `Open-Orca/OpenOrca-Platypus2-13B` and dpo error accured
dataset is used `Anthropic/hh-rlhf`

``` python3
Traceback (most recent call last):
  File "/data/workspace/train/train_dpo.py", line 133, in <module>
    main(model_args=model_args, dataset_args=dataset_args, training_args=training_args)
  File "/data/workspace/train/train_dpo.py", line 119, in main
    dpo_trainer.train()
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 1539, in train
    return inner_training_loop(
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 1809, in _inner_training_loop
    tr_loss_step = self.training_step(model, inputs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 2654, in training_step
    loss = self.compute_loss(model, inputs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 360, in compute_loss
    loss, metrics = self.get_batch_metrics(model, inputs, train_eval="train")
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 327, in get_batch_metrics
    ) = self.concatenated_forward(self.ref_model, batch)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 290, in concatenated_forward
Traceback (most recent call last):
    all_logits = model(
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/models/llama/modeling_llama.py", line 806, in forward
  File "/data/workspace/train/train_dpo.py", line 133, in <module>
    main(model_args=model_args, dataset_args=dataset_args, training_args=training_args)
  File "/data/workspace/train/train_dpo.py", line 119, in main
    dpo_trainer.train()
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 1539, in train
    return inner_training_loop(
    outputs = self.model(
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 1809, in _inner_training_loop
    tr_loss_step = self.training_step(model, inputs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/trainer.py", line 2654, in training_step
    loss = self.compute_loss(model, inputs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 360, in compute_loss
    loss, metrics = self.get_batch_metrics(model, inputs, train_eval="train")
    return forward_call(*args, **kwargs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/models/llama/modeling_llama.py", line 646, in forward
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 327, in get_batch_metrics
    ) = self.concatenated_forward(self.ref_model, batch)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/trl/trainer/dpo_trainer.py", line 290, in concatenated_forward
    all_logits = model(
    inputs_embeds = self.embed_tokens(input_ids)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/models/llama/modeling_llama.py", line 806, in forward
    outputs = self.model(
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/transformers/models/llama/modeling_llama.py", line 646, in forward
    inputs_embeds = self.embed_tokens(input_ids)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
    return forward_call(*args, **kwargs)  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/sparse.py", line 162, in forward
    return F.embedding(

  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/modules/sparse.py", line 162, in forward
    return F.embedding(
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/functional.py", line 2210, in embedding
    return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
  File "/data/workspace/.bart_venv/lib/python3.10/site-packages/torch/nn/functional.py", line 2210, in embedding
RuntimeError: 'weight' must be 2-D
    return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
```

if i changed model, error accured too.
how can i use zero3?

``` json
{
    "fp16": {
        "enabled": "auto",
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    },
    "zero_allow_untested_optimizer": true,
    "zero_force_ds_cpu_optimizer": false,
    "zero_optimization": {
        "stage": 3,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": true
        },
        "overlap_comm": true,
        "contiguous_gradients": true,
        "sub_group_size": 5e8,
        "allgather_partitions": true,
        "allgather_bucket_size": 1e10,
        "reduce_bucket_size": "auto",
        "stage3_prefetch_bucket_size": "auto",
        "stage3_param_persistence_threshold": "auto",
        "stage3_max_live_parameters": 1e10,
        "stage3_max_reuse_distance": 1e10,
        "stage3_gather_16bit_weights_on_model_save": true
    },
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "gradient_accumulation_steps": "auto"
}
```

Hints from issue discussion:
also have the same problem with zero3
cc @vwxyzjn who is currently looking at DS
i find that problem is accured by `ref_wav`'s set accelerate initialize....

ref_wav can not prepare for deepspeed. because using just `prepare()` not `prepare_model()`
`prepare` is for inference, i think. ref_wav must be freezed but not inference. so that have to on deepspeed.

i just modified, that line to `_prepare_deepspeed()`, it work. but, i have little knowledge on deepspeed. so, i don't know that is right solution.

plz check and modify it.🤗🤗🤗


I also encountered a similar problem, can you describe your solution in detail

Commit message: Fix: self.args.deepspeed > self.is_deepspeed_enabled

Patch to review:
diff --git a/trl/trainer/dpo_trainer.py b/trl/trainer/dpo_trainer.py
index ff4d7a504d..17936d4c24 100644
--- a/trl/trainer/dpo_trainer.py
+++ b/trl/trainer/dpo_trainer.py
@@ -205,7 +205,11 @@ def __init__(
                     "You are using a `peft` version that does not support `disable_adapter`. Please update your `peft` version to the latest version."
                 )
         else:
-            self.ref_model = self.accelerator.prepare_model(self.ref_model, evaluation_mode=True)
+            if self.is_deepspeed_enabled:
+                (self.ref_model,) = self.accelerator._prepare_deepspeed(self.ref_model)
+                self.ref_model.eval()
+            else:
+                self.ref_model = self.accelerator.prepare_model(self.ref_model, evaluation_mode=True)
 
     def concatenated_inputs(self, batch: Dict[str, Union[List, torch.LongTensor]]) -> Dict[str, torch.LongTensor]:
         """Concatenate the chosen and rejected inputs into a single tensor.


Code review comments:
diff_hunk: @@ -205,7 +205,11 @@ def __init__(
                     "You are using a `peft` version that does not support `disable_adapter`. Please update your `peft` version to the latest version."
                 )
         else:
-            self.ref_model = self.accelerator.prepare_model(self.ref_model, evaluation_mode=True)
+            if self.is_deepspeed_enabled:
+                (self.ref_model,) = self.accelerator._prepare_deepspeed(self.ref_model)
path: trl/trainer/dpo_trainer.py
text: @user1:
```suggestion
                # Read more about the issue in https://github.com/huggingface/trl/pull/687
                self.ref_model = self.accelerator._prepare_deepspeed(self.ref_model)
```

@author:
@user1 
good idea!
i agree this!

@user1:
Great! Feel free to accept the suggestion above