From b2b772a9427c457754fb370143464e4deee9c66f Mon Sep 17 00:00:00 2001 From: glide-the Date: Wed, 11 Sep 2024 16:24:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BA=86=E4=BB=8ESAT?= =?UTF-8?q?=E6=9D=83=E9=87=8D=E6=96=87=E4=BB=B6=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E7=9A=84lora=E6=9D=83=E9=87=8D=EF=BC=8C=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=9C=A8CogVideoX=E4=BB=93=E5=BA=93=20tools/export=5Fsat=5Flor?= =?UTF-8?q?a=5Fweight.py=20=E5=8A=A0=E8=BD=BD=E5=90=8E=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20load=5Fcogvideox=5Flora.py=20=E6=8E=A8=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/hf_lora_weights.png | Bin 0 -> 61412 bytes sat/README.md | 28 ++++++++- sat/README_ja.md | 32 +++++++++- sat/README_zh.md | 28 ++++++++- tools/export_sat_lora_weight.py | 83 +++++++++++++++++++++++++ tools/load_cogvideox_lora.py | 107 ++++++++++++++++++++++++++++++++ 6 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 resources/hf_lora_weights.png create mode 100644 tools/export_sat_lora_weight.py create mode 100644 tools/load_cogvideox_lora.py diff --git a/resources/hf_lora_weights.png b/resources/hf_lora_weights.png new file mode 100644 index 0000000000000000000000000000000000000000..cdf13cc50ac22329393923784ded6a5a72a57fe4 GIT binary patch literal 61412 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 H_Tm2l!7EI1 literal 0 HcmV?d00001 diff --git a/sat/README.md b/sat/README.md index df49e30..c07568f 100644 --- a/sat/README.md +++ b/sat/README.md @@ -406,4 +406,30 @@ The SAT weight format is different from Huggingface's weight format and needs to python ../tools/convert_weight_sat2hf.py ``` -**Note**: This content has not yet been tested with LORA fine-tuning models. \ No newline at end of file +### Exporting Huggingface Diffusers lora LoRA Weights from SAT Checkpoints + +After completing the training using the above steps, we get a SAT checkpoint with LoRA weights. You can find the file at `{args.save}/1000/1000/mp_rank_00_model_states.pt`. + +The script for exporting LoRA weights can be found in the CogVideoX repository at `tools/export_sat_lora_weight.py`. After exporting, you can use `load_cogvideox_lora.py` for inference. + +#### Export command: +```bash +python tools/export_sat_lora_weight.py --sat_pt_path {args.save}/{experiment_name}-09-09-21-10/1000/mp_rank_00_model_states.pt --lora_save_directory {args.save}/export_hf_lora_weights_1/ +``` + +This training mainly modified the following model structures. The table below lists the corresponding structure mappings for converting to the HF (Hugging Face) format LoRA structure. As you can see, LoRA adds a low-rank weight to the model's attention structure. + +``` + + 'attention.query_key_value.matrix_A.0': 'attn1.to_q.lora_A.weight', + 'attention.query_key_value.matrix_A.1': 'attn1.to_k.lora_A.weight', + 'attention.query_key_value.matrix_A.2': 'attn1.to_v.lora_A.weight', + 'attention.query_key_value.matrix_B.0': 'attn1.to_q.lora_B.weight', + 'attention.query_key_value.matrix_B.1': 'attn1.to_k.lora_B.weight', + 'attention.query_key_value.matrix_B.2': 'attn1.to_v.lora_B.weight', + 'attention.dense.matrix_A.0': 'attn1.to_out.0.lora_A.weight', + 'attention.dense.matrix_B.0': 'attn1.to_out.0.lora_B.weight' +``` + +Using export_sat_lora_weight.py, you can convert the SAT checkpoint into the HF LoRA format. +![alt text](../resources/hf_lora_weights.png) diff --git a/sat/README_ja.md b/sat/README_ja.md index 0e2ce34..af48b9c 100644 --- a/sat/README_ja.md +++ b/sat/README_ja.md @@ -411,4 +411,34 @@ SAT ウェイト形式は Huggingface のウェイト形式と異なり、変換 python ../tools/convert_weight_sat2hf.py ``` -**注意**:この内容は LORA ファインチューニングモデルではまだテストされていません。 +### SATチェックポイントからHuggingface Diffusers lora LoRAウェイトをエクスポート + +上記のステップを完了すると、LoRAウェイト付きのSATチェックポイントが得られます。ファイルは `{args.save}/1000/1000/mp_rank_00_model_states.pt` にあります。 + +LoRAウェイトをエクスポートするためのスクリプトは、CogVideoXリポジトリの `tools/export_sat_lora_weight.py` にあります。エクスポート後、`load_cogvideox_lora.py` を使用して推論を行うことができます。 + +#### エクスポートコマンド: +```bash +python tools/export_sat_lora_weight.py --sat_pt_path {args.save}/{experiment_name}-09-09-21-10/1000/mp_rank_00_model_states.pt --lora_save_directory {args.save}/export_hf_lora_weights_1/ +``` + +このトレーニングでは主に以下のモデル構造が変更されました。以下の表は、HF (Hugging Face) 形式のLoRA構造に変換する際の対応関係を示しています。ご覧の通り、LoRAはモデルの注意メカニズムに低ランクの重みを追加しています。 + + + +``` + + 'attention.query_key_value.matrix_A.0': 'attn1.to_q.lora_A.weight', + 'attention.query_key_value.matrix_A.1': 'attn1.to_k.lora_A.weight', + 'attention.query_key_value.matrix_A.2': 'attn1.to_v.lora_A.weight', + 'attention.query_key_value.matrix_B.0': 'attn1.to_q.lora_B.weight', + 'attention.query_key_value.matrix_B.1': 'attn1.to_k.lora_B.weight', + 'attention.query_key_value.matrix_B.2': 'attn1.to_v.lora_B.weight', + 'attention.dense.matrix_A.0': 'attn1.to_out.0.lora_A.weight', + 'attention.dense.matrix_B.0': 'attn1.to_out.0.lora_B.weight' +``` + +export_sat_lora_weight.py を使用して、SATチェックポイントをHF LoRA形式に変換できます。 + + +![alt text](../resources/hf_lora_weights.png) diff --git a/sat/README_zh.md b/sat/README_zh.md index a5df855..c6010e3 100644 --- a/sat/README_zh.md +++ b/sat/README_zh.md @@ -404,4 +404,30 @@ SAT 权重格式与 Huggingface 的权重格式不同,需要转换。请运行 python ../tools/convert_weight_sat2hf.py ``` -**注意** 本内容暂未测试 LORA 微调模型。 \ No newline at end of file +### 从SAT权重文件 导出Huggingface Diffusers lora权重 + +支持了从SAT权重文件 +在经过上面这些步骤训练之后,我们得到了一个sat带lora的权重,在{args.save}/1000/1000/mp_rank_00_model_states.pt你可以看到这个文件 + +导出的lora权重脚本在CogVideoX仓库 tools/export_sat_lora_weight.py ,导出后使用 load_cogvideox_lora.py 推理 +- 导出命令 +``` +python tools/export_sat_lora_weight.py --sat_pt_path {args.save}/{experiment_name}-09-09-21-10/1000/mp_rank_00_model_states.pt --lora_save_directory {args.save}/export_hf_lora_weights_1/ +··· + +这次训练主要修改了下面几个模型结构,下面列出了 转换为HF格式的lora结构对应关系,可以看到lora将模型注意力结构上增加一个低秩权重, + +``` + + 'attention.query_key_value.matrix_A.0': 'attn1.to_q.lora_A.weight', + 'attention.query_key_value.matrix_A.1': 'attn1.to_k.lora_A.weight', + 'attention.query_key_value.matrix_A.2': 'attn1.to_v.lora_A.weight', + 'attention.query_key_value.matrix_B.0': 'attn1.to_q.lora_B.weight', + 'attention.query_key_value.matrix_B.1': 'attn1.to_k.lora_B.weight', + 'attention.query_key_value.matrix_B.2': 'attn1.to_v.lora_B.weight', + 'attention.dense.matrix_A.0': 'attn1.to_out.0.lora_A.weight', + 'attention.dense.matrix_B.0': 'attn1.to_out.0.lora_B.weight' +``` + +通过export_sat_lora_weight.py将它转换为HF格式的lora结构 +![alt text](../resources/hf_lora_weights.png) diff --git a/tools/export_sat_lora_weight.py b/tools/export_sat_lora_weight.py new file mode 100644 index 0000000..9340d8f --- /dev/null +++ b/tools/export_sat_lora_weight.py @@ -0,0 +1,83 @@ +from typing import Any, Dict +import torch +import argparse +from diffusers.loaders.lora_base import LoraBaseMixin +from diffusers.models.modeling_utils import load_state_dict + + +def get_state_dict(saved_dict: Dict[str, Any]) -> Dict[str, Any]: + state_dict = saved_dict + if "model" in saved_dict.keys(): + state_dict = state_dict["model"] + if "module" in saved_dict.keys(): + state_dict = state_dict["module"] + if "state_dict" in saved_dict.keys(): + state_dict = state_dict["state_dict"] + return state_dict + +LORA_KEYS_RENAME = { + + 'attention.query_key_value.matrix_A.0': 'attn1.to_q.lora_A.weight', + 'attention.query_key_value.matrix_A.1': 'attn1.to_k.lora_A.weight', + 'attention.query_key_value.matrix_A.2': 'attn1.to_v.lora_A.weight', + 'attention.query_key_value.matrix_B.0': 'attn1.to_q.lora_B.weight', + 'attention.query_key_value.matrix_B.1': 'attn1.to_k.lora_B.weight', + 'attention.query_key_value.matrix_B.2': 'attn1.to_v.lora_B.weight', + 'attention.dense.matrix_A.0': 'attn1.to_out.0.lora_A.weight', + 'attention.dense.matrix_B.0': 'attn1.to_out.0.lora_B.weight' +} + + + +PREFIX_KEY = "model.diffusion_model." +SAT_UNIT_KEY = "layers" +LORA_PREFIX_KEY = "transformer_blocks" + + + +def export_lora_weight(ckpt_path,lora_save_directory): + + merge_original_state_dict = get_state_dict(torch.load(ckpt_path, map_location="cpu", mmap=True)) + + + lora_state_dict = {} + for key in list(merge_original_state_dict.keys()): + new_key = key[len(PREFIX_KEY) :] + for special_key, lora_keys in LORA_KEYS_RENAME.items(): + if new_key.endswith(special_key): + new_key = new_key.replace(special_key, lora_keys) + new_key = new_key.replace(SAT_UNIT_KEY, LORA_PREFIX_KEY) + + lora_state_dict[new_key] = merge_original_state_dict[key] + + + + # final length should be 240 + if len(lora_state_dict) != 240: + raise ValueError("lora_state_dict length is not 240") + + lora_state_dict.keys() + + LoraBaseMixin.write_lora_layers( + state_dict=lora_state_dict, + save_directory=lora_save_directory, + is_main_process=True, + weight_name=None, + save_function=None, + safe_serialization=True + ) + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--sat_pt_path", type=str, required=True, help="Path to original sat transformer checkpoint" + ) + parser.add_argument("--lora_save_directory", type=str, required=True, help="Path where converted lora should be saved") + return parser.parse_args() + + +if __name__ == "__main__": + args = get_args() + + export_lora_weight(args.sat_pt_path, args.lora_save_directory) diff --git a/tools/load_cogvideox_lora.py b/tools/load_cogvideox_lora.py new file mode 100644 index 0000000..449320a --- /dev/null +++ b/tools/load_cogvideox_lora.py @@ -0,0 +1,107 @@ +# Copyright 2024 The HuggingFace Team. +# 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 math +import random +import time +from diffusers.utils import export_to_video +from diffusers.image_processor import VaeImageProcessor +from datetime import datetime, timedelta +from diffusers import CogVideoXPipeline, CogVideoXDDIMScheduler, CogVideoXDPMScheduler +import os +import torch +import argparse + + +device = "cuda" if torch.cuda.is_available() else "cpu" + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--pretrained_model_name_or_path", + type=str, + default=None, + required=True, + help="Path to pretrained model or model identifier from huggingface.co/models.", + ) + parser.add_argument( + "--lora_weights_path", + type=str, + default=None, + required=True, + help="Path to lora weights.", + ) + parser.add_argument( + "--lora_r", + type=int, + default=128, + help="""LoRA weights have a rank parameter, with the default for 2B trans set at 128 and 5B trans set at 256. + This part is used to calculate the value for lora_scale, which is by default divided by the alpha value, + used for stable learning and to prevent underflow. In the SAT training framework, + alpha is set to 1 by default. The higher the rank, the better the expressive capability, + but it requires more memory and training time. Increasing this number blindly isn't always better. + The formula for lora_scale is: lora_r / alpha. + """, + ) + parser.add_argument( + "--output_dir", + type=str, + default="output", + help="The output directory where the model predictions and checkpoints will be written.", + ) + return parser.parse_args() + + +if __name__ == "__main__": + args = get_args() + pipe = CogVideoXPipeline.from_pretrained(args.pretrained_model_name_or_path, torch_dtype=torch.bfloat16).to(device) + pipe.load_lora_weights(args.lora_weights_path, weight_name="pytorch_lora_weights.safetensors", adapter_name="test_1") + pipe.fuse_lora(lora_scale=1/128) + + + pipe.scheduler = CogVideoXDPMScheduler.from_config(pipe.scheduler.config, timestep_spacing="trailing") + + os.makedirs(args.output_dir, exist_ok=True) + prompt="""In the heart of a bustling city, a young woman with long, flowing brown hair and a radiant smile stands out. She's donned in a cozy white beanie adorned with playful animal ears, adding a touch of whimsy to her appearance. Her eyes sparkle with joy as she looks directly into the camera, her expression inviting and warm. The background is a blur of activity, with indistinct figures moving about, suggesting a lively public space. The lighting is soft and diffused, casting a gentle glow on her face and highlighting her features. The overall mood is cheerful and vibrant, capturing a moment of happiness in the midst of urban life. + """ + latents = pipe( + prompt=prompt, + num_videos_per_prompt=1, + num_inference_steps=50, + num_frames=49, + use_dynamic_cfg=True, + output_type="pt", + guidance_scale=3.0, + generator=torch.Generator(device="cpu").manual_seed(42), + ).frames + batch_size = latents.shape[0] + batch_video_frames = [] + for batch_idx in range(batch_size): + pt_image = latents[batch_idx] + pt_image = torch.stack([pt_image[i] for i in range(pt_image.shape[0])]) + + image_np = VaeImageProcessor.pt_to_numpy(pt_image) + image_pil = VaeImageProcessor.numpy_to_pil(image_np) + batch_video_frames.append(image_pil) + + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + video_path = f"{args.output_dir}/{timestamp}.mp4" + os.makedirs(os.path.dirname(video_path), exist_ok=True) + tensor = batch_video_frames[0] + fps=math.ceil((len(batch_video_frames[0]) - 1) / 6) + + export_to_video(tensor, video_path, fps=fps) \ No newline at end of file