模型量化

量化是降低模型大小和内存需求的技术,让大模型能在普通硬件上运行。

什么是量化?

量化是将模型权重从高精度(如 FP16)转换为低精度(如 INT4)的过程。

原始模型使用 16 位浮点数存储权重,量化后可以使用 4 位整数存储,大大减少内存占用。

量化类型

常用量化格式

格式说明大小质量
Q4_K_M4位中等量化较小良好
Q4_K_S4位小量化最小可接受
Q5_K_M5位中等量化中等较好
Q5_K_S5位小量化中等较好
Q6_K6位量化较大很好
Q8_08位量化最大最好

量化命名规则

Q4_K_M
│ │ │ │
│ │ │ └─ M: Medium(中等)
│ │ └─── K: K-quant(K量化)
│ └───── 4: 4位
└─────── Q: Quantization(量化)

选择量化类型

根据内存选择

可用内存推荐量化
4-6 GBQ4_K_S
6-8 GBQ4_K_M
8-12 GBQ5_K_M
12-16 GBQ6_K
16+ GBQ8_0 或 FP16

根据用途选择

用途推荐量化
聊天对话Q4_K_M
代码生成Q5_K_M 或更高
文本摘要Q4_K_M
翻译任务Q4_K_M
精确任务Q6_K 或 Q8_0

查看模型量化

ollama show llama3.2

输出包含量化信息:

Model
  architecture        llama
  parameters          3.2B
  quantization        Q4_K_M

API 查看

import ollama

info = ollama.show('llama3.2')
quant = info['details']['quantization_level']
print(f"量化类型: {quant}")

下载特定量化

# 默认量化(通常是 Q4_K_M)
ollama pull llama3.2

# 指定量化
ollama pull llama3.2:3b-q4_K_M
ollama pull llama3.2:3b-q5_K_M
ollama pull llama3.2:3b-q8_0

量化对比

import ollama
import time

def benchmark_quantization(model_name, prompt, quantizations):
    results = []
    
    for quant in quantizations:
        full_name = f"{model_name}:{quant}"
        
        try:
            ollama.pull(full_name)
        except:
            print(f"跳过 {full_name}(不可用)")
            continue
        
        info = ollama.show(full_name)
        size = info['details'].get('size', 0)
        
        start = time.time()
        response = ollama.generate(
            model=full_name,
            prompt=prompt,
            options={'num_predict': 100}
        )
        duration = time.time() - start
        
        results.append({
            'quantization': quant,
            'size_gb': size / (1024**3),
            'duration': duration,
            'tokens': response.get('eval_count', 0)
        })
    
    return results

results = benchmark_quantization(
    'llama3.2',
    '写一首关于春天的诗',
    ['q4_K_S', 'q4_K_M', 'q5_K_M', 'q8_0']
)

for r in results:
    print(f"{r['quantization']}: {r['size_gb']:.2f}GB, {r['duration']:.2f}s")

内存估算

def estimate_memory(parameters_b, quantization):
    bits = {
        'q4_K_S': 4.5,
        'q4_K_M': 4.8,
        'q5_K_S': 5.5,
        'q5_K_M': 5.7,
        'q6_K': 6.6,
        'q8_0': 8.5,
        'fp16': 16
    }
    
    bits_per_param = bits.get(quantization.lower(), 4.8)
    size_gb = (parameters_b * 1e9 * bits_per_param) / (8 * 1024**3)
    
    return size_gb

print(f"7B Q4_K_M: {estimate_memory(7, 'q4_K_M'):.2f} GB")
print(f"7B Q8_0: {estimate_memory(7, 'q8_0'):.2f} GB")
print(f"13B Q4_K_M: {estimate_memory(13, 'q4_K_M'):.2f} GB")

量化与质量权衡

import ollama

def compare_quality(prompt, models):
    for model in models:
        response = ollama.generate(
            model=model,
            prompt=prompt,
            options={'temperature': 0.7}
        )
        
        print(f"\n=== {model} ===")
        print(response['response'][:200])

compare_quality(
    "解释什么是机器学习",
    ['llama3.2:3b-q4_K_M', 'llama3.2:3b-q5_K_M', 'llama3.2:3b-q8_0']
)