declare-lab/tango2
92
1# coding=utf-82# Copyright 2023 The HuggingFace Inc. team.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15""" PyTorch - Flax general utilities."""16import re17 18import jax.numpy as jnp19from flax.traverse_util import flatten_dict, unflatten_dict20from jax.random import PRNGKey21 22from ..utils import logging23 24 25logger = logging.get_logger(__name__)26 27 28def rename_key(key):29 regex = r"\w+[.]\d+"30 pats = re.findall(regex, key)31 for pat in pats:32 key = key.replace(pat, "_".join(pat.split(".")))33 return key34 35 36#####################37# PyTorch => Flax #38#####################39 40 41# Adapted from https://github.com/huggingface/transformers/blob/c603c80f46881ae18b2ca50770ef65fa4033eacd/src/transformers/modeling_flax_pytorch_utils.py#L6942# and https://github.com/patil-suraj/stable-diffusion-jax/blob/main/stable_diffusion_jax/convert_diffusers_to_jax.py43def rename_key_and_reshape_tensor(pt_tuple_key, pt_tensor, random_flax_state_dict):44 """Rename PT weight names to corresponding Flax weight names and reshape tensor if necessary"""45 46 # conv norm or layer norm47 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("scale",)48 if (49 any("norm" in str_ for str_ in pt_tuple_key)50 and (pt_tuple_key[-1] == "bias")51 and (pt_tuple_key[:-1] + ("bias",) not in random_flax_state_dict)52 and (pt_tuple_key[:-1] + ("scale",) in random_flax_state_dict)53 ):54 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("scale",)55 return renamed_pt_tuple_key, pt_tensor56 elif pt_tuple_key[-1] in ["weight", "gamma"] and pt_tuple_key[:-1] + ("scale",) in random_flax_state_dict:57 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("scale",)58 return renamed_pt_tuple_key, pt_tensor59 60 # embedding61 if pt_tuple_key[-1] == "weight" and pt_tuple_key[:-1] + ("embedding",) in random_flax_state_dict:62 pt_tuple_key = pt_tuple_key[:-1] + ("embedding",)63 return renamed_pt_tuple_key, pt_tensor64 65 # conv layer66 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("kernel",)67 if pt_tuple_key[-1] == "weight" and pt_tensor.ndim == 4:68 pt_tensor = pt_tensor.transpose(2, 3, 1, 0)69 return renamed_pt_tuple_key, pt_tensor70 71 # linear layer72 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("kernel",)73 if pt_tuple_key[-1] == "weight":74 pt_tensor = pt_tensor.T75 return renamed_pt_tuple_key, pt_tensor76 77 # old PyTorch layer norm weight78 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("weight",)79 if pt_tuple_key[-1] == "gamma":80 return renamed_pt_tuple_key, pt_tensor81 82 # old PyTorch layer norm bias83 renamed_pt_tuple_key = pt_tuple_key[:-1] + ("bias",)84 if pt_tuple_key[-1] == "beta":85 return renamed_pt_tuple_key, pt_tensor86 87 return pt_tuple_key, pt_tensor88 89 90def convert_pytorch_state_dict_to_flax(pt_state_dict, flax_model, init_key=42):91 # Step 1: Convert pytorch tensor to numpy92 pt_state_dict = {k: v.numpy() for k, v in pt_state_dict.items()}93 94 # Step 2: Since the model is stateless, get random Flax params95 random_flax_params = flax_model.init_weights(PRNGKey(init_key))96 97 random_flax_state_dict = flatten_dict(random_flax_params)98 flax_state_dict = {}99 100 # Need to change some parameters name to match Flax names101 for pt_key, pt_tensor in pt_state_dict.items():102 renamed_pt_key = rename_key(pt_key)103 pt_tuple_key = tuple(renamed_pt_key.split("."))104 105 # Correctly rename weight parameters106 flax_key, flax_tensor = rename_key_and_reshape_tensor(pt_tuple_key, pt_tensor, random_flax_state_dict)107 108 if flax_key in random_flax_state_dict:109 if flax_tensor.shape != random_flax_state_dict[flax_key].shape:110 raise ValueError(111 f"PyTorch checkpoint seems to be incorrect. Weight {pt_key} was expected to be of shape "112 f"{random_flax_state_dict[flax_key].shape}, but is {flax_tensor.shape}."113 )114 115 # also add unexpected weight so that warning is thrown116 flax_state_dict[flax_key] = jnp.asarray(flax_tensor)117 118 return unflatten_dict(flax_state_dict)119 