22"""
33Plot KLD (Kullback-Leibler Divergence) vs model file size for quantization analysis.
44
5+ Categories: INT AWQ (W4A16, W8A16, FP8-INT4), NVFP4, GGUF - each with distinct color/shape.
6+
57Usage:
68 pip install matplotlib
79 python examples/plot_kld_analysis.py
8-
9- Edit the DATA section below to add your models.
1010"""
1111
1212import argparse
1919
2020
2121# --- Edit your data here ---
22- # Format: (file_size_gib, mean_kld, label)
22+ # Format: (file_size_gib, mean_kld, bpw, label, category)
23+ # category: "original" | "int_awq" | "nvfp4" | "gguf"
2324DATA = [
24- (30.0 , 0.0 , "Original (Llama-3.1-8B bf16)" ),
25- (6.2 , 0.033707 , "Quantized (FP8_INT4)" ),
26- (5.4 , 0.076226 , "Quantized (W4A16_GS128)" ),
27- (5.7 , 0.109275 , "Quantized (NVFP4)" ),
28- (8.6 , 0.000899 , "Quantized (W8A16_GS128)" ),
29- (8.5 , 0.006547 , "Quantized (W8A8-FP8_BLOCK)" ),
25+ # Original
26+ (30.0 , 0.0 , 16.0 , "Original (Llama-3.1-8B bf16)" , "original" ),
27+ # INT AWQ: W4A16, W8A16, FP8-INT4
28+ (5.4 , 0.076226 , 4.25 , "W4A16_GS128" , "int_awq" ),
29+ (8.6 , 0.000899 , 8.25 , "W8A16_GS128" , "int_awq" ),
30+ (6.2 , 0.033707 , 4.0 , "FP8_INT4" , "int_awq" ),
31+ # NVFP4
32+ (5.7 , 0.109275 , 4.0 , "NVFP4" , "nvfp4" ),
33+ (8.5 , 0.006547 , 8.0 , "W8A8-FP8_BLOCK" , "nvfp4" ),
34+ # GGUF (from reference chart)
35+ (3.5 , 0.1241 , 3.50 , "IQ3_XS" , "gguf" ),
36+ (3.65 , 0.1782 , 3.64 , "Q3_K_S" , "gguf" ),
37+ (4.0 , 0.0744 , 4.00 , "Q3_K_M" , "gguf" ),
38+ (4.4 , 0.0327 , 4.42 , "IQ4_XS" , "gguf" ),
39+ (4.7 , 0.0305 , 4.67 , "Q4_K_S" , "gguf" ),
40+ (4.9 , 0.0267 , 4.89 , "Q4_K_M" , "gguf" ),
41+ (5.6 , 0.0102 , 5.57 , "Q5_K_S" , "gguf" ),
42+ (5.7 , 0.0092 , 5.70 , "Q5_K_M" , "gguf" ),
43+ (6.6 , 0.0040 , 6.56 , "Q6_K" , "gguf" ),
44+ (8.0 , 0.0011 , 8.50 , "Q8_0" , "gguf" ),
3045]
31- # Add more: DATA.append((size_gib, kld, "Label"))
46+
47+ # Category styles: (color, marker)
48+ STYLES = {
49+ "original" : ("#7f7f7f" , "o" ),
50+ "int_awq" : ("#1f77b4" , "s" ),
51+ "nvfp4" : ("#ff7f0e" , "^" ),
52+ "gguf" : ("#2ca02c" , "D" ),
53+ }
3254
3355
3456def main ():
@@ -42,31 +64,68 @@ def main():
4264 )
4365 args = parser .parse_args ()
4466
45- fig , ax = plt .subplots (figsize = (10 , 6 ))
67+ fig , ax = plt .subplots (figsize = (16 , 10 ))
4668
47- # Unique style per point: original=gray circle, quants=distinct markers+colors
48- QUANT_MARKERS = ["s" , "^" , "D" , "v" , "p" , "h" , "8" , "*" , "P" , "X" ]
49- QUANT_COLORS = [
50- "#1f77b4" , "#ff7f0e" , "#2ca02c" , "#d62728" , "#9467bd" ,
51- "#8c564b" , "#e377c2" , "#7f7f7f" , "#bcbd22" , "#17becf" ,
69+ # Track legend entries to avoid duplicates
70+ legend_added = set ()
71+
72+ # Stagger label positions to reduce overlap (alternate quadrants)
73+ offsets = [
74+ (25 , 20 ), (25 , - 30 ), (- 100 , 20 ), (25 , 20 ), (- 100 , - 30 ),
75+ (25 , - 30 ), (- 100 , 20 ), (25 , 20 ), (- 100 , - 30 ), (25 , 20 ),
76+ (- 100 , - 30 ), (25 , - 30 ), (- 100 , 20 ), (25 , 20 ), (- 100 , - 30 ),
77+ (25 , - 30 ),
5278 ]
5379
54- for i , (s , k , lbl ) in enumerate (DATA ):
55- if k == 0 :
56- color , marker = "gray" , "o"
80+ for i , (size_gib , kld , bpw , label , category ) in enumerate (DATA ):
81+ color , marker = STYLES [category ]
82+ full_label = f"Llama-3.1-8B-Instruct-{ label } " if category != "original" else label
83+
84+ # Add to legend only once per category
85+ if category not in legend_added :
86+ legend_label = {
87+ "original" : "Original (bf16)" ,
88+ "int_awq" : "INT AWQ (W4A16, W8A16, FP8-INT4)" ,
89+ "nvfp4" : "NVFP4 / W8A8-FP8" ,
90+ "gguf" : "GGUF" ,
91+ }[category ]
92+ ax .scatter (
93+ [], [], color = color , marker = marker , s = 120 , label = legend_label
94+ )
95+ legend_added .add (category )
96+
97+ ax .scatter (size_gib , kld , color = color , s = 120 , marker = marker , zorder = 3 )
98+
99+ # Annotate with model name, KLD, bpw (like reference graph)
100+ text = f"{ full_label } \n { kld :.4f} \n { bpw :.2f} bpw"
101+
102+ if category == "original" :
103+ xytext = (- 120 , 15 )
57104 else :
58- idx = (i - 1 ) % len (QUANT_MARKERS )
59- color = QUANT_COLORS [idx % len (QUANT_COLORS )]
60- marker = QUANT_MARKERS [idx % len (QUANT_MARKERS )]
61- legend_label = f"{ lbl } ({ k :.4f} )" if k > 0 else lbl
62- ax .scatter (s , k , label = legend_label , color = color , s = 120 , marker = marker , zorder = 3 )
63-
64- ax .set_xlabel ("File Size (GiB)" )
65- ax .set_ylabel ("Mean KL Divergence (Lower is Better)" )
66- ax .set_title ("Quantization Quality: KLD vs File Size" )
67- ax .legend ()
68- ax .grid (True , alpha = 0.3 )
105+ xytext = offsets [i % len (offsets )]
106+ ha = "left" if xytext [0 ] > 0 else "right"
107+ va = "bottom" if xytext [1 ] > 0 else "top"
108+ ax .annotate (
109+ text ,
110+ (size_gib , kld ),
111+ xytext = xytext ,
112+ textcoords = "offset points" ,
113+ fontsize = 8 ,
114+ ha = ha ,
115+ va = va ,
116+ arrowprops = dict (arrowstyle = "-" , color = "gray" , lw = 0.5 ),
117+ )
118+
119+ ax .set_xlabel ("File Size (GiB)" , fontsize = 12 )
120+ ax .set_ylabel ("Mean KL Divergence (Lower is Better)" , fontsize = 12 )
121+ ax .set_title (
122+ "Llama-3.1-8B-Instruct Quantization Analysis: Mean KL Divergence vs. Model File Size" ,
123+ fontsize = 14 ,
124+ )
125+ ax .legend (loc = "upper right" , fontsize = 10 )
126+ ax .grid (True , alpha = 0.3 , linestyle = "--" )
69127 ax .set_ylim (bottom = - 0.02 )
128+ ax .set_xlim (left = 2.5 , right = 32 )
70129
71130 plt .tight_layout ()
72131 if args .output :
0 commit comments