File size: 2,603 Bytes
1836a26 | 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 | import torch
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
# 1. 路径定义
BASE_MODEL_PATH = "./Qwen3-4B-Thinking-2507"
LORA_PATH = "./Qwen3-4B-Thinking-2507_FTtrained_lora"
OUTPUT_PRUNED_PATH = "./QiMing-Polaris-Qwen3-4B-HardPruned"
# 2. 定义需要剪掉的层(根据你的 Audit 数据,L-29 到 L-32 发生了剧烈塌缩)
LAYERS_TO_REMOVE = [29, 30, 31, 32]
print("🚀 阶段 1/4: 正在加载基础模型与分词器...")
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_PATH, trust_remote_code=True)
base_model = AutoModelForCausalLM.from_pretrained(
BASE_MODEL_PATH,
dtype=torch.bfloat16, # 避免 deprecated 警告
device_map="cpu", # 融合与剪枝在 CPU 内存上进行,防止显存溢出
trust_remote_code=True,
)
print("🔗 阶段 2/4: 加载并融合 LoRA 适配器...")
lora_model = PeftModel.from_pretrained(base_model, LORA_PATH)
merged_model = lora_model.merge_and_unload()
print("✅ LoRA 权重融合成功!")
print("✂️ 阶段 3/4: 正在执行硬剪枝 (Hard Pruning)...")
original_layers_count = len(merged_model.model.layers)
print(f"原模型总层数: {original_layers_count} 层")
# 计算需要保留的层索引
keep_indices = [i for i in range(original_layers_count) if i not in LAYERS_TO_REMOVE]
print(f"准备移除的层: {LAYERS_TO_REMOVE}")
print(f"保留的层索引数量: {len(keep_indices)} 层")
# 1. 物理切割:重构 layers 的 ModuleList
pruned_layers = torch.nn.ModuleList(
[merged_model.model.layers[i] for i in keep_indices]
)
merged_model.model.layers = pruned_layers
# 2. 【核心修复】同步更新 config 中的所有层数及 layer_types 列表
configs_to_update = [merged_model.config]
if (
hasattr(merged_model.config, "text_config")
and merged_model.config.text_config is not None
):
configs_to_update.append(merged_model.config.text_config)
for cfg in configs_to_update:
cfg.num_hidden_layers = len(keep_indices)
# 切割 layer_types 列表以匹配新的层数
if hasattr(cfg, "layer_types") and cfg.layer_types is not None:
cfg.layer_types = [cfg.layer_types[i] for i in keep_indices]
print(f"剪枝完成!新模型总层数: {len(merged_model.model.layers)} 层")
print(f"💾 阶段 4/4: 正在保存硬剪枝后的全新模型至 {OUTPUT_PRUNED_PATH}...")
os.makedirs(OUTPUT_PRUNED_PATH, exist_ok=True)
merged_model.save_pretrained(OUTPUT_PRUNED_PATH, safe_serialization=True)
tokenizer.save_pretrained(OUTPUT_PRUNED_PATH)
print("🎉 恭喜!硬剪枝独立模型已成功保存导出!")
|