Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b39e701e21 | ||
|
|
b9d9d1dc43 | ||
|
|
9c5ff0d3cb | ||
|
|
797efa690e | ||
|
|
fff730e6cd | ||
|
|
b583f11948 | ||
|
|
17434661aa | ||
|
|
38ef1f660a | ||
|
|
d4acbfcd4e | ||
|
|
672ee985a7 | ||
|
|
bb9062e48c | ||
|
|
49520692fb | ||
|
|
fe3c052fba | ||
|
|
065825877d | ||
|
|
adf9e6fac8 |
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -35,14 +35,14 @@ jobs:
|
||||
- name: Check Branch
|
||||
id: check-branch
|
||||
run: |
|
||||
if [[ ${{ github.ref }} =~ ^refs/heads/(develop)$ ]]; then
|
||||
if [[ ${{ github.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "match=true" >> $GITHUB_OUTPUT
|
||||
fi # See: https://stackoverflow.com/a/58869470/1123955
|
||||
|
||||
- name: Is A Publish Branch
|
||||
if: steps.check-branch.outputs.match == 'true' && steps.should-deploy.outputs.should_deploy == 'true'
|
||||
env:
|
||||
TWINE_USERNAME: paddle-dev
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.paddlenlp }}
|
||||
PACKAGE: ${{ inputs.package }}
|
||||
PADDLENLP_STABLE_VERSION: "true"
|
||||
|
||||
@@ -58,10 +58,10 @@ def read_local_dataset(path):
|
||||
def main():
|
||||
# Arguments
|
||||
parser = PdArgumentParser((GenerateArgument, QuantArgument, ModelArgument, DataArgument, TrainingArguments))
|
||||
if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
|
||||
gen_args, quant_args, model_args, data_args, training_args = parser.parse_json_file(
|
||||
json_file=os.path.abspath(sys.argv[1])
|
||||
)
|
||||
# Support format as "args.json --arg1 value1 --arg2 value2.”
|
||||
# In case of conflict, command line arguments take precedence.
|
||||
if len(sys.argv) >= 2 and sys.argv[1].endswith(".json"):
|
||||
gen_args, quant_args, model_args, data_args, training_args = parser.parse_json_file_and_cmd_lines()
|
||||
else:
|
||||
gen_args, quant_args, model_args, data_args, training_args = parser.parse_args_into_dataclasses()
|
||||
training_args.print_config(model_args, "Model")
|
||||
|
||||
132
llm/llama/tests/test_argparser.py
Normal file
132
llm/llama/tests/test_argparser.py
Normal file
@@ -0,0 +1,132 @@
|
||||
# Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from llm.run_pretrain import PreTrainingArguments
|
||||
from paddlenlp.trainer.argparser import PdArgumentParser
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = PdArgumentParser((PreTrainingArguments,))
|
||||
# Support format as "args.json --arg1 value1 --arg2 value2.”
|
||||
# In case of conflict, command line arguments take precedence.
|
||||
if len(sys.argv) >= 2 and sys.argv[1].endswith(".json"):
|
||||
model_args = parser.parse_json_file_and_cmd_lines()
|
||||
else:
|
||||
model_args = parser.parse_args_into_dataclasses()
|
||||
return model_args
|
||||
|
||||
|
||||
def create_json_from_dict(data_dict, file_path):
|
||||
with open(file_path, "w") as f:
|
||||
json.dump(data_dict, f)
|
||||
|
||||
|
||||
class ArgparserTest(unittest.TestCase):
|
||||
script_name = "test_argparser.py"
|
||||
args_dict = {
|
||||
"max_steps": 3000,
|
||||
"amp_master_grad": False,
|
||||
"adam_beta1": 0.9,
|
||||
"adam_beta2": 0.999,
|
||||
"amp_custom_black_list": ["reduce_sum", "sin", "cos"],
|
||||
"adam_epsilon": 1e-08,
|
||||
"bf16": False,
|
||||
"enable_linear_fused_grad_add": False,
|
||||
"eval_steps": 3216,
|
||||
"flatten_param_grads": False,
|
||||
"fp16": 1,
|
||||
"log_on_each_node": True,
|
||||
"logging_dir": "./checkpoints/llama2_pretrain_ckpts/runs/Dec27_04-28-35_instance-047hzlt0-4",
|
||||
"logging_first_step": False,
|
||||
"logging_steps": 1,
|
||||
"lr_end": 1e-07,
|
||||
"max_evaluate_steps": -1,
|
||||
"max_grad_norm": 1.0,
|
||||
"min_learning_rate": 3e-06,
|
||||
"no_cuda": False,
|
||||
"num_cycles": 0.5,
|
||||
"num_train_epochs": 3.0,
|
||||
"output_dir": "./checkpoints/llama2_pretrain_ckpts",
|
||||
}
|
||||
|
||||
def test_parse_cmd_lines(self):
|
||||
cmd_line_args = [ArgparserTest.script_name]
|
||||
for key, value in ArgparserTest.args_dict.items():
|
||||
if isinstance(value, list):
|
||||
cmd_line_args.extend([f"--{key}", *[str(v) for v in value]])
|
||||
else:
|
||||
cmd_line_args.extend([f"--{key}", str(value)])
|
||||
with patch("sys.argv", cmd_line_args):
|
||||
model_args = vars(parse_args()[0])
|
||||
for key, value in ArgparserTest.args_dict.items():
|
||||
self.assertEqual(model_args.get(key), value)
|
||||
|
||||
def test_parse_json_file(self):
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmpfile:
|
||||
create_json_from_dict(ArgparserTest.args_dict, tmpfile.name)
|
||||
tmpfile_path = tmpfile.name
|
||||
with patch("sys.argv", [ArgparserTest.script_name, tmpfile_path]):
|
||||
model_args = vars(parse_args()[0])
|
||||
for key, value in ArgparserTest.args_dict.items():
|
||||
self.assertEqual(model_args.get(key), value)
|
||||
os.remove(tmpfile_path)
|
||||
|
||||
def test_parse_json_file_and_cmd_lines(self):
|
||||
half_size = len(ArgparserTest.args_dict) // 2
|
||||
json_part = {k: ArgparserTest.args_dict[k] for k in list(ArgparserTest.args_dict)[:half_size]}
|
||||
cmd_line_part = {k: ArgparserTest.args_dict[k] for k in list(ArgparserTest.args_dict)[half_size:]}
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmpfile:
|
||||
create_json_from_dict(json_part, tmpfile.name)
|
||||
tmpfile_path = tmpfile.name
|
||||
cmd_line_args = [ArgparserTest.script_name, tmpfile_path]
|
||||
for key, value in cmd_line_part.items():
|
||||
if isinstance(value, list):
|
||||
cmd_line_args.extend([f"--{key}", *[str(v) for v in value]])
|
||||
else:
|
||||
cmd_line_args.extend([f"--{key}", str(value)])
|
||||
with patch("sys.argv", cmd_line_args):
|
||||
model_args = vars(parse_args()[0])
|
||||
for key, value in ArgparserTest.args_dict.items():
|
||||
self.assertEqual(model_args.get(key), value)
|
||||
os.remove(tmpfile_path)
|
||||
|
||||
def test_parse_json_file_and_cmd_lines_with_conflict(self):
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmpfile:
|
||||
json.dump(ArgparserTest.args_dict, tmpfile)
|
||||
tmpfile_path = tmpfile.name
|
||||
cmd_line_args = [
|
||||
ArgparserTest.script_name,
|
||||
tmpfile_path,
|
||||
"--min_learning_rate",
|
||||
"2e-5",
|
||||
"--max_steps",
|
||||
"3000",
|
||||
"--log_on_each_node",
|
||||
"False",
|
||||
]
|
||||
with patch("sys.argv", cmd_line_args):
|
||||
model_args = vars(parse_args()[0])
|
||||
self.assertEqual(model_args.get("min_learning_rate"), 2e-5)
|
||||
self.assertEqual(model_args.get("max_steps"), 3000)
|
||||
self.assertEqual(model_args.get("log_on_each_node"), False)
|
||||
for key, value in ArgparserTest.args_dict.items():
|
||||
if key not in ["min_learning_rate", "max_steps", "log_on_each_node"]:
|
||||
self.assertEqual(model_args.get(key), value)
|
||||
os.remove(tmpfile_path)
|
||||
@@ -372,8 +372,10 @@ class PretrainingTrainer(Trainer):
|
||||
|
||||
def main():
|
||||
parser = PdArgumentParser((ModelArguments, DataArguments, PreTrainingArguments))
|
||||
if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
|
||||
model_args, data_args, training_args = parser.parse_json_file(json_file=os.path.abspath(sys.argv[1]))
|
||||
# Support format as "args.json --arg1 value1 --arg2 value2.”
|
||||
# In case of conflict, command line arguments take precedence.
|
||||
if len(sys.argv) >= 2 and sys.argv[1].endswith(".json"):
|
||||
model_args, data_args, training_args = parser.parse_json_file_and_cmd_lines()
|
||||
else:
|
||||
model_args, data_args, training_args = parser.parse_args_into_dataclasses()
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import sys
|
||||
PADDLENLP_STABLE_VERSION = "PADDLENLP_STABLE_VERSION"
|
||||
|
||||
|
||||
__version__ = "2.6.1.post"
|
||||
__version__ = "2.7.2.post"
|
||||
if os.getenv(PADDLENLP_STABLE_VERSION):
|
||||
__version__ = __version__.replace(".post", "")
|
||||
|
||||
|
||||
@@ -231,12 +231,12 @@ class LoRAModel(nn.Layer):
|
||||
|
||||
if self.is_pipelinemodel:
|
||||
self.model._single_to_pp_mapping = None
|
||||
if self.quantized and merge_tensor_parallel and self.lora_config.tensor_parallel_degre > 1:
|
||||
if self.quantized and merge_tensor_parallel and self.lora_config.tensor_parallel_degree > 1:
|
||||
merge_tensor_parallel = False
|
||||
logger.warning(
|
||||
"Quantized strategy does not support merge_tensor_parallel. Set merge_tensor_parallel to False."
|
||||
)
|
||||
if self.is_pipelinemodel and merge_tensor_parallel and self.lora_config.tensor_parallel_degre > 1:
|
||||
if self.is_pipelinemodel and merge_tensor_parallel and self.lora_config.tensor_parallel_degree > 1:
|
||||
merge_tensor_parallel = False
|
||||
logger.warning(
|
||||
"Pipeline parallism does not support merge_tensor_parallel. Set merge_tensor_parallel to False."
|
||||
@@ -489,7 +489,7 @@ class LoRAModel(nn.Layer):
|
||||
freeze_numel += np.prod(weight.shape)
|
||||
else:
|
||||
trainable_numel += np.prod(weight.shape)
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"Frozen parameters: {freeze_numel:.2e} || Trainable parameters:{trainable_numel:.2e} || Total parameters:{freeze_numel+trainable_numel:.2e}|| Trainable:{trainable_numel / (freeze_numel+trainable_numel):.2%}"
|
||||
)
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ class PrefixModelForCausalLM(paddle.nn.Layer):
|
||||
freeze_numel += np.prod(weight.shape)
|
||||
else:
|
||||
trainable_numel += np.prod(weight.shape)
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"Frozen parameters: {freeze_numel:.2e} || Trainable parameters:{trainable_numel:.2e} || Total parameters:{freeze_numel+trainable_numel:.2e}|| Trainable:{trainable_numel / (freeze_numel+trainable_numel):.2%}"
|
||||
)
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class QuantizationLinear(nn.Layer):
|
||||
self.quant_scale = self.create_parameter(
|
||||
shape=[out_features],
|
||||
attr=scale_attr,
|
||||
dtype="float32",
|
||||
dtype=self._dtype,
|
||||
is_bias=False,
|
||||
)
|
||||
if self.quant_algo in ["fp4", "nf4"]:
|
||||
@@ -231,7 +231,7 @@ class ColumnParallelQuantizationLinear(nn.Layer):
|
||||
self.quant_scale = self.create_parameter(
|
||||
shape=[self.output_size_per_partition],
|
||||
attr=scale_attr,
|
||||
dtype="float32",
|
||||
dtype=self._dtype,
|
||||
is_bias=False,
|
||||
)
|
||||
self.quant_scale.is_distributed = True if self.is_mp else False
|
||||
@@ -345,7 +345,7 @@ class RowParallelQuantizationLinear(nn.Layer):
|
||||
self.quant_scale = self.create_parameter(
|
||||
shape=[out_features],
|
||||
attr=scale_attr,
|
||||
dtype="float32",
|
||||
dtype=self._dtype,
|
||||
is_bias=False,
|
||||
)
|
||||
self.quant_scale.is_distributed = True if self.is_mp else False
|
||||
|
||||
@@ -109,9 +109,12 @@ def convert_to_quantize_state_dict_with_check(state_dict, quantization_linear_li
|
||||
raise ValueError(
|
||||
f"{quant_weight_name} should be {paddle.int8} in state_dict but received dtype {state_dict[quant_weight_name].dtype}."
|
||||
)
|
||||
if state_dict[quant_scale_name].dtype != paddle.float32:
|
||||
if (
|
||||
state_dict[quant_scale_name].dtype != paddle.float16
|
||||
and state_dict[quant_scale_name].dtype != paddle.bfloat16
|
||||
):
|
||||
raise ValueError(
|
||||
f"{quant_scale_name} should be {paddle.float32} in state_dict but received dtype {state_dict[quant_scale_name].dtype}."
|
||||
f"{quant_scale_name} should be {paddle.float16} or {paddle.bfloat16} in state_dict but received dtype {state_dict[quant_scale_name].dtype}."
|
||||
)
|
||||
elif weight_name in state_dict:
|
||||
target_weight = state_dict.pop(weight_name).cast(dtype)
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
from .argparser import *
|
||||
from .training_args import *
|
||||
from .compression_args import *
|
||||
from .plugins.timer import *
|
||||
from .trainer import *
|
||||
from .trainer_callback import *
|
||||
from .trainer_utils import *
|
||||
from .trainer_compress import *
|
||||
from .training_args_seq2seq import *
|
||||
from .trainer_seq2seq import *
|
||||
from .trainer_utils import *
|
||||
from .training_args import *
|
||||
from .training_args_seq2seq import *
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import dataclasses
|
||||
import json
|
||||
import sys
|
||||
import warnings
|
||||
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError
|
||||
from copy import copy
|
||||
from enum import Enum
|
||||
@@ -247,6 +248,49 @@ class PdArgumentParser(ArgumentParser):
|
||||
outputs.append(obj)
|
||||
return (*outputs,)
|
||||
|
||||
def parse_json_file_and_cmd_lines(self) -> Tuple[DataClass, ...]:
|
||||
"""
|
||||
Extend the functionality of `parse_json_file` to handle command line arguments in addition to loading a JSON
|
||||
file.
|
||||
|
||||
When there is a conflict between the command line arguments and the JSON file configuration,
|
||||
the command line arguments will take precedence.
|
||||
|
||||
Returns:
|
||||
Tuple consisting of:
|
||||
|
||||
- the dataclass instances in the same order as they were passed to the initializer.abspath
|
||||
"""
|
||||
if not sys.argv[1].endswith(".json"):
|
||||
raise ValueError(f"The first argument should be a JSON file, but it is {sys.argv[1]}")
|
||||
json_file = Path(sys.argv[1])
|
||||
if json_file.exists():
|
||||
with open(json_file, "r") as file:
|
||||
data = json.load(file)
|
||||
json_args = []
|
||||
for key, value in data.items():
|
||||
if isinstance(value, list):
|
||||
json_args.extend([f"--{key}", *[str(v) for v in value]])
|
||||
else:
|
||||
json_args.extend([f"--{key}", str(value)])
|
||||
else:
|
||||
raise FileNotFoundError(f"The argument file {json_file} does not exist.")
|
||||
# In case of conflict, command line arguments take precedence
|
||||
args = json_args + sys.argv[2:]
|
||||
namespace, remaining_args = self.parse_known_args(args=args)
|
||||
outputs = []
|
||||
for dtype in self.dataclass_types:
|
||||
keys = {f.name for f in dataclasses.fields(dtype) if f.init}
|
||||
inputs = {k: v for k, v in vars(namespace).items() if k in keys}
|
||||
for k in keys:
|
||||
delattr(namespace, k)
|
||||
obj = dtype(**inputs)
|
||||
outputs.append(obj)
|
||||
if remaining_args:
|
||||
warnings.warn(f"Some specified arguments are not used by the PdArgumentParser: {remaining_args}")
|
||||
|
||||
return (*outputs,)
|
||||
|
||||
def parse_dict(self, args: dict) -> Tuple[DataClass, ...]:
|
||||
"""
|
||||
Alternative helper method that does not use `argparse` at all, instead uses a dict and populating the dataclass
|
||||
|
||||
@@ -96,7 +96,7 @@ class VisualDLCallback(TrainerCallback):
|
||||
|
||||
if self.vdl_writer is not None:
|
||||
self.vdl_writer.add_text("args", args.to_json_string())
|
||||
if "model" in kwargs:
|
||||
if "model" in kwargs and logger.logger.level < 20:
|
||||
model = kwargs["model"]
|
||||
if isinstance(model, LoRAModel) or isinstance(model, PrefixModelForCausalLM):
|
||||
model = kwargs["model"].model
|
||||
|
||||
@@ -31,14 +31,14 @@ class _Timer:
|
||||
|
||||
def start(self):
|
||||
"""Start the timer."""
|
||||
assert not self.started_, "timer has already started"
|
||||
assert not self.started_, f"{self.name} timer has already started"
|
||||
paddle.device.synchronize()
|
||||
self.start_time = time.time()
|
||||
self.started_ = True
|
||||
|
||||
def stop(self):
|
||||
"""Stop the timers."""
|
||||
assert self.started_, "timer is not started."
|
||||
assert self.started_, f"{self.name} timer is not started."
|
||||
paddle.device.synchronize()
|
||||
self.elapsed_ += time.time() - self.start_time
|
||||
self.started_ = False
|
||||
@@ -65,6 +65,32 @@ class _Timer:
|
||||
return elapsed_
|
||||
|
||||
|
||||
class RuntimeTimer:
|
||||
"""A timer that can be dynamically adjusted during runtime."""
|
||||
|
||||
def __init__(self, name):
|
||||
self.timer = _Timer(name)
|
||||
|
||||
def start(self, name):
|
||||
"""Start the RuntimeTimer."""
|
||||
self.timer.name = name
|
||||
self.timer.start()
|
||||
|
||||
def stop(self):
|
||||
"""Stop the RuntimeTimer."""
|
||||
self.timer.stop()
|
||||
|
||||
def log(self):
|
||||
"""Log, stop and reset the RuntimeTimer."""
|
||||
runtime = self.timer.elapsed(reset=True)
|
||||
if self.timer.started_ is True:
|
||||
self.timer.stop()
|
||||
self.timer.reset()
|
||||
|
||||
string = "[timelog] {}: {:.2f}s ({}) ".format(self.timer.name, runtime, time.strftime("%Y-%m-%d %H:%M:%S"))
|
||||
return string
|
||||
|
||||
|
||||
class Timers:
|
||||
"""Group of timers."""
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ def save_unified_checkpoint(args, model, optimizer, output_dir, safe_serializati
|
||||
else:
|
||||
raise ValueError("Unified checkpoint only supports PretrainedModel")
|
||||
|
||||
skip_save_model_weight = False
|
||||
if UnifiedCheckpointOption.SKIP_SAVE_MODEL_WEIGHT.value in args.unified_checkpoint_config:
|
||||
if is_need_master_weight(optimizer, is_fp16_or_bp16=(args.fp16 or args.bf16)):
|
||||
logger.info(
|
||||
@@ -122,36 +123,40 @@ def save_unified_checkpoint(args, model, optimizer, output_dir, safe_serializati
|
||||
"The master weight will be loaded as model weights for next resumption."
|
||||
)
|
||||
# not save model weight, load from master weight
|
||||
return
|
||||
config_to_save = None
|
||||
state_dict, config_to_save, shard_file, sharded_index = unified_checkpoint_into_shards(
|
||||
args, model_to_save, safe_serialization=safe_serialization
|
||||
)
|
||||
skip_save_model_weight = True
|
||||
|
||||
save_directory = output_dir
|
||||
os.makedirs(save_directory, exist_ok=True)
|
||||
|
||||
is_sync_save = True
|
||||
if "async_save" in args.unified_checkpoint_config:
|
||||
is_sync_save = False
|
||||
file_save_async_or_sync(
|
||||
state_dict, os.path.join(save_directory, shard_file), safe_serialization, is_sync=is_sync_save
|
||||
)
|
||||
# save model weights
|
||||
if not skip_save_model_weight:
|
||||
state_dict, shard_file, sharded_index = unified_checkpoint_into_shards(
|
||||
args, model_to_save, safe_serialization=safe_serialization
|
||||
)
|
||||
is_sync_save = True
|
||||
if "async_save" in args.unified_checkpoint_config:
|
||||
is_sync_save = False
|
||||
file_save_async_or_sync(
|
||||
state_dict, os.path.join(save_directory, shard_file), safe_serialization, is_sync=is_sync_save
|
||||
)
|
||||
|
||||
if sharded_index is not None:
|
||||
if not safe_serialization:
|
||||
path = os.path.join(output_dir, PADDLE_WEIGHTS_INDEX_NAME)
|
||||
else:
|
||||
path = os.path.join(output_dir, SAFE_WEIGHTS_INDEX_NAME)
|
||||
|
||||
with open(path, "w") as f:
|
||||
json.dump(sharded_index, f, indent=4)
|
||||
|
||||
# save the config
|
||||
config_to_save = save_config(model_to_save)
|
||||
# Attach architecture to the config
|
||||
config_to_save.architectures = [model_to_save.__class__.__name__]
|
||||
# Save the config
|
||||
if args.should_save:
|
||||
config_to_save.save_pretrained(save_directory)
|
||||
|
||||
if sharded_index is not None:
|
||||
if not safe_serialization:
|
||||
path = os.path.join(output_dir, PADDLE_WEIGHTS_INDEX_NAME)
|
||||
else:
|
||||
path = os.path.join(output_dir, SAFE_WEIGHTS_INDEX_NAME)
|
||||
|
||||
with open(path, "w") as f:
|
||||
json.dump(sharded_index, f, indent=4)
|
||||
paddle.device.cuda.empty_cache()
|
||||
|
||||
|
||||
def load_unified_checkpoint(args, model, optimizer, resume_from_checkpoint: str, safe_serialization=False) -> None:
|
||||
@@ -252,6 +257,18 @@ def load_unified_checkpoint_locally(args, model, resume_from_checkpoint: str, sa
|
||||
raise RuntimeError(f"Error(s) in loading state_dict for {model.__class__.__name__}:\n\t{error_msg}")
|
||||
|
||||
|
||||
def save_config(model_to_save):
|
||||
dtype = get_parameter_dtype(model_to_save)
|
||||
model_to_save.config.dtype = str(dtype).split(".")[1]
|
||||
config_to_save = copy.deepcopy(model_to_save.config)
|
||||
|
||||
if config_to_save.tensor_parallel_degree > 1:
|
||||
# do we need to change?
|
||||
config_to_save.tensor_parallel_degree = 1
|
||||
|
||||
return config_to_save
|
||||
|
||||
|
||||
def unified_checkpoint_into_shards(
|
||||
args,
|
||||
model_to_save,
|
||||
@@ -266,14 +283,13 @@ def unified_checkpoint_into_shards(
|
||||
Returns:
|
||||
tuple: state_dict, config, shard_file: file name, sharded_index: map for weight to file name.
|
||||
"""
|
||||
paddle.device.cuda.empty_cache()
|
||||
assert hasattr(model_to_save, "config")
|
||||
|
||||
state_dict = model_to_save.state_dict()
|
||||
|
||||
all_filter_keys = filter_params(model_to_save, state_dict)
|
||||
|
||||
dtype = get_parameter_dtype(model_to_save)
|
||||
model_to_save.config.dtype = str(dtype).split(".")[1]
|
||||
config_to_save = copy.deepcopy(model_to_save.config)
|
||||
|
||||
if config_to_save.tensor_parallel_degree > 1:
|
||||
@@ -282,10 +298,6 @@ def unified_checkpoint_into_shards(
|
||||
)
|
||||
state_dict = merge_tensor_parallel_with_shard(state_dict, tp_actions, all_filter_keys)
|
||||
|
||||
if config_to_save.tensor_parallel_degree > 1:
|
||||
# do we need to change?
|
||||
config_to_save.tensor_parallel_degree = 1
|
||||
|
||||
# build index json file
|
||||
index_weight_file = {}
|
||||
total_size = 0
|
||||
@@ -302,7 +314,9 @@ def unified_checkpoint_into_shards(
|
||||
total_size_list,
|
||||
)
|
||||
|
||||
return state_dict, config_to_save, shard_file, sharded_index
|
||||
paddle.device.cuda.empty_cache()
|
||||
|
||||
return state_dict, shard_file, sharded_index
|
||||
|
||||
|
||||
def save_unified_optimizer(args, model, optimizer, output_dir, safe_serialization=False):
|
||||
@@ -324,6 +338,8 @@ def save_unified_optimizer(args, model, optimizer, output_dir, safe_serializatio
|
||||
optim_state_dict, shard_optim_file, sharded_optim_index = results[0]
|
||||
master_weight_state_dict, shard_master_weight_file, sharded_master_weight_index = results[1]
|
||||
|
||||
paddle.device.cuda.empty_cache()
|
||||
|
||||
save_directory = output_dir
|
||||
os.makedirs(save_directory, exist_ok=True)
|
||||
|
||||
@@ -343,16 +359,17 @@ def save_unified_optimizer(args, model, optimizer, output_dir, safe_serializatio
|
||||
)
|
||||
|
||||
if sharded_optim_index is not None:
|
||||
if not safe_serialization:
|
||||
path = os.path.join(output_dir, PADDLE_OPTIMIZER_INDEX_NAME)
|
||||
master_path = os.path.join(output_dir, PADDLE_MASTER_WEIGHTS_INDEX_NAME)
|
||||
else:
|
||||
path = os.path.join(output_dir, SAFE_OPTIMIZER_INDEX_NAME)
|
||||
master_path = os.path.join(output_dir, SAFE_MASTER_WEIGHTS_INDEX_NAME)
|
||||
|
||||
optimizer_index_name = SAFE_OPTIMIZER_INDEX_NAME if safe_serialization else PADDLE_OPTIMIZER_INDEX_NAME
|
||||
path = os.path.join(output_dir, optimizer_index_name)
|
||||
with open(path, "w") as f:
|
||||
json.dump(sharded_optim_index, f, indent=4)
|
||||
|
||||
master_weights_name = (
|
||||
SAFE_MASTER_WEIGHTS_INDEX_NAME if safe_serialization else PADDLE_MASTER_WEIGHTS_INDEX_NAME
|
||||
)
|
||||
if UnifiedCheckpointOption.SKIP_SAVE_MODEL_WEIGHT.value in args.unified_checkpoint_config:
|
||||
master_weights_name = SAFE_WEIGHTS_INDEX_NAME if safe_serialization else PADDLE_WEIGHTS_INDEX_NAME
|
||||
master_path = os.path.join(output_dir, master_weights_name)
|
||||
if master_weight_state_dict is not None:
|
||||
with open(master_path, "w") as f:
|
||||
json.dump(sharded_master_weight_index, f, indent=4)
|
||||
@@ -504,6 +521,7 @@ def unified_optimizer_into_shards(
|
||||
optimizer (Optimizer): optimizer to save.
|
||||
safe_serialization (bool, optional): safe serialization using safetensors. Defaults to False.
|
||||
"""
|
||||
paddle.device.cuda.empty_cache()
|
||||
optim_state_dict = nested_copy(optimizer.state_dict())
|
||||
master_weights = None
|
||||
if "master_weights" in optim_state_dict.keys():
|
||||
@@ -549,18 +567,23 @@ def unified_optimizer_into_shards(
|
||||
tp_actions,
|
||||
filter_optim_keys,
|
||||
)
|
||||
paddle.device.cuda.empty_cache()
|
||||
|
||||
if master_weights is not None:
|
||||
master_weights = merge_tensor_parallel_for_optimizer(
|
||||
master_weights,
|
||||
tp_actions,
|
||||
filter_master_keys,
|
||||
)
|
||||
paddle.device.cuda.empty_cache()
|
||||
|
||||
# build index json file
|
||||
index_optimizer_file, index_master_weight_file = {}, {}
|
||||
total_optim_size, total_master_weight_size = 0, 0
|
||||
optimizer_name = SAFE_OPTIMIZER_NAME if safe_serialization else PADDLE_OPTIMIZER_NAME
|
||||
master_weights_name = SAFE_MASTER_WEIGHTS_NAME if safe_serialization else PADDLE_MASTER_WEIGHTS_NAME
|
||||
if UnifiedCheckpointOption.SKIP_SAVE_MODEL_WEIGHT.value in args.unified_checkpoint_config:
|
||||
master_weights_name = SAFE_WEIGHTS_NAME if safe_serialization else PADDLE_WEIGHTS_NAME
|
||||
shard_optimizer_file = get_sharded_file_name(args, optimizer_name, is_optimizer=True)
|
||||
shard_master_weight_file = get_sharded_file_name(args, master_weights_name, is_optimizer=True)
|
||||
|
||||
@@ -589,6 +612,7 @@ def unified_optimizer_into_shards(
|
||||
else:
|
||||
sharded_optim_index["master_weights"] = False
|
||||
|
||||
paddle.device.cuda.empty_cache()
|
||||
if master_weights is None:
|
||||
return [(optim_state_dict, shard_optimizer_file, sharded_optim_index)]
|
||||
else:
|
||||
@@ -1648,6 +1672,10 @@ def update_master_weight_status(args, optimizer, has_master_weight, safe_seriali
|
||||
index_filename_master_weights = (
|
||||
PADDLE_MASTER_WEIGHTS_INDEX_NAME if not safe_serialization else SAFE_MASTER_WEIGHTS_INDEX_NAME
|
||||
)
|
||||
if UnifiedCheckpointOption.SKIP_SAVE_MODEL_WEIGHT.value in args.unified_checkpoint_config:
|
||||
index_filename_master_weights = (
|
||||
PADDLE_WEIGHTS_INDEX_NAME if not safe_serialization else SAFE_WEIGHTS_INDEX_NAME
|
||||
)
|
||||
else:
|
||||
has_master_weight = False
|
||||
index_filename_master_weights = None
|
||||
|
||||
@@ -104,7 +104,7 @@ from ..utils.import_utils import is_datasets_available, is_paddle_cuda_available
|
||||
from ..utils.log import logger
|
||||
from .argparser import strtobool
|
||||
from .integrations import get_reporting_integration_callbacks
|
||||
from .plugins.timer import get_timers, set_timers
|
||||
from .plugins.timer import RuntimeTimer, get_timers, set_timers
|
||||
from .plugins.unified_checkpoint import (
|
||||
load_unified_checkpoint,
|
||||
load_unified_optimizer,
|
||||
@@ -304,6 +304,7 @@ class Trainer:
|
||||
if not args.skip_profile_timer:
|
||||
set_timers()
|
||||
self.timers = get_timers()
|
||||
self.runtime_timer = RuntimeTimer("RuntimeTimer")
|
||||
|
||||
self.model_wrapped = model
|
||||
self.model = model
|
||||
@@ -506,6 +507,7 @@ class Trainer:
|
||||
`bool` and equals `True`, load the last checkpoint in *args.output_dir* as saved by a previous instance
|
||||
of [`Trainer`]. Only load model state dict.
|
||||
"""
|
||||
self.runtime_timer.start("checkpoint loading time")
|
||||
resume_from_checkpoint = None if not resume_from_checkpoint else resume_from_checkpoint
|
||||
|
||||
# Load potential model checkpoint
|
||||
@@ -531,10 +533,12 @@ class Trainer:
|
||||
safe_serialization=True,
|
||||
)
|
||||
logger.info(f"Loading model from {resume_from_checkpoint} using unified checkpoint.")
|
||||
self.runtime_timer.stop()
|
||||
return
|
||||
|
||||
if isinstance(self.model, LoRAModel) or isinstance(self.model, PrefixModelForCausalLM):
|
||||
self._load_from_peft_checkpoint(resume_from_checkpoint)
|
||||
self.runtime_timer.stop()
|
||||
return
|
||||
|
||||
weight_name = PADDLE_WEIGHTS_NAME
|
||||
@@ -584,6 +588,7 @@ class Trainer:
|
||||
|
||||
elif resume_from_checkpoint is not None:
|
||||
logger.info(f"not loading ckpt :{self.args.dataset_rank}")
|
||||
self.runtime_timer.stop()
|
||||
|
||||
def _wrap_model_and_load_sharded_checkpoint(self, resume_from_checkpoint):
|
||||
# In the sharded mode, should invoke _load_from_checkpoint after _wrap_model.
|
||||
@@ -639,7 +644,6 @@ class Trainer:
|
||||
|
||||
# memory metrics - must set up as early as possible
|
||||
self._memory_tracker.start()
|
||||
|
||||
if not self.args.should_load_sharding_stage1_model:
|
||||
self._load_from_checkpoint(resume_from_checkpoint)
|
||||
|
||||
@@ -695,6 +699,7 @@ class Trainer:
|
||||
|
||||
if self.args.should_load_sharding_stage1_model:
|
||||
model = self._wrap_model_and_load_sharded_checkpoint(resume_from_checkpoint)
|
||||
|
||||
elif self.args.should_save_sharding_stage1_model:
|
||||
# In the non-sharded mode, should invoke _load_from_checkpoint before _wrap_model.
|
||||
# In this mode, the rank0 load all params and the _wrap_model implicitly broadcast params from rank0 to the other ranks.
|
||||
@@ -718,6 +723,8 @@ class Trainer:
|
||||
self.create_optimizer_and_scheduler(num_training_steps=max_steps)
|
||||
self._load_optimizer_and_scheduler(resume_from_checkpoint)
|
||||
|
||||
logger.info(f"{self.runtime_timer.log()}")
|
||||
|
||||
logger.info("***** Running training *****")
|
||||
logger.info(f" Num examples = {num_examples:,}")
|
||||
logger.info(f" Num Epochs = {num_train_epochs}")
|
||||
@@ -729,7 +736,7 @@ class Trainer:
|
||||
# per_device_trainable_numel = sum(p.numel().item() for p in model.parameters() if not p.stop_gradient)
|
||||
# TODO: Temporary fix since Tensor.numel() not supported in distributed mode
|
||||
per_device_trainable_numel = sum(np.prod(p.shape) for p in model.parameters() if not p.stop_gradient)
|
||||
logger.info(f" Number of trainable parameters = {per_device_trainable_numel:,} (per device)")
|
||||
logger.debug(f" Number of trainable parameters = {per_device_trainable_numel:,} (per device)")
|
||||
if self.args.use_hybrid_parallel:
|
||||
# todo fix for pipeline_parallel_degree
|
||||
parts_num = max(self.args.tensor_parallel_degree, 1) * max(self.args.pipeline_parallel_degree, 1)
|
||||
@@ -745,7 +752,7 @@ class Trainer:
|
||||
trainable_numel = trainable_numel // self.args.sep_parallel_degree
|
||||
# the numel is roughly, because the tensor parallel still hold own bias or layer_norm weight without splited
|
||||
# so, the trainable numel is a little bigger than real.
|
||||
logger.info(f" Number of trainable parameters = {trainable_numel:,} (all devices, roughly)")
|
||||
logger.debug(f" Number of trainable parameters = {trainable_numel:,} (all devices, roughly)")
|
||||
|
||||
start_time = time.time()
|
||||
self._globalstep_last_start_time = time.time()
|
||||
@@ -1239,6 +1246,7 @@ class Trainer:
|
||||
paddle.device.cuda.synchronize()
|
||||
|
||||
self._save_checkpoint(model, metrics=metrics)
|
||||
logger.info(f"{self.runtime_timer.log()}")
|
||||
self.control = self.callback_handler.on_save(self.args, self.state, self.control)
|
||||
|
||||
def _get_learning_rate(self):
|
||||
@@ -1293,6 +1301,9 @@ class Trainer:
|
||||
)
|
||||
|
||||
def _get_eval_sampler(self, eval_dataset: Dataset):
|
||||
if eval_dataset is None or not has_length(eval_dataset):
|
||||
return None
|
||||
|
||||
if self.args.world_size <= 1:
|
||||
return paddle.io.BatchSampler(
|
||||
eval_dataset,
|
||||
@@ -2024,11 +2035,20 @@ class Trainer:
|
||||
self.model_wrapped.get_all_parameters(convert2cpu=True)
|
||||
|
||||
if self.args.should_save_model_state:
|
||||
unified_checkpoint_config_backup = self.args.unified_checkpoint_config
|
||||
# backup and remove unified_checkpoint_config for not trine stage
|
||||
if not self.is_in_train:
|
||||
self.args.unified_checkpoint_config = []
|
||||
|
||||
self._save(output_dir=output_dir, merge_tensor_parallel=merge_tensor_parallel)
|
||||
|
||||
# recover unified_checkpoint_config for not trine stage
|
||||
if not self.is_in_train:
|
||||
self.args.unified_checkpoint_config = unified_checkpoint_config_backup
|
||||
|
||||
def _save_checkpoint(self, model, metrics=None):
|
||||
# assert unwrap_model(model) is self.model, "internal model should be a reference to self.model"
|
||||
|
||||
self.runtime_timer.start("checkpoint saving time")
|
||||
# Save model checkpoint
|
||||
checkpoint_folder = f"{PREFIX_CHECKPOINT_DIR}-{self.state.global_step}"
|
||||
|
||||
@@ -2074,6 +2094,7 @@ class Trainer:
|
||||
if self.do_grad_scaling:
|
||||
paddle.save(self.scaler.state_dict(), os.path.join(output_dir, SCALER_NAME))
|
||||
|
||||
self.runtime_timer.stop()
|
||||
# Determine the new best metric / best model checkpoint
|
||||
if metrics is not None and self.args.metric_for_best_model is not None:
|
||||
metric_to_check = self.args.metric_for_best_model
|
||||
@@ -2292,10 +2313,13 @@ class Trainer:
|
||||
|
||||
def _load_optimizer_and_scheduler(self, checkpoint):
|
||||
"""If optimizer and scheduler states exist, load them."""
|
||||
self.runtime_timer.start("checkpoint loading time")
|
||||
if checkpoint is None:
|
||||
self.runtime_timer.stop()
|
||||
return
|
||||
|
||||
if (not self.args.should_load_sharding_stage1_model) and self.args.ignore_load_lr_and_optim:
|
||||
self.runtime_timer.stop()
|
||||
return
|
||||
|
||||
opt_state_dict = None
|
||||
@@ -2304,8 +2328,8 @@ class Trainer:
|
||||
checkpoint, OPTIMIZER_NAME, self.model_wrapped
|
||||
)
|
||||
else:
|
||||
use_unified_checkpoint = False
|
||||
if self.args.unified_checkpoint:
|
||||
use_unified_checkpoint = False
|
||||
if self.is_unified_checkpoint(checkpoint):
|
||||
use_unified_checkpoint = True
|
||||
else:
|
||||
@@ -2354,6 +2378,7 @@ class Trainer:
|
||||
self.scaler.load_state_dict(
|
||||
paddle.load(distributed_file(os.path.join(checkpoint, SCALER_NAME)), return_numpy=True)
|
||||
)
|
||||
self.runtime_timer.stop()
|
||||
|
||||
def log(self, logs: Dict[str, float], **kwargs) -> None:
|
||||
"""
|
||||
@@ -2380,7 +2405,7 @@ class Trainer:
|
||||
kwargs.update(timer=self.timers, paddle_pipeline_timers=paddle_pipeline_timers)
|
||||
|
||||
if self.state.epoch is not None:
|
||||
logs["epoch"] = round(self.state.epoch, 4)
|
||||
logs["progress_or_epoch"] = round(self.state.epoch, 4)
|
||||
output = {**logs, **{"step": self.state.global_step}}
|
||||
self.state.log_history.append(output)
|
||||
self.control = self.callback_handler.on_log(self.args, self.state, self.control, logs, **kwargs)
|
||||
@@ -2941,23 +2966,23 @@ class Trainer:
|
||||
"""
|
||||
print config values
|
||||
"""
|
||||
logger.info("=" * 60)
|
||||
logger.debug("=" * 60)
|
||||
if args is None:
|
||||
args = self.args
|
||||
key = "Training"
|
||||
import paddlenlp
|
||||
|
||||
logger.info("{:^40}".format("{} Configuration Arguments".format(key)))
|
||||
logger.info("{:30}: {}".format("paddle commit id", paddle.version.commit))
|
||||
logger.info("{:30}: {}".format("paddlenlp commit id", paddlenlp.version.commit))
|
||||
logger.debug("{:^40}".format("{} Configuration Arguments".format(key)))
|
||||
logger.debug("{:30}: {}".format("paddle commit id", paddle.version.commit))
|
||||
logger.debug("{:30}: {}".format("paddlenlp commit id", paddlenlp.version.commit))
|
||||
|
||||
for a in dir(args):
|
||||
if a[:2] != "__": # don't print double underscore methods
|
||||
v = getattr(args, a)
|
||||
if not isinstance(v, types.MethodType):
|
||||
logger.info("{:30}: {}".format(a, v))
|
||||
logger.debug("{:30}: {}".format(a, v))
|
||||
|
||||
logger.info("")
|
||||
logger.debug("")
|
||||
|
||||
def is_unified_checkpoint(self, resume_from_checkpoint, safe_serialization=True):
|
||||
is_unified_checkpoint_type = False
|
||||
|
||||
@@ -515,7 +515,7 @@ class ProgressCallback(TrainerCallback):
|
||||
logs_str = ", ".join(f"{k}: {v}" for k, v in logs.items())
|
||||
else:
|
||||
logs_str = str(logs)
|
||||
self.training_bar.write(logs_str)
|
||||
logger.info(logs_str)
|
||||
|
||||
def on_train_end(self, args, state, control, **kwargs):
|
||||
if state.is_local_process_zero:
|
||||
|
||||
@@ -1308,8 +1308,10 @@ class TrainingArguments:
|
||||
self.unified_checkpoint_config = [
|
||||
"skip_save_model_weight",
|
||||
"master_weight_compatible",
|
||||
"async_save",
|
||||
# "async_save",
|
||||
]
|
||||
else:
|
||||
self.unified_checkpoint_config = self.unified_checkpoint_config.split(" ")
|
||||
|
||||
if self.report_to is None:
|
||||
logger.info(
|
||||
@@ -1701,21 +1703,21 @@ class TrainingArguments:
|
||||
"""
|
||||
print all config values.
|
||||
"""
|
||||
logger.info("=" * 60)
|
||||
logger.debug("=" * 60)
|
||||
if args is None:
|
||||
args = self
|
||||
key = "Training"
|
||||
|
||||
import paddlenlp
|
||||
|
||||
logger.info("{:^40}".format("{} Configuration Arguments".format(key)))
|
||||
logger.info("{:30}: {}".format("paddle commit id", paddle.version.commit))
|
||||
logger.info("{:30}: {}".format("paddlenlp commit id", paddlenlp.version.commit))
|
||||
logger.debug("{:^40}".format("{} Configuration Arguments".format(key)))
|
||||
logger.debug("{:30}: {}".format("paddle commit id", paddle.version.commit))
|
||||
logger.debug("{:30}: {}".format("paddlenlp commit id", paddlenlp.version.commit))
|
||||
|
||||
for a in dir(args):
|
||||
if a[:2] != "__": # don't print double underscore methods
|
||||
v = getattr(args, a)
|
||||
if not isinstance(v, types.MethodType):
|
||||
logger.info("{:30}: {}".format(a, v))
|
||||
logger.debug("{:30}: {}".format(a, v))
|
||||
|
||||
logger.info("")
|
||||
logger.debug("")
|
||||
|
||||
@@ -42,14 +42,17 @@ from huggingface_hub import (
|
||||
)
|
||||
from huggingface_hub.utils import EntryNotFoundError
|
||||
from paddle import Tensor
|
||||
from paddle.distributed.fleet.meta_parallel.parallel_layers import SharedLayerDesc
|
||||
from paddle.distributed.fleet.meta_parallel.parallel_layers import (
|
||||
PipelineLayer,
|
||||
SharedLayerDesc,
|
||||
)
|
||||
from paddle.nn import Embedding, Layer
|
||||
|
||||
# TODO(fangzeyang) Temporary fix and replace by paddle framework downloader later
|
||||
from paddle.utils.download import is_url as is_remote_url
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from paddlenlp.utils.downloader import get_path_from_url_with_filelock, hf_file_exists
|
||||
from paddlenlp.utils.downloader import get_path_from_url_with_filelock
|
||||
from paddlenlp.utils.env import (
|
||||
CONFIG_NAME,
|
||||
LEGACY_CONFIG_NAME,
|
||||
@@ -364,28 +367,7 @@ def resolve_weight_file_from_hf_hub(repo_id: str, cache_dir: str, support_conver
|
||||
support_conversion (bool): whether support converting pytorch weight file to paddle weight file
|
||||
subfolder (str, optional) An optional value corresponding to a folder inside the repo.
|
||||
"""
|
||||
is_local = os.path.isdir(repo_id)
|
||||
if not is_local:
|
||||
if hf_file_exists(repo_id, PADDLE_WEIGHTS_NAME, subfolder=subfolder):
|
||||
file_name = PADDLE_WEIGHTS_NAME
|
||||
assert (
|
||||
support_conversion is False
|
||||
), "Please call set convert_from_torch for paddle weights on huggingface hub, eg. Model.from_pretrained(model_name, from_hf_hub=True, convert_from_torch=False)"
|
||||
elif hf_file_exists(repo_id, PYTORCH_WEIGHTS_NAME, subfolder=subfolder):
|
||||
if not support_conversion:
|
||||
raise EntryNotFoundError(
|
||||
f"can not download `{PADDLE_WEIGHTS_NAME} from https://huggingface.co/{repo_id}` "
|
||||
"and current model doesn't support conversion from pytorch weight file to paddle weight file"
|
||||
)
|
||||
file_name = PYTORCH_WEIGHTS_NAME
|
||||
else:
|
||||
raise EntryNotFoundError(
|
||||
message=f"can not find the paddle/pytorch weight file from: https://huggingface.co/{repo_id}",
|
||||
response=None,
|
||||
)
|
||||
else:
|
||||
# for local file, we use support_conversion to select paddle or torch weight.
|
||||
file_name = PYTORCH_WEIGHTS_NAME if support_conversion else PADDLE_WEIGHTS_NAME
|
||||
file_name = PYTORCH_WEIGHTS_NAME if support_conversion else PADDLE_WEIGHTS_NAME
|
||||
|
||||
file_name_list = [SAFE_WEIGHTS_NAME] + [file_name] + [PYTORCH_WEIGHTS_INDEX_NAME] + [SAFE_WEIGHTS_INDEX_NAME]
|
||||
resolved_file = None
|
||||
@@ -935,6 +917,18 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
):
|
||||
self.init_weights()
|
||||
|
||||
# Note:
|
||||
# 1. PipelineLayer will create parameters for each layer and
|
||||
# call `_synchronize_shared_weights()` to synchronize the shared parameters.
|
||||
# 2. When setting the model `state_dict`, `_synchronize_shared_weights` will be called to
|
||||
# synchronize the shared parameters.
|
||||
# However, `self._init_weights` will re-initialize the parameters without
|
||||
# synchronizing the shared parameters. If the following step does not load a checkpoint,
|
||||
# the shared parameters will be different.
|
||||
|
||||
if isinstance(self, PipelineLayer):
|
||||
self._synchronize_shared_weights()
|
||||
|
||||
def _init_weights(self, layer):
|
||||
"""
|
||||
Initialize the weights. This method should be overridden by derived class.
|
||||
@@ -1744,9 +1738,15 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
loaded_keys, quantization_linear_list, config.quantization_config
|
||||
)
|
||||
if keep_in_fp32_modules is None:
|
||||
keep_in_fp32_modules = ["quant_scale"]
|
||||
keep_in_fp32_modules = (
|
||||
["quant_scale"] if config.quantization_config.weight_quantize_algo in ["nf4", "fp4"] else None
|
||||
)
|
||||
else:
|
||||
keep_in_fp32_modules += ["quant_scale"]
|
||||
keep_in_fp32_modules = (
|
||||
keep_in_fp32_modules + ["quant_scale"]
|
||||
if config.quantization_config.weight_quantize_algo in ["nf4", "fp4"]
|
||||
else keep_in_fp32_modules
|
||||
)
|
||||
|
||||
missing_keys = list(set(expected_keys) - set(loaded_keys))
|
||||
unexpected_keys = list(set(loaded_keys) - set(expected_keys))
|
||||
@@ -1929,15 +1929,23 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
raise RuntimeError(f"Error(s) in loading state_dict for {model.__class__.__name__}:\n\t{error_msg}")
|
||||
|
||||
if len(unexpected_keys) > 0:
|
||||
logger.warning(
|
||||
f"Some weights of the model checkpoint at {pretrained_model_name_or_path} were not used when"
|
||||
f" initializing {model.__class__.__name__}: {sorted(unexpected_keys)}\n- This IS expected if you are"
|
||||
f" initializing {model.__class__.__name__} from the checkpoint of a model trained on another task or"
|
||||
" with another architecture (e.g. initializing a BertForSequenceClassification model from a"
|
||||
" BertForPreTraining model).\n- This IS NOT expected if you are initializing"
|
||||
f" {model.__class__.__name__} from the checkpoint of a model that you expect to be exactly identical"
|
||||
" (initializing a BertForSequenceClassification model from a BertForSequenceClassification model)."
|
||||
)
|
||||
if logger.logger.level < 20:
|
||||
logger.warning(
|
||||
f"Some weights of the model checkpoint at {pretrained_model_name_or_path} were not used when"
|
||||
f" initializing {model.__class__.__name__}: {sorted(unexpected_keys)}\n- This IS expected if you are"
|
||||
f" initializing {model.__class__.__name__} from the checkpoint of a model trained on another task or"
|
||||
" with another architecture (e.g. initializing a BertForSequenceClassification model from a"
|
||||
" BertForPreTraining model).\n- This IS NOT expected if you are initializing"
|
||||
f" {model.__class__.__name__} from the checkpoint of a model that you expect to be exactly identical"
|
||||
" (initializing a BertForSequenceClassification model from a BertForSequenceClassification model)."
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"Some weights of the model checkpoint at {pretrained_model_name_or_path} were not used when"
|
||||
f" initializing the model, - This IS expected if you are"
|
||||
f" initializing the model from a checkpoint of a model trained on another task or"
|
||||
" with another architecture."
|
||||
)
|
||||
else:
|
||||
logger.info(f"All model checkpoint weights were used when initializing {model.__class__.__name__}.\n")
|
||||
|
||||
@@ -2135,12 +2143,31 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
or resolved_archive_file.endswith(SAFE_WEIGHTS_NAME)
|
||||
or resolved_archive_file.endswith(SAFE_WEIGHTS_INDEX_NAME)
|
||||
):
|
||||
# try to get the name-mapping info
|
||||
logger.info(
|
||||
f"Starting to convert pytorch weight file<{resolved_archive_file}> to "
|
||||
f"paddle weight file<{os.path.join(cache_dir, PADDLE_WEIGHTS_NAME)}> ..."
|
||||
converted_paddle_weights = os.path.join(
|
||||
os.path.dirname(resolved_archive_file), PADDLE_WEIGHTS_NAME
|
||||
)
|
||||
state_dict = cls.convert(resolved_archive_file, config, cache_dir)
|
||||
if not os.path.exists(converted_paddle_weights):
|
||||
# try to get the name-mapping info
|
||||
logger.info(
|
||||
f"Starting to convert pytorch weight file <{resolved_archive_file}> to "
|
||||
f"paddle weight file <{converted_paddle_weights}> ..."
|
||||
)
|
||||
state_dict = cls.convert(resolved_archive_file, config, os.path.dirname(resolved_archive_file))
|
||||
else:
|
||||
# try to load the converted paddle weight file
|
||||
resolved_archive_file = converted_paddle_weights
|
||||
sharded_metadata = None
|
||||
is_sharded = False
|
||||
logger.info(
|
||||
f"Detect the converted Paddle weight file <{converted_paddle_weights}>. We intend to reuse this file."
|
||||
)
|
||||
if config.tensor_parallel_degree > 1 and resolved_archive_file.endswith(
|
||||
"model_state.pdparams"
|
||||
):
|
||||
state_dict = cls.convert_tensor_parallel(resolved_archive_file, config)
|
||||
else:
|
||||
state_dict = load_state_dict(resolved_archive_file)
|
||||
logger.info("Loaded weights file from disk, setting weights to model.")
|
||||
else:
|
||||
raise ValueError(f"Unexpected file: {resolved_archive_file} for weight conversion.")
|
||||
else:
|
||||
@@ -2158,7 +2185,9 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
logger.info("Loaded weights file from disk, setting weights to model.")
|
||||
|
||||
# Check if `_keep_in_fp32_modules` is not None
|
||||
use_keep_in_fp32_modules = (cls._keep_in_fp32_modules is not None) and dtype == "float16"
|
||||
use_keep_in_fp32_modules = (cls._keep_in_fp32_modules is not None) and (
|
||||
dtype == "float16" or dtype == "bfloat16"
|
||||
)
|
||||
|
||||
if is_sharded:
|
||||
loaded_state_dict_keys = sharded_metadata["all_checkpoint_keys"]
|
||||
@@ -2193,6 +2222,10 @@ class PretrainedModel(Layer, GenerationMixin, ConversionMixin):
|
||||
quantization_config=config.quantization_config,
|
||||
llm_int8_threshold=config.quantization_config.llm_int8_threshold,
|
||||
)
|
||||
quantization_linear_list = []
|
||||
for key in model.state_dict().keys():
|
||||
if "quant_weight" in key:
|
||||
quantization_linear_list.append(key[:-13])
|
||||
|
||||
model, missing_keys, unexpected_keys, mismatched_keys = cls._load_pretrained_model(
|
||||
model=model,
|
||||
|
||||
@@ -587,7 +587,7 @@ def cached_file_for_hf_hub(
|
||||
download_check(path_or_repo_id, full_filename, addition="from_hf_hub")
|
||||
resolved_file = hf_hub_download(
|
||||
repo_id=path_or_repo_id,
|
||||
filename=full_filename,
|
||||
filename=filename,
|
||||
cache_dir=cache_dir,
|
||||
subfolder=subfolder,
|
||||
library_name="PaddleNLP",
|
||||
|
||||
Reference in New Issue
Block a user