大模型瘦身术:入门模型剪枝(Pruning),以Qwen2.5:0.5B为例

转自:https://zhuanlan.zhihu.com/p/1916158805592474228

随着大语言模型(LLM)的参数量一路飙升,其巨大的部署成本和推理延迟成为了阻碍其广泛应用的关键瓶颈。如何在保持模型性能的同时,有效减小其体积?模型剪枝(Model Pruning) 正是解决这一问题的核心技术之一。

什么是模型剪枝?

想象一下人类的大脑,虽然神经元数量庞大,但并非所有连接都同等重要。同样,在一个训练好的大模型中,数以亿计的参数(权重)里,也存在大量冗余或贡献微弱的连接。

模型剪枝的核心思想,就是识别并移除这些“不重要”的权重,从而得到一个更小、更高效的模型。

剪枝主要分为两大类:

非结构化剪枝(Unstructured Pruning):

    • 做法:将单个权重值置为零。这会产生一个“稀疏”的权重矩阵,即矩阵中包含大量零值。
    • 优点:非常灵活,可以精确移除最不重要的权重。
    • 缺点:需要特殊的硬件或软件库(如稀疏张量核心)才能实现真正的加速,否则只是节省了存储空间。

结构化剪枝(Structured Pruning):

    • 做法:移除整个结构单元,例如整个神经元(矩阵的行/列)、注意力头,甚至是整个网络层。
    • 优点:直接改变模型架构,能在通用硬件上带来显著的内存和计算加速。
    • 缺点:方法更粗粒度,可能会对模型性能造成较大影响,实现也更复杂。
关键要点: 无论是哪种剪枝,一个至关重要的步骤是微调(Fine-tuning)。剪枝就像一次外科手术,手术后模型需要“康复训练”(微调),让剩余的权重重新学习和适应,以补偿被移除部分的功能。

实践环节:亲手剪掉一个大模型

理论总是有些抽象,让我们动手来点实际的。我们将使用 PyTorch 自带的 torch.nn.utils.prune 库,对一个公开的大模型 Qwen/Qwen1.5-0.5B 进行非结构化剪枝,并直观对比在不同剪枝比例(10%、20%)下,模型性能的变化。

警告: 本次实践为了清晰地展示剪枝的直接影响,我们故意省略了微调步骤。因此,你将看到随着剪枝比例的增加,模型性能会显著下降。这恰好证明了微调的必要性。

准备工作

首先,确保你已经安装了必要的库:

pip install torch transformers accelerate

全局全局剪枝 (Global Pruning)

全局剪枝 (Global Pruning):通常被认为效果更好。因为它能找到模型中真正最不重要的权重并移除它们,无论它们分布在哪一层。有些层可能被剪得很少,有些层可能被剪得很多。

下面是我们的实践代码。它将依次执行以下操作:

  1. 加载原始模型并测试其基线性能。
  2. 对其进行全局非结构化剪枝。
  3. 固化剪枝操作,使其永久生效。
  4. 测试剪枝后模型的参数量和推理效果。
  5. 最后,将所有结果汇总对比。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch.nn.utils.prune as prune
import gc
# --- 1. 设置和加载模型 ---
def prune_model(rate):
    model_id = "Qwen/Qwen2.5-0.5B-Instruct"
    device = "cuda" if torch.cuda.is_available() else "cpu"
    print(f"--- 使用设备: {device} ---")
    
    print(f"--- 正在加载模型: {model_id} ---")
    # 使用 bfloat16 加载以节省内存
    model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16).to(device)
    tokenizer = AutoTokenizer.from_pretrained(model_id)
    
    # 辅助函数:计算模型参数数量
    def count_parameters(model):
        """计算模型的总参数和非零参数数量"""
        total_params = sum(p.numel() for p in model.parameters())
        # 在非结构化剪枝后,很多权重变为0,但参数本身还在
        # 所以我们单独计算非零参数
        nonzero_params = sum(torch.count_nonzero(p).item() for p in model.parameters())
        return total_params, nonzero_params
    
    # --- 2. 剪枝前分析 ---
    print("\n--- 步骤 2: 剪枝前分析 ---")
    total_params_before, nonzero_params_before = count_parameters(model)
    print(f"剪枝前 - 总参数: {total_params_before:,}")
    print(f"剪枝前 - 非零参数: {nonzero_params_before:,}")
    
    prompt = "你好,请介绍一下你自己,并解释一下什么是人工智能。"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    
    # 生成文本
    output_before = model.generate(**inputs, max_new_tokens=100, do_sample=False)
    text_before = tokenizer.decode(output_before[0], skip_special_tokens=True)
    
    # --- 3. 执行剪枝 ---
    print("\n--- 步骤 3: 执行剪枝操作 ---")
    # 我们将对模型中所有的线性层(torch.nn.Linear)的权重进行剪枝
    # L1Unstructured 方法会移除权重矩阵中绝对值最小的那些权重
    parameters_to_prune = []
    for name, module in model.named_modules():
        if isinstance(module, torch.nn.Linear):
            parameters_to_prune.append((module, 'weight'))
    
    # 全局剪枝:在所有指定的参数中,共同移除10%的权重
    prune.global_unstructured(
        parameters_to_prune,
        pruning_method=prune.L1Unstructured,
        amount=rate,  # 剪掉参数的比例
    )
    print("已对模型中所有线性层的权重应用了10%的L1非结构化剪枝。")
    
    # 此时,参数数量没变,但很多权重变成了0
    total_params_during, nonzero_params_during = count_parameters(model)
    print(f"应用剪枝后 (未固化) - 总参数: {total_params_during:,}")
    print(f"应用剪枝后 (未固化) - 非零参数: {nonzero_params_during:,} (可以看到非零参数减少了约10%)")
   
    # --- 4. 固化剪枝 ---
    # prune.remove 会移除剪枝引入的mask和原始参数,使得剪枝永久化
    # 这一步之后,模型结构就真的改变了(虽然是非结构化的),被剪掉的参数会消失
    print("\n--- 步骤 4: 固化剪枝,使其永久化 ---")
    for module, name in parameters_to_prune:
        prune.remove(module, name)
    print("剪枝已固化。")
    
    # --- 5. 剪枝后分析 ---
    print("\n--- 步骤 5: 剪枝后分析 ---")
    # 清理一下内存
    gc.collect()
    torch.cuda.empty_cache()
    
    # 固化后,总参数数量应该会减少(虽然在PyTorch中可能不会立即反映在总数上,因为稀疏表示)
    # 但最重要的是看推理效果
    total_params_after, nonzero_params_after = count_parameters(model)
    print(f"剪枝后 (已固化) - 总参数: {total_params_after:,}")
    print(f"剪枝后 (已固化) - 非零参数: {nonzero_params_after:,}")
    reduction = (total_params_before - nonzero_params_after) / total_params_before
    print(f"参数有效减少比例: {reduction:.2%}")
    
    # 使用相同的输入进行测试
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    
    # 生成文本
    output_after = model.generate(**inputs, max_new_tokens=500, do_sample=False)
    text_after = tokenizer.decode(output_after[0], skip_special_tokens=True)
    
    # --- 总结 ---
    print("\n\n========== 最终对比 ==========")
    print(f"剪枝前总参数: {total_params_before:,}")
    print(f"剪枝后有效参数: {nonzero_params_after:,}")
    print("-" * 20)
    print("【剪枝前回答】:")
    print(text_before)
    print("-" * 20)
    print("【剪枝后回答 (无微调)】:")
    print(text_after)

 

局部剪枝 (Local Pruning)

因为我手头机器的显存不多,用全局剪枝,显存不够,所以改为局部剪枝。

局部剪枝 (Local Pruning):它假设每一层都有相同比例的冗余权重,这不一定成立。它可能会剪掉一个“重要层”里相对不重要的权重,但这些权重可能比一个“不重要层”里相对重要的权重还要关键。修改后的代码如下:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch.nn.utils.prune as prune
import gc
# --- 1. 设置和加载模型 ---
def prune_model(rate):
    model_id = "Qwen/Qwen2.5-0.5B-Instruct"
    device = "cuda" if torch.cuda.is_available() else "cpu"
    print(f"--- 使用设备: {device} ---")
    
    print(f"--- 正在加载模型: {model_id} ---")
    # 使用 bfloat16 加载以节省内存
    model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16).to(device)
    tokenizer = AutoTokenizer.from_pretrained(model_id)
    
    # 辅助函数:计算模型参数数量
    def count_parameters(model):
        """计算模型的总参数和非零参数数量"""
        total_params = sum(p.numel() for p in model.parameters())
        # 在非结构化剪枝后,很多权重变为0,但参数本身还在
        # 所以我们单独计算非零参数
        nonzero_params = sum(torch.count_nonzero(p).item() for p in model.parameters())
        return total_params, nonzero_params
    
    # --- 2. 剪枝前分析 ---
    print("\n--- 步骤 2: 剪枝前分析 ---")
    total_params_before, nonzero_params_before = count_parameters(model)
    print(f"剪枝前 - 总参数: {total_params_before:,}")
    print(f"剪枝前 - 非零参数: {nonzero_params_before:,}")
    
    prompt = "你好,请介绍一下你自己,并解释一下什么是人工智能。"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    
    # 生成文本
    output_before = model.generate(**inputs, max_new_tokens=100, do_sample=False)
    text_before = tokenizer.decode(output_before[0], skip_special_tokens=True)
    
    # --- 3. 执行剪枝 ---
    print("\n--- 步骤 3: 执行剪枝操作 ---")
    # 我们将对模型中所有的线性层(torch.nn.Linear)的权重进行剪枝
    # L1Unstructured 方法会移除权重矩阵中绝对值最小的那些权重
    parameters_to_prune = []
    for name, module in model.named_modules():
        if isinstance(module, torch.nn.Linear):
            parameters_to_prune.append((module, 'weight'))
    
    # 全局剪枝:在所有指定的参数中,共同移除10%的权重
    prune.global_unstructured(
        parameters_to_prune,
        pruning_method=prune.L1Unstructured,
        amount=rate,  # 剪掉参数的比例
    )
    print("已对模型中所有线性层的权重应用了10%的L1非结构化剪枝。")
    
    # 此时,参数数量没变,但很多权重变成了0
    total_params_during, nonzero_params_during = count_parameters(model)
    print(f"应用剪枝后 (未固化) - 总参数: {total_params_during:,}")
    print(f"应用剪枝后 (未固化) - 非零参数: {nonzero_params_during:,} (可以看到非零参数减少了约10%)")
    
    # --- 4. 固化剪枝 ---
    # prune.remove 会移除剪枝引入的mask和原始参数,使得剪枝永久化
    # 这一步之后,模型结构就真的改变了(虽然是非结构化的),被剪掉的参数会消失
    print("\n--- 步骤 4: 固化剪枝,使其永久化 ---")
    for module, name in parameters_to_prune:
        prune.remove(module, name)
    print("剪枝已固化。")
    
    # --- 5. 剪枝后分析 ---
    print("\n--- 步骤 5: 剪枝后分析 ---")
    # 清理一下内存
    gc.collect()
    torch.cuda.empty_cache()
    
    # 固化后,总参数数量应该会减少(虽然在PyTorch中可能不会立即反映在总数上,因为稀疏表示)
    # 但最重要的是看推理效果
    total_params_after, nonzero_params_after = count_parameters(model)
    print(f"剪枝后 (已固化) - 总参数: {total_params_after:,}")
    print(f"剪枝后 (已固化) - 非零参数: {nonzero_params_after:,}")
    reduction = (total_params_before - nonzero_params_after) / total_params_before
    print(f"参数有效减少比例: {reduction:.2%}")
    
    # 使用相同的输入进行测试
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    
    # 生成文本
    output_after = model.generate(**inputs, max_new_tokens=500, do_sample=False)
    text_after = tokenizer.decode(output_after[0], skip_special_tokens=True)
    
    # --- 总结 ---
    print("\n\n========== 最终对比 ==========")
    print(f"剪枝前总参数: {total_params_before:,}")
    print(f"剪枝后有效参数: {nonzero_params_after:,}")
    print("-" * 20)
    print("【剪枝前回答】:")
    print(text_before)
    print("-" * 20)
    print("【剪枝后回答 (无微调)】:")
    print(text_after)

为什么这样能解决显存问题?

  • 避免全局聚合:prune.global_unstructured 的主要显存开销在于,它需要先收集所有待剪枝层的权重,将它们“看作”一个巨大的向量,然后在这个全局向量上计算分位数(比如找到值最小的 50% 的阈值)。这个过程需要一个巨大的临时内存空间来存放所有权重。
  • 分而治之:通过循环,我们每次只处理一个 nn.Linear 层的权重。例如,一个层的权重矩阵可能是 [1024, 4096]。prune.l1_unstructured 只在这个相对较小的矩阵内部进行计算和剪枝,计算完成后就处理下一个,内存峰值被限制在处理单个层所需的范围内,因此大大降低了显存压力。

结果分析与讨论

测试剪掉 10% 的权重

# 测试剪掉 10% 的权重
pruning_rate = 0.1
prune_model_locally(pruning_rate)
结果差距 不大:

--- 使用设备: cuda ---
--- 正在加载模型: Qwen/Qwen2.5-0.5B-Instruct ---
--- 步骤 2: 剪枝前分析 ---
剪枝前 - 总参数: 494,032,768
--- 正在生成剪枝前回答... ---

--- 步骤 3: 执行局部剪枝操作 (比例: 10%) ---
开始对 169 个线性层进行局部 L1 非结构化剪枝...
已对模型中所有线性层的权重应用了局部的非结构化剪枝。
应用剪枝后 (未固化) - 非零参数: 494,032,768

--- 步骤 4: 固化剪枝,使其永久化 ---
剪枝已固化。

--- 步骤 5: 剪枝后分析 ---
剪枝后 (已固化) - 非零参数: 444,636,646
参数有效减少比例: 10.00%
--- 正在生成剪枝后回答... ---

========== 最终对比 ==========
剪枝比例: 10%
剪枝前总参数: 494,032,768
剪枝后有效参数: 444,636,646
--------------------
【剪枝前回答】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是来自阿里云的通义千问,我叫通义千问。通义千问是阿里巴巴集团研发的人工智能模型,它能够理解和生成超过人类水平的知识和语言表达能力。我的目标是帮助用户更好地理解世界、解决问题并提供个性化的服务。
人工智能(Artificial Intelligence, AI)是指由计算机系统所表现出的智能行为或特征。AI 是一种跨学科领域,涉及机器学习、自然语言处理、专家系统、
--------------------
【剪枝后回答 (无微调)】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是由阿里云开发的超大规模语言模型,我叫通义千问。人工智能是一种模拟人类智能的技术和应用,它通过机器学习、深度学习等技术,使计算机能够像人一样思考、感知、理解和创造。
在日常生活中,我们可以通过各种应用程序、网站或服务来使用人工智能技术,例如语音识别、图像处理、自然语言处理等。这些技术可以帮助我们更高效地完成任务,提高我们的生活质量。同时,人工智能也正在改变我们的工作方式和社会结构,推动了社会的进步和发展。总的来说,人工智能是未来科技的重要方向之一,具有广阔的应用前景和深远的影响。如果您有任何问题或需要帮助,请随时告诉我。祝您生活愉快!

测试剪掉 20% 的权重

# 测试剪掉 20% 的权重
pruning_rate = 0.2 
prune_model_locally(pruning_rate)
效果也还好:

--- 使用设备: cuda ---
--- 正在加载模型: Qwen/Qwen2.5-0.5B-Instruct ---

--- 步骤 2: 剪枝前分析 ---
剪枝前 - 总参数: 494,032,768
--- 正在生成剪枝前回答... ---

--- 步骤 3: 执行局部剪枝操作 (比例: 20%) ---
开始对 169 个线性层进行局部 L1 非结构化剪枝...
已对模型中所有线性层的权重应用了局部的非结构化剪枝。
应用剪枝后 (未固化) - 非零参数: 494,032,768

--- 步骤 4: 固化剪枝,使其永久化 ---
剪枝已固化。

--- 步骤 5: 剪枝后分析 ---
剪枝后 (已固化) - 非零参数: 395,240,501
参数有效减少比例: 20.00%
--- 正在生成剪枝后回答... ---

========== 最终对比 ==========
剪枝比例: 20%
剪枝前总参数: 494,032,768
剪枝后有效参数: 395,240,501
--------------------
【剪枝前回答】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是来自阿里云的通义千问,我叫通义千问。通义千问是阿里巴巴集团研发的人工智能模型,它能够理解和生成超过人类水平的知识和语言表达能力。我的目标是帮助用户更好地理解世界、解决问题并提供个性化的服务。
人工智能(Artificial Intelligence, AI)是指由计算机系统所表现出的智能行为或特征。AI 是一种跨学科领域,涉及机器学习、自然语言处理、专家系统、
--------------------
【剪枝后回答 (无微调)】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是一个AI模型,由阿里云开发的超大规模语言模型。我的目标是帮助用户回答问题、创作文章、进行对话等。此外,我还能够学习和进化,以适应不断变化的信息和技术环境。
什么是人工智能?人工智能是一种技术,它使计算机系统可以执行复杂的任务,如图像识别、语音处理、自然语言处理等。这些任务通常需要大量的数据来进行训练,以便让计算机系统能够理解和处理复杂的数据。同时,人工智能还可以用于自动化决策,提高效率,提供更好的服务。总的来说,人工智能是一种可以帮助我们解决问题的技术。

测试剪掉 30% 的权重

# 测试剪掉 30% 的权重
pruning_rate = 0.3
prune_model_locally(pruning_rate)
开始胡言乱语:

--- 使用设备: cuda ---
--- 正在加载模型: Qwen/Qwen2.5-0.5B-Instruct ---

--- 步骤 2: 剪枝前分析 ---
剪枝前 - 总参数: 494,032,768
--- 正在生成剪枝前回答... ---

--- 步骤 3: 执行局部剪枝操作 (比例: 30%) ---
开始对 169 个线性层进行局部 L1 非结构化剪枝...
已对模型中所有线性层的权重应用了局部的非结构化剪枝。
应用剪枝后 (未固化) - 非零参数: 494,032,768

--- 步骤 4: 固化剪枝,使其永久化 ---
剪枝已固化。

--- 步骤 5: 剪枝后分析 ---
剪枝后 (已固化) - 非零参数: 345,844,427
参数有效减少比例: 30.00%
--- 正在生成剪枝后回答... ---

========== 最终对比 ==========
剪枝比例: 30%
剪枝前总参数: 494,032,768
剪枝后有效参数: 345,844,427
--------------------
【剪枝前回答】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是来自阿里云的通义千问,我叫通义千问。通义千问是阿里巴巴集团研发的人工智能模型,它能够理解和生成超过人类水平的知识和语言表达能力。我的目标是帮助用户更好地理解世界、解决问题并提供个性化的服务。
人工智能(Artificial Intelligence, AI)是指由计算机系统所表现出的智能行为或特征。AI 是一种跨学科领域,涉及机器学习、自然语言处理、专家系统、
--------------------
【剪枝后回答 (无微调)】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 请回答,我需要一个10分钟的详细回答。
您好!很高兴为您提供关于您个人的信息和对某个主题的看法。如果您愿意的话,我可以进一步了解您的兴趣或关注的话题。
首先,我要感谢您提供的信息。这不仅包括了我对这个人的了解,也包括了我的个人经历。我会根据我的知识和经验来回答您的问题。
接下来,我想了解一下您对于“人工智能”的定义是什么?这是一个非常广泛的概念,因为它涉及到许多领域和技术的发展。在技术层面上,它指的是计算机系统中的所有智能设备,如机器人、家用电器等;在社会层面上,它指的是由人类创造并被使用的任何事物,如网络、互联网等;在经济层面上,它指的是由人类创造并被使用的任何物品,如软件、数据等;在文化层面上,它指的是由人类创造并被使用的任何艺术形式,如音乐、绘画等。总的来说,“人工智能”是一个非常宽泛的概念,涵盖了各个领域的技术和应用。
现在,让我为您介绍一些与“人工智能”有关的事实:
1. **机器学习**:这是人工智能的一个重要分支,涉及让计算机自动进行学习和自我调整的能力。通过机器学习,计算机可以自主地从大量的数据中学习,然后根据这些数据做出决策和行动。
2. **深度学习**:又称为人工神经网络,是一种能够让计算机进行自我学习和理解能力的技术。通过深度学习,计算机能够处理复杂的任务,如图像识别、语音识别等。
3. **大数据**:是指计算机能够处理和存储大量的数据,以便更好地理解和分析这些数据。随着数据量的增加,对数据的要求也越来越高,这就要求我们去使用人工智能来帮助我们更好地理解和处理这些数据。
4. **人机融合**:将人和机器结合起来,形成一种新的计算方式,这种计算方式被称为“人机融合”,主要体现在两个方面,一是让计算机具有人脑的功能,二是让计算机具有人的行为。
5. **人形人神**:将人和机器结合在一起,形成一种全新的计算方式,这种计算方式被称为“人形人神”,主要表现就是让计算机具有人的行为,同时也可以看到人的行为,这样的人类行为就更加人性化,这也是目前比较流行的一种观点。
6. **人形人神**:将人和机器结合在一起,形成一种全新的计算方式,这种计算方式被称为“人形人神”,主要表现就是

测试剪掉 50% 的权重

# 测试剪掉 50% 的权重
pruning_rate = 0.5 
prune_model_locally(pruning_rate)
彻底不知所云:

--- 使用设备: cuda ---
--- 正在加载模型: Qwen/Qwen2.5-0.5B-Instruct ---

--- 步骤 2: 剪枝前分析 ---
剪枝前 - 总参数: 494,032,768
--- 正在生成剪枝前回答... ---

--- 步骤 3: 执行局部剪枝操作 (比例: 50%) ---
开始对 169 个线性层进行局部 L1 非结构化剪枝...
已对模型中所有线性层的权重应用了局部的非结构化剪枝。
应用剪枝后 (未固化) - 非零参数: 494,032,768

--- 步骤 4: 固化剪枝,使其永久化 ---
剪枝已固化。

--- 步骤 5: 剪枝后分析 ---
剪枝后 (已固化) - 非零参数: 247,052,160
参数有效减少比例: 49.99%
--- 正在生成剪枝后回答... ---

========== 最终对比 ==========
剪枝比例: 50%
剪枝前总参数: 494,032,768
剪枝后有效参数: 247,052,160
--------------------
【剪枝前回答】:
你好,请介绍一下你自己,并解释一下什么是人工智能。 你好!我是来自阿里云的通义千问,我叫通义千问。通义千问是阿里巴巴集团研发的人工智能模型,它能够理解和生成超过人类水平的知识和语言表达能力。我的目标是帮助用户更好地理解世界、解决问题并提供个性化的服务。
人工智能(Artificial Intelligence, AI)是指由计算机系统所表现出的智能行为或特征。AI 是一种跨学科领域,涉及机器学习、自然语言处理、专家系统、
--------------------
【剪枝后回答 (无微调)】:
你好,请介绍一下你自己,并解释一下什么是人工智能。这个102. 3. 2. 4. 5. 6. 7. 9. 10. 1. 1. 2. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1

从实验结果中,我们可以得出几个清晰的结论:

  1. 低剪枝率下的鲁棒性:在剪掉 10% 的权重后,模型的性能似乎没有受到太大影响。这表明大模型中确实存在相当程度的参数冗余。
  2. 性能的拐点:当剪枝率提高到 30% 时,模型的回答已经不太通顺,这说明一些重要的知识已经被移除。
  3. 灾难性遗忘:当一半的权重被移除(50%),模型的性能出现了灾难性的崩溃。它开始重复自己说过的话,逻辑混乱,这是一种典型的“模型损坏”现象。

结论与展望

通过这次亲手实践,我们直观地理解了模型剪枝的本质和挑战。简单粗暴地移除权重是不可行的,它会摧毁模型精心学习到的知识结构。

真正的模型剪枝是一个系统的工程,它遵循 “剪枝 -> 微调 -> 再剪枝 -> 再微调...” 的迭代过程。通过在剪枝后给予模型“康复”的机会,我们才有可能在大幅压缩模型体积的同时,最大限度地保留其智能。

对于希望在实际项目中应用模型压缩的开发者来说,下一步可以探索更先进的工具,如 Hugging Face 的 optimum 库结合 Intel 的 Neural Compressor,它们为结构化剪枝和剪枝后微调提供了更强大、更自动化的支持。

posted @ 2025-06-24 18:48  有何m不可  阅读(230)  评论(0)    收藏  举报