File size: 6,307 Bytes
252b3d1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | {
"cells": [
{
"cell_type": "code",
"execution_count": 10,
"id": "c15deb04-94a0-4073-a174-adcd22af10b8",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"The config attributes {'block_out_channels': [128, 128, 256, 512, 512], 'force_upcast': False} were passed to AsymmetricAutoencoderKL, but are not expected and will be ignored. Please verify your config.json configuration file.\n",
"The config attributes {'block_out_channels': [128, 128, 256, 512, 512], 'force_upcast': False} were passed to AsymmetricAutoencoderKL, but are not expected and will be ignored. Please verify your config.json configuration file.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"✅ Создана новая модель: <class 'diffusers.models.autoencoders.autoencoder_asym_kl.AsymmetricAutoencoderKL'>\n",
"\n",
"--- Перенос весов ---\n",
"✅ Готово. Модель сохранена в vae9\n"
]
}
],
"source": [
"from diffusers.models import AsymmetricAutoencoderKL\n",
"import torch\n",
"from tqdm import tqdm\n",
"\n",
"# ---- Конфиг новой модели ----\n",
"config = {\n",
" \"_class_name\": \"AsymmetricAutoencoderKL\",\n",
" \"act_fn\": \"silu\",\n",
" \"in_channels\": 3,\n",
" \"out_channels\": 3,\n",
" \"scaling_factor\": 1.0,\n",
" \"norm_num_groups\": 32,\n",
" \"down_block_out_channels\": [128, 256, 512, 512],\n",
" \"down_block_types\": [\n",
" \"DownEncoderBlock2D\",\n",
" \"DownEncoderBlock2D\",\n",
" \"DownEncoderBlock2D\",\n",
" \"DownEncoderBlock2D\",\n",
" ],\n",
" \"latent_channels\": 16,\n",
" \"up_block_out_channels\": [128,128, 256, 512, 512],\n",
" \"up_block_types\": [\n",
" \"UpDecoderBlock2D\",\n",
" \"UpDecoderBlock2D\",\n",
" \"UpDecoderBlock2D\",\n",
" \"UpDecoderBlock2D\",\n",
" \"UpDecoderBlock2D\",\n",
" ],\n",
"}\n",
"\n",
"# ---- Создание пустой асимметричной модели ----\n",
"vae = AsymmetricAutoencoderKL(\n",
" act_fn=config[\"act_fn\"],\n",
" down_block_out_channels=config[\"down_block_out_channels\"],\n",
" down_block_types=config[\"down_block_types\"],\n",
" latent_channels=config[\"latent_channels\"],\n",
" up_block_out_channels=config[\"up_block_out_channels\"],\n",
" up_block_types=config[\"up_block_types\"],\n",
" in_channels=config[\"in_channels\"],\n",
" out_channels=config[\"out_channels\"],\n",
" scaling_factor=config[\"scaling_factor\"],\n",
" norm_num_groups=config[\"norm_num_groups\"],\n",
" layers_per_down_block=2,\n",
" layers_per_up_block=3,\n",
" sample_size=256\n",
")\n",
"\n",
"vae.save_pretrained(\"asymmetric_vae_empty\")\n",
"print(\"✅ Создана новая модель:\", type(vae))\n",
"\n",
"def transfer_weights(old_path, new_path, save_path=\"vae_final\", device=\"cuda\", dtype=torch.float32):\n",
" old_vae = AsymmetricAutoencoderKL.from_pretrained(old_path).to(device, dtype=dtype)\n",
" new_vae = AsymmetricAutoencoderKL.from_pretrained(new_path).to(device, dtype=dtype)\n",
"\n",
" old_sd = old_vae.state_dict()\n",
" new_sd = new_vae.state_dict()\n",
"\n",
" print(\"\\n--- Перенос весов ---\")\n",
" \n",
" # 1. Переносим всё, что совпадает по именам и формам (Энкодер, конволоции и т.д.)\n",
" # Это покроет Encoder полностью, так как там down_blocks не менялись\n",
" for k, v in old_sd.items():\n",
" if k in new_sd and v.shape == new_sd[k].shape:\n",
" new_sd[k] = v.clone()\n",
"\n",
" # 2. Переносим блоки декодера (Up-blocks)\n",
" # Старый: [0, 1, 2, 3, 4] -> Новой: [0, 1, 2, 3]\n",
" # Нам нужно перенести глубокие слои (0, 1, 2), а последний 3-й взять из 4-го старого\n",
" \n",
" # Сопоставление индексов: старый блок -> новый блок\n",
" # Мы берем 0->0, 1->1, 2->2 и 4->3 (пропуская лишний блок 128->128)\n",
" mapping = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} \n",
" \n",
" for old_idx, new_idx in mapping.items():\n",
" old_prefix = f\"decoder.up_blocks.{old_idx}.\"\n",
" new_prefix = f\"decoder.up_blocks.{new_idx}.\"\n",
" \n",
" for k, v in old_sd.items():\n",
" if k.startswith(old_prefix):\n",
" new_key = k.replace(old_prefix, new_prefix)\n",
" if new_key in new_sd and v.shape == new_sd[new_key].shape:\n",
" new_sd[new_key] = v.clone()\n",
" else:\n",
" print(f\"⚠️ Пропущен слой или не совпал размер: {new_key}\")\n",
"\n",
" # Загрузка\n",
" new_vae.load_state_dict(new_sd, strict=False)\n",
" new_vae.save_pretrained(save_path)\n",
" print(f\"✅ Готово. Модель сохранена в {save_path}\")\n",
"\n",
"# Запуск\n",
"transfer_weights(\"vae8\", \"asymmetric_vae_empty\", save_path=\"vae9\")\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "59fcafb9-6d89-49b4-8362-b4891f591687",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
|