|
5 | 5 |
|
6 | 6 | from transformers import Trainer |
7 | 7 | from transformers.trainer import ( |
| 8 | + is_sagemaker_mp_enabled, |
| 9 | + get_parameter_names, |
8 | 10 | has_length, |
| 11 | + ALL_LAYERNORM_LAYERS, |
| 12 | + ShardedDDPOption, |
| 13 | + logger, |
9 | 14 | ) |
10 | 15 | from typing import List, Optional |
11 | 16 |
|
@@ -74,12 +79,8 @@ def get_modality_length_grouped_indices(lengths, batch_size, world_size, generat |
74 | 79 | megabatch_indices = torch.randperm(len(megabatches), generator=generator) |
75 | 80 | megabatches = [megabatches[i] for i in megabatch_indices] |
76 | 81 |
|
77 | | - if len(additional_batch) >= megabatch_size: |
78 | | - megabatches = [additional_batch[:megabatch_size]] + megabatches |
79 | | - additional_batch = additional_batch[megabatch_size:] |
80 | | - |
81 | 82 | if len(additional_batch) > 0: |
82 | | - megabatches.append(additional_batch) |
| 83 | + megabatches.append(sorted(additional_batch)) |
83 | 84 |
|
84 | 85 | return [i for megabatch in megabatches for i in megabatch] |
85 | 86 |
|
@@ -146,6 +147,95 @@ def _get_train_sampler(self) -> Optional[torch.utils.data.Sampler]: |
146 | 147 | else: |
147 | 148 | return super()._get_train_sampler() |
148 | 149 |
|
| 150 | + def create_optimizer(self): |
| 151 | + """ |
| 152 | + Setup the optimizer. |
| 153 | +
|
| 154 | + We provide a reasonable default that works well. If you want to use something else, you can pass a tuple in the |
| 155 | + Trainer's init through `optimizers`, or subclass and override this method in a subclass. |
| 156 | + """ |
| 157 | + if is_sagemaker_mp_enabled(): |
| 158 | + return super().create_optimizer() |
| 159 | + if self.sharded_ddp == ShardedDDPOption.SIMPLE: |
| 160 | + return super().create_optimizer() |
| 161 | + |
| 162 | + opt_model = self.model |
| 163 | + |
| 164 | + if self.optimizer is None: |
| 165 | + decay_parameters = get_parameter_names(opt_model, ALL_LAYERNORM_LAYERS) |
| 166 | + decay_parameters = [name for name in decay_parameters if "bias" not in name] |
| 167 | + if self.args.mm_projector_lr is not None: |
| 168 | + projector_parameters = [name for name, _ in opt_model.named_parameters() if "mm_projector" in name] |
| 169 | + optimizer_grouped_parameters = [ |
| 170 | + { |
| 171 | + "params": [ |
| 172 | + p for n, p in opt_model.named_parameters() if (n in decay_parameters and n not in projector_parameters and p.requires_grad) |
| 173 | + ], |
| 174 | + "weight_decay": self.args.weight_decay, |
| 175 | + }, |
| 176 | + { |
| 177 | + "params": [ |
| 178 | + p for n, p in opt_model.named_parameters() if (n not in decay_parameters and n not in projector_parameters and p.requires_grad) |
| 179 | + ], |
| 180 | + "weight_decay": 0.0, |
| 181 | + }, |
| 182 | + { |
| 183 | + "params": [ |
| 184 | + p for n, p in opt_model.named_parameters() if (n in decay_parameters and n in projector_parameters and p.requires_grad) |
| 185 | + ], |
| 186 | + "weight_decay": self.args.weight_decay, |
| 187 | + "lr": self.args.mm_projector_lr, |
| 188 | + }, |
| 189 | + { |
| 190 | + "params": [ |
| 191 | + p for n, p in opt_model.named_parameters() if (n not in decay_parameters and n in projector_parameters and p.requires_grad) |
| 192 | + ], |
| 193 | + "weight_decay": 0.0, |
| 194 | + "lr": self.args.mm_projector_lr, |
| 195 | + }, |
| 196 | + ] |
| 197 | + else: |
| 198 | + optimizer_grouped_parameters = [ |
| 199 | + { |
| 200 | + "params": [ |
| 201 | + p for n, p in opt_model.named_parameters() if (n in decay_parameters and p.requires_grad) |
| 202 | + ], |
| 203 | + "weight_decay": self.args.weight_decay, |
| 204 | + }, |
| 205 | + { |
| 206 | + "params": [ |
| 207 | + p for n, p in opt_model.named_parameters() if (n not in decay_parameters and p.requires_grad) |
| 208 | + ], |
| 209 | + "weight_decay": 0.0, |
| 210 | + }, |
| 211 | + ] |
| 212 | + |
| 213 | + optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args) |
| 214 | + |
| 215 | + if self.sharded_ddp == ShardedDDPOption.SIMPLE: |
| 216 | + self.optimizer = OSS( |
| 217 | + params=optimizer_grouped_parameters, |
| 218 | + optim=optimizer_cls, |
| 219 | + **optimizer_kwargs, |
| 220 | + ) |
| 221 | + else: |
| 222 | + self.optimizer = optimizer_cls(optimizer_grouped_parameters, **optimizer_kwargs) |
| 223 | + if optimizer_cls.__name__ == "Adam8bit": |
| 224 | + import bitsandbytes |
| 225 | + |
| 226 | + manager = bitsandbytes.optim.GlobalOptimManager.get_instance() |
| 227 | + |
| 228 | + skipped = 0 |
| 229 | + for module in opt_model.modules(): |
| 230 | + if isinstance(module, nn.Embedding): |
| 231 | + skipped += sum({p.data_ptr(): p.numel() for p in module.parameters()}.values()) |
| 232 | + logger.info(f"skipped {module}: {skipped/2**20}M params") |
| 233 | + manager.register_module_override(module, "weight", {"optim_bits": 32}) |
| 234 | + logger.debug(f"bitsandbytes: will optimize {module} in fp32") |
| 235 | + logger.info(f"skipped: {skipped/2**20}M params") |
| 236 | + |
| 237 | + return self.optimizer |
| 238 | + |
149 | 239 | def _save_checkpoint(self, model, trial, metrics=None): |
150 | 240 | if getattr(self.args, 'tune_mm_mlp_adapter', False): |
151 | 241 | from transformers.trainer_utils import PREFIX_CHECKPOINT_DIR |
|
0 commit comments