Module neuralops.compression_engine.huffman_coder
Huffman Coder & Entropy Compression Engine for Weight and KV Cache Quantization. Registered as 'huffman'. Production-hardened with vectorized encode/decode, exact byte accounting, safe LoRA freezing, and robust tokenizer forward checks.
Functions
def huffman_factory(model: nn.Module, comp_config: Any = None, **kwargs: Any) ‑> torch.nn.modules.module.Module-
Expand source code
@COMPRESSOR_REGISTRY.register("huffman") @COMPRESSOR_REGISTRY.register("huffman_coder") def huffman_factory(model: nn.Module, comp_config: Any = None, **kwargs: Any) -> nn.Module: """Huffman compressor factory function.""" bits = kwargs.pop( "quantize_bits", kwargs.pop( "bits", _cfg_get(comp_config, "huffman_bits", _cfg_get(comp_config, "quantize_bits", 8)), ), ) max_error = kwargs.pop( "max_error", _cfg_get(comp_config, "huffman_max_error", _cfg_get(comp_config, "max_error", 0.20)), ) target_attention_only = kwargs.pop( "target_attention_only", _cfg_get( comp_config, "huffman_target_attention_only", _cfg_get(comp_config, "target_attention_only", False), ), ) fallback = kwargs.pop( "fallback_to_original", _cfg_get( comp_config, "huffman_fallback_to_original", _cfg_get(comp_config, "fallback_to_original", True), ), ) compressor = HuffmanCompressor( model, quantize_bits=bits, max_error=max_error, target_attention_only=target_attention_only, fallback_to_original=fallback, cfg=comp_config, **kwargs, ) compressed_model, _ = compressor.compress() return compressed_modelHuffman compressor factory function.
Classes
class HuffmanCoder-
Expand source code
class HuffmanCoder: """ Vectorized lossless entropy coder for quantized weight and KV cache tensors. Supports continuous tensor quantization (e.g. 4-bit / 8-bit), symbol frequency modeling, binary prefix tree construction, numpy bitstream packing, and vectorized decoding. """ @staticmethod def build_tree(frequencies: dict[int, int]) -> HuffmanNode | None: """Build Huffman binary prefix tree from symbol frequencies.""" if not frequencies: return None heap: list[HuffmanNode] = [HuffmanNode(sym, freq) for sym, freq in frequencies.items()] heapq.heapify(heap) if len(heap) == 1: root = HuffmanNode(freq=heap[0].freq, left=heap[0]) return root while len(heap) > 1: node1 = heapq.heappop(heap) node2 = heapq.heappop(heap) merged = HuffmanNode(freq=node1.freq + node2.freq, left=node1, right=node2) heapq.heappush(heap, merged) return heap[0] @staticmethod def generate_code_table( root: HuffmanNode | None, current_code: str = "", code_table: dict[int, str] | None = None, ) -> dict[int, str]: """Traverse Huffman tree to generate prefix bitstring per symbol.""" if code_table is None: code_table = {} if root is None: return code_table if root.symbol is not None: code_table[root.symbol] = current_code if current_code else "0" return code_table if root.left is not None: HuffmanCoder.generate_code_table(root.left, current_code + "0", code_table) if root.right is not None: HuffmanCoder.generate_code_table(root.right, current_code + "1", code_table) return code_table @staticmethod def encode( tensor: torch.Tensor, quantize_bits: int | None = 8, ) -> tuple[bytes, dict[int, str], dict[str, Any]]: """ Vectorized encode input tensor into packed bitstream bytes and Huffman codebook. """ flat = tensor.detach().float().view(-1) numel = flat.numel() if numel == 0: return b"", {}, {"total_elements": 0, "entropy": 0.0, "compressed_bytes": 0} min_val = flat.min().item() max_val = flat.max().item() # Handle high quantize_bits properly: skip quantization / identity mapping if quantize_bits is None or quantize_bits >= 16: if tensor.dtype == torch.bfloat16: raw_bytes = tensor.detach().cpu().view(torch.int16).numpy().tobytes() else: raw_bytes = tensor.detach().cpu().numpy().tobytes() metadata = { "scale": 1.0, "min_val": 0.0, "orig_shape": list(tensor.shape), "orig_dtype": str(tensor.dtype), "total_elements": numel, "entropy": 0.0, "pad_len": 0, "compressed_bytes": len(raw_bytes), "is_raw": True, } return raw_bytes, {}, metadata # Quantization num_levels = 2 ** int(quantize_bits) scale = (max_val - min_val) / max(num_levels - 1, 1) scale = max(scale, 1e-12) quantized = torch.clamp(torch.round((flat - min_val) / scale), 0, num_levels - 1).long() q_np = quantized.cpu().numpy() symbols, counts = np.unique(q_np, return_counts=True) frequencies = {int(s): int(c) for s, c in zip(symbols, counts)} root = HuffmanCoder.build_tree(frequencies) code_table = HuffmanCoder.generate_code_table(root) probs = counts / numel entropy = -float(np.sum(probs * np.log2(probs + 1e-12))) # Vectorized bitstream packing using LUT mapping and numpy.packbits max_sym = int(symbols.max()) lut = [code_table.get(i, "0") for i in range(max_sym + 1)] bit_chunks = [lut[v] for v in q_np] bitstream_str = "".join(bit_chunks) pad_len = (8 - len(bitstream_str) % 8) % 8 padded = bitstream_str + "0" * pad_len # Fast bit packing using np.packbits bit_arr = np.frombuffer(padded.encode("ascii"), dtype=np.uint8) - ord("0") packed_np = np.packbits(bit_arr) byte_array = packed_np.tobytes() metadata = { "scale": scale, "min_val": min_val, "orig_shape": list(tensor.shape), "orig_dtype": str(tensor.dtype), "total_elements": numel, "entropy": round(entropy, 3), "pad_len": pad_len, "compressed_bytes": len(byte_array), "is_raw": False, } return byte_array, code_table, metadata @staticmethod def decode( packed_bytes: bytes, code_table: dict[int, str], metadata: dict[str, Any], device: torch.device | None = None, ) -> torch.Tensor: """Vectorized decode bitstream back into reconstructed tensor.""" total_elements = metadata.get("total_elements", 0) if total_elements == 0: return torch.empty(metadata.get("orig_shape", [0]), device=device) if metadata.get("is_raw", False): orig_dtype_str = metadata.get("orig_dtype", "torch.float32") target_dtype = getattr(torch, orig_dtype_str.replace("torch.", ""), torch.float32) if target_dtype == torch.bfloat16: arr = np.frombuffer(packed_bytes, dtype=np.int16) tensor_out = ( torch.from_numpy(arr.copy()) .view(torch.bfloat16) .reshape(metadata.get("orig_shape")) ) else: dtype_str = orig_dtype_str.replace("torch.", "") np_dtype = getattr(np, dtype_str if hasattr(np, dtype_str) else "float32") arr = np.frombuffer(packed_bytes, dtype=np_dtype) tensor_out = ( torch.from_numpy(arr.copy()) .reshape(metadata.get("orig_shape")) .to(dtype=target_dtype) ) return tensor_out.to(device=device) scale = metadata.get("scale", 1.0) min_val = metadata.get("min_val", 0.0) shape = metadata.get("orig_shape", [total_elements]) # Vectorized unpacking of bits pad_len = metadata.get("pad_len", 0) raw_arr = np.frombuffer(packed_bytes, dtype=np.uint8) bits = np.unpackbits(raw_arr) if pad_len > 0: bits = bits[:-pad_len] # Fast flat-array binary trie traversal node_left = [-1] node_right = [-1] node_sym = [-1] for sym, code in code_table.items(): curr = 0 for b in code: if b == "0": if node_left[curr] == -1: node_left[curr] = len(node_left) node_left.append(-1) node_right.append(-1) node_sym.append(-1) curr = node_left[curr] else: if node_right[curr] == -1: node_right[curr] = len(node_right) node_left.append(-1) node_right.append(-1) node_sym.append(-1) curr = node_right[curr] node_sym[curr] = sym nl = np.array(node_left, dtype=np.int32) nr = np.array(node_right, dtype=np.int32) ns = np.array(node_sym, dtype=np.int32) decoded = np.empty(total_elements, dtype=np.float32) curr = 0 idx = 0 # Fast traversal loop for b in bits: curr = nr[curr] if b else nl[curr] sym = ns[curr] if sym != -1: decoded[idx] = sym idx += 1 curr = 0 if idx == total_elements: break decoded = decoded * scale + min_val return torch.from_numpy(decoded).reshape(shape).to(device=device)Vectorized lossless entropy coder for quantized weight and KV cache tensors. Supports continuous tensor quantization (e.g. 4-bit / 8-bit), symbol frequency modeling, binary prefix tree construction, numpy bitstream packing, and vectorized decoding.
Static methods
def build_tree(frequencies: dict[int, int]) ‑> HuffmanNode | None-
Expand source code
@staticmethod def build_tree(frequencies: dict[int, int]) -> HuffmanNode | None: """Build Huffman binary prefix tree from symbol frequencies.""" if not frequencies: return None heap: list[HuffmanNode] = [HuffmanNode(sym, freq) for sym, freq in frequencies.items()] heapq.heapify(heap) if len(heap) == 1: root = HuffmanNode(freq=heap[0].freq, left=heap[0]) return root while len(heap) > 1: node1 = heapq.heappop(heap) node2 = heapq.heappop(heap) merged = HuffmanNode(freq=node1.freq + node2.freq, left=node1, right=node2) heapq.heappush(heap, merged) return heap[0]Build Huffman binary prefix tree from symbol frequencies.
def decode(packed_bytes: bytes,
code_table: dict[int, str],
metadata: dict[str, Any],
device: torch.device | None = None) ‑> torch.Tensor-
Expand source code
@staticmethod def decode( packed_bytes: bytes, code_table: dict[int, str], metadata: dict[str, Any], device: torch.device | None = None, ) -> torch.Tensor: """Vectorized decode bitstream back into reconstructed tensor.""" total_elements = metadata.get("total_elements", 0) if total_elements == 0: return torch.empty(metadata.get("orig_shape", [0]), device=device) if metadata.get("is_raw", False): orig_dtype_str = metadata.get("orig_dtype", "torch.float32") target_dtype = getattr(torch, orig_dtype_str.replace("torch.", ""), torch.float32) if target_dtype == torch.bfloat16: arr = np.frombuffer(packed_bytes, dtype=np.int16) tensor_out = ( torch.from_numpy(arr.copy()) .view(torch.bfloat16) .reshape(metadata.get("orig_shape")) ) else: dtype_str = orig_dtype_str.replace("torch.", "") np_dtype = getattr(np, dtype_str if hasattr(np, dtype_str) else "float32") arr = np.frombuffer(packed_bytes, dtype=np_dtype) tensor_out = ( torch.from_numpy(arr.copy()) .reshape(metadata.get("orig_shape")) .to(dtype=target_dtype) ) return tensor_out.to(device=device) scale = metadata.get("scale", 1.0) min_val = metadata.get("min_val", 0.0) shape = metadata.get("orig_shape", [total_elements]) # Vectorized unpacking of bits pad_len = metadata.get("pad_len", 0) raw_arr = np.frombuffer(packed_bytes, dtype=np.uint8) bits = np.unpackbits(raw_arr) if pad_len > 0: bits = bits[:-pad_len] # Fast flat-array binary trie traversal node_left = [-1] node_right = [-1] node_sym = [-1] for sym, code in code_table.items(): curr = 0 for b in code: if b == "0": if node_left[curr] == -1: node_left[curr] = len(node_left) node_left.append(-1) node_right.append(-1) node_sym.append(-1) curr = node_left[curr] else: if node_right[curr] == -1: node_right[curr] = len(node_right) node_left.append(-1) node_right.append(-1) node_sym.append(-1) curr = node_right[curr] node_sym[curr] = sym nl = np.array(node_left, dtype=np.int32) nr = np.array(node_right, dtype=np.int32) ns = np.array(node_sym, dtype=np.int32) decoded = np.empty(total_elements, dtype=np.float32) curr = 0 idx = 0 # Fast traversal loop for b in bits: curr = nr[curr] if b else nl[curr] sym = ns[curr] if sym != -1: decoded[idx] = sym idx += 1 curr = 0 if idx == total_elements: break decoded = decoded * scale + min_val return torch.from_numpy(decoded).reshape(shape).to(device=device)Vectorized decode bitstream back into reconstructed tensor.
def encode(tensor: torch.Tensor, quantize_bits: int | None = 8) ‑> tuple[bytes, dict[int, str], dict[str, typing.Any]]-
Expand source code
@staticmethod def encode( tensor: torch.Tensor, quantize_bits: int | None = 8, ) -> tuple[bytes, dict[int, str], dict[str, Any]]: """ Vectorized encode input tensor into packed bitstream bytes and Huffman codebook. """ flat = tensor.detach().float().view(-1) numel = flat.numel() if numel == 0: return b"", {}, {"total_elements": 0, "entropy": 0.0, "compressed_bytes": 0} min_val = flat.min().item() max_val = flat.max().item() # Handle high quantize_bits properly: skip quantization / identity mapping if quantize_bits is None or quantize_bits >= 16: if tensor.dtype == torch.bfloat16: raw_bytes = tensor.detach().cpu().view(torch.int16).numpy().tobytes() else: raw_bytes = tensor.detach().cpu().numpy().tobytes() metadata = { "scale": 1.0, "min_val": 0.0, "orig_shape": list(tensor.shape), "orig_dtype": str(tensor.dtype), "total_elements": numel, "entropy": 0.0, "pad_len": 0, "compressed_bytes": len(raw_bytes), "is_raw": True, } return raw_bytes, {}, metadata # Quantization num_levels = 2 ** int(quantize_bits) scale = (max_val - min_val) / max(num_levels - 1, 1) scale = max(scale, 1e-12) quantized = torch.clamp(torch.round((flat - min_val) / scale), 0, num_levels - 1).long() q_np = quantized.cpu().numpy() symbols, counts = np.unique(q_np, return_counts=True) frequencies = {int(s): int(c) for s, c in zip(symbols, counts)} root = HuffmanCoder.build_tree(frequencies) code_table = HuffmanCoder.generate_code_table(root) probs = counts / numel entropy = -float(np.sum(probs * np.log2(probs + 1e-12))) # Vectorized bitstream packing using LUT mapping and numpy.packbits max_sym = int(symbols.max()) lut = [code_table.get(i, "0") for i in range(max_sym + 1)] bit_chunks = [lut[v] for v in q_np] bitstream_str = "".join(bit_chunks) pad_len = (8 - len(bitstream_str) % 8) % 8 padded = bitstream_str + "0" * pad_len # Fast bit packing using np.packbits bit_arr = np.frombuffer(padded.encode("ascii"), dtype=np.uint8) - ord("0") packed_np = np.packbits(bit_arr) byte_array = packed_np.tobytes() metadata = { "scale": scale, "min_val": min_val, "orig_shape": list(tensor.shape), "orig_dtype": str(tensor.dtype), "total_elements": numel, "entropy": round(entropy, 3), "pad_len": pad_len, "compressed_bytes": len(byte_array), "is_raw": False, } return byte_array, code_table, metadataVectorized encode input tensor into packed bitstream bytes and Huffman codebook.
def generate_code_table(root: HuffmanNode | None,
current_code: str = '',
code_table: dict[int, str] | None = None) ‑> dict[int, str]-
Expand source code
@staticmethod def generate_code_table( root: HuffmanNode | None, current_code: str = "", code_table: dict[int, str] | None = None, ) -> dict[int, str]: """Traverse Huffman tree to generate prefix bitstring per symbol.""" if code_table is None: code_table = {} if root is None: return code_table if root.symbol is not None: code_table[root.symbol] = current_code if current_code else "0" return code_table if root.left is not None: HuffmanCoder.generate_code_table(root.left, current_code + "0", code_table) if root.right is not None: HuffmanCoder.generate_code_table(root.right, current_code + "1", code_table) return code_tableTraverse Huffman tree to generate prefix bitstring per symbol.
class HuffmanCompressor (model: nn.Module,
quantize_bits: int = 8,
max_error: float = 0.2,
target_attention_only: bool = False,
fallback_to_original: bool = True,
cfg: Any | None = None,
**kwargs: Any)-
Expand source code
@COMPRESSOR_REGISTRY.register("huffman") @COMPRESSOR_REGISTRY.register("huffman_coder") class HuffmanCompressor(BaseCompressor): """ HuffmanCompressor: Model-wide entropy compression profiler and simulator. """ def __init__( self, model: nn.Module, quantize_bits: int = 8, max_error: float = 0.20, target_attention_only: bool = False, fallback_to_original: bool = True, cfg: Any | None = None, **kwargs: Any, ) -> None: super().__init__(model, name="huffman", **kwargs) cfg = cfg or kwargs.get("comp_config") self.cfg = cfg self.quantize_bits = int( _cfg_get( cfg, "huffman_quantize_bits", _cfg_get(cfg, "quantize_bits", _cfg_get(cfg, "bits", quantize_bits)), ) ) self.max_error = float( _cfg_get(cfg, "huffman_max_error", _cfg_get(cfg, "max_error", max_error)) ) self.target_attention_only = bool( _cfg_get( cfg, "huffman_target_attention_only", _cfg_get(cfg, "target_attention_only", target_attention_only), ) ) self.fallback_to_original = bool( _cfg_get( cfg, "huffman_fallback_to_original", _cfg_get(cfg, "fallback_to_original", fallback_to_original), ) ) self.compressed_layers: list[str] = [] self.fallback_layers: list[str] = [] self.skipped_layers: list[str] = [] self.layer_errors: dict[str, float] = {} def _is_target_module(self, name: str, module: nn.Module) -> bool: name_lower = name.lower() parts = name.split(".") if any(part in parts for part in ["lora_A", "lora_B", "base_layer"]): return False if any( skip in name_lower for skip in [ "classifier", "score", "lm_head", "pooler", "embedding", "router", "gate", ] ): return False if self.target_attention_only: if not any(attn_kw in name_lower for attn_kw in _ATTN_NAMES): return False target_mod = getattr(module, "base_layer", module) cls_name = target_mod.__class__.__name__.lower() is_linear = isinstance(target_mod, nn.Linear) is_conv1d = "conv1d" in cls_name or hasattr(target_mod, "nf") if not (is_linear or is_conv1d): return False if not should_compress_linear(self.model, name): return False return True def compress(self) -> tuple[nn.Module, dict[str, Any]]: """Profile and apply Huffman entropy coding across all linear layers.""" first_p = next(self.model.parameters(), None) _model_device = first_p.device if first_p is not None else torch.device("cpu") total_orig_bytes = 0 total_comp_bytes = 0 total_entropy = 0.0 self.compressed_layers = [] self.fallback_layers = [] self.skipped_layers = [] self.layer_errors = {} seen_weights: set[int] = set() # Freeze skipped non-target layers if target_attention_only is enabled if self.target_attention_only: for name, module in self.model.named_modules(): if any(part in name.split(".") for part in ["lora_A", "lora_B", "base_layer"]): continue target_mod = getattr(module, "base_layer", module) cls_name = target_mod.__class__.__name__.lower() is_linear = isinstance(target_mod, nn.Linear) is_conv1d = "conv1d" in cls_name or hasattr(target_mod, "nf") if (is_linear or is_conv1d) and not self._is_target_module(name, module): _freeze_base_only(module) self.skipped_layers.append(name) for name, module in self.model.named_modules(): if not self._is_target_module(name, module): continue target_mod = getattr(module, "base_layer", module) if not hasattr(target_mod, "weight") or target_mod.weight is None: continue w_id = id(target_mod.weight) if w_id in seen_weights: self.skipped_layers.append(name) continue seen_weights.add(w_id) cls_name = target_mod.__class__.__name__.lower() is_conv1d = "conv1d" in cls_name or hasattr(target_mod, "nf") raw_w = target_mod.weight.data orig_shape = raw_w.shape orig_device = raw_w.device orig_dtype = raw_w.dtype # Byte accounting based on actual element_size() elem_bytes = raw_w.element_size() if hasattr(raw_w, "element_size") else 2 layer_orig_bytes = raw_w.numel() * elem_bytes W_orig = raw_w.t().float() if is_conv1d else raw_w.float() norm_w = torch.norm(W_orig, p="fro").item() try: packed_b, code_map, meta = HuffmanCoder.encode( W_orig, quantize_bits=self.quantize_bits ) W_rec = HuffmanCoder.decode(packed_b, code_map, meta, device=orig_device).to( dtype=torch.float32 ) if norm_w < 1e-12: err = 0.0 else: err = float(torch.norm(W_orig - W_rec, p="fro").item() / norm_w) self.layer_errors[name] = err d_out, d_in = W_orig.shape fam = getattr(getattr(self.model, "config", None), "model_type", None) eff_max_err = max(self.max_error, adaptive_max_error(None, d_in, d_out, family=fam)) if err > eff_max_err: logger.warning( "Huffman error %.4f on %s exceeded max_error %.4f (base max_err=%.4f)", err, name, eff_max_err, self.max_error, ) if self.fallback_to_original: self.fallback_layers.append(name) _freeze_base_only(module) total_orig_bytes += layer_orig_bytes total_comp_bytes += layer_orig_bytes continue # Apply reconstructed weight if is_conv1d: res_w = W_rec.t().to(dtype=orig_dtype, device=orig_device) else: res_w = W_rec.to(dtype=orig_dtype, device=orig_device) assert res_w.shape == orig_shape, ( f"Shape mismatch on {name}: {res_w.shape} vs {orig_shape}" ) target_mod.weight.data.copy_(res_w) # Preserve LoRA adapter trainability for lora_attr in ("lora_A", "lora_B", "lora_a", "lora_b"): if hasattr(module, lora_attr): l_mod = getattr(module, lora_attr) if ( isinstance(l_mod, nn.Module) and hasattr(l_mod, "weight") and l_mod.weight is not None ): l_mod.weight.requires_grad = True elif isinstance(l_mod, nn.Parameter): l_mod.requires_grad = True self.compressed_layers.append(name) total_orig_bytes += layer_orig_bytes total_comp_bytes += meta["compressed_bytes"] total_entropy += meta["entropy"] except Exception as e: logger.debug("Huffman exception on %s: %s", name, e) self.fallback_layers.append(name) _freeze_base_only(module) total_orig_bytes += layer_orig_bytes total_comp_bytes += layer_orig_bytes # Ensure all parameters on target device self.model.to(device=_model_device) forward_check_success = None try: with torch.no_grad(): dev = next(self.model.parameters(), torch.tensor(0.0)).device tokenizer = getattr(self.model, "tokenizer", None) or getattr( getattr(self.model, "config", None), "tokenizer", None ) if tokenizer is not None: tok_out = tokenizer("Hello world", return_tensors="pt") tok_out = {k: v.to(dev) for k, v in tok_out.items()} self.model(**tok_out) forward_check_success = True else: # Look for token embeddings has_embed = any( any(kw in n.lower() for kw in ("embed_tokens", "wte", "word_embeddings")) for n, _ in self.model.named_modules() ) if has_embed: dummy_ids = torch.randint(0, 100, (1, 8), device=dev) dummy_mask = torch.ones((1, 8), device=dev) try: self.model(input_ids=dummy_ids, attention_mask=dummy_mask) except TypeError: self.model(dummy_ids) forward_check_success = True else: first_linear = next( (m for m in self.model.modules() if isinstance(m, nn.Linear)), None, ) if first_linear is not None: in_dim = getattr(first_linear, "in_features", 8) self.model(torch.randn(1, 8, in_dim, device=dev)) forward_check_success = True else: forward_check_success = None except Exception as fwd_exc: logger.debug("Huffman forward check failed: %s", fwd_exc) forward_check_success = None stats = self.get_compression_stats() avg_err = ( (sum(self.layer_errors.values()) / max(1, len(self.layer_errors))) if self.layer_errors else 0.0 ) stats["quantize_bits"] = self.quantize_bits stats["avg_entropy_bits"] = round(total_entropy / max(len(self.compressed_layers), 1), 2) stats["total_compressed_bytes"] = total_comp_bytes stats["huffman_compression_ratio"] = round(total_orig_bytes / max(total_comp_bytes, 1), 2) stats["theoretical_compression_ratio"] = stats["huffman_compression_ratio"] stats["num_compressed"] = len(self.compressed_layers) stats["num_fallback"] = len(self.fallback_layers) stats["num_skipped"] = len(self.skipped_layers) stats["compressed_layers"] = self.compressed_layers stats["fallback_layers"] = self.fallback_layers stats["skipped_layers"] = self.skipped_layers stats["avg_reconstruction_error"] = avg_err stats["forward_check_success"] = forward_check_success logger.info( "Compressor huffman finished: %d compressed, %d fallback, avg_err=%.4f, max_err_threshold=%.4f", len(self.compressed_layers), len(self.fallback_layers), avg_err, self.max_error, ) return self.model, statsHuffmanCompressor: Model-wide entropy compression profiler and simulator.
Ancestors
Methods
def compress(self) ‑> tuple[torch.nn.modules.module.Module, dict[str, typing.Any]]-
Expand source code
def compress(self) -> tuple[nn.Module, dict[str, Any]]: """Profile and apply Huffman entropy coding across all linear layers.""" first_p = next(self.model.parameters(), None) _model_device = first_p.device if first_p is not None else torch.device("cpu") total_orig_bytes = 0 total_comp_bytes = 0 total_entropy = 0.0 self.compressed_layers = [] self.fallback_layers = [] self.skipped_layers = [] self.layer_errors = {} seen_weights: set[int] = set() # Freeze skipped non-target layers if target_attention_only is enabled if self.target_attention_only: for name, module in self.model.named_modules(): if any(part in name.split(".") for part in ["lora_A", "lora_B", "base_layer"]): continue target_mod = getattr(module, "base_layer", module) cls_name = target_mod.__class__.__name__.lower() is_linear = isinstance(target_mod, nn.Linear) is_conv1d = "conv1d" in cls_name or hasattr(target_mod, "nf") if (is_linear or is_conv1d) and not self._is_target_module(name, module): _freeze_base_only(module) self.skipped_layers.append(name) for name, module in self.model.named_modules(): if not self._is_target_module(name, module): continue target_mod = getattr(module, "base_layer", module) if not hasattr(target_mod, "weight") or target_mod.weight is None: continue w_id = id(target_mod.weight) if w_id in seen_weights: self.skipped_layers.append(name) continue seen_weights.add(w_id) cls_name = target_mod.__class__.__name__.lower() is_conv1d = "conv1d" in cls_name or hasattr(target_mod, "nf") raw_w = target_mod.weight.data orig_shape = raw_w.shape orig_device = raw_w.device orig_dtype = raw_w.dtype # Byte accounting based on actual element_size() elem_bytes = raw_w.element_size() if hasattr(raw_w, "element_size") else 2 layer_orig_bytes = raw_w.numel() * elem_bytes W_orig = raw_w.t().float() if is_conv1d else raw_w.float() norm_w = torch.norm(W_orig, p="fro").item() try: packed_b, code_map, meta = HuffmanCoder.encode( W_orig, quantize_bits=self.quantize_bits ) W_rec = HuffmanCoder.decode(packed_b, code_map, meta, device=orig_device).to( dtype=torch.float32 ) if norm_w < 1e-12: err = 0.0 else: err = float(torch.norm(W_orig - W_rec, p="fro").item() / norm_w) self.layer_errors[name] = err d_out, d_in = W_orig.shape fam = getattr(getattr(self.model, "config", None), "model_type", None) eff_max_err = max(self.max_error, adaptive_max_error(None, d_in, d_out, family=fam)) if err > eff_max_err: logger.warning( "Huffman error %.4f on %s exceeded max_error %.4f (base max_err=%.4f)", err, name, eff_max_err, self.max_error, ) if self.fallback_to_original: self.fallback_layers.append(name) _freeze_base_only(module) total_orig_bytes += layer_orig_bytes total_comp_bytes += layer_orig_bytes continue # Apply reconstructed weight if is_conv1d: res_w = W_rec.t().to(dtype=orig_dtype, device=orig_device) else: res_w = W_rec.to(dtype=orig_dtype, device=orig_device) assert res_w.shape == orig_shape, ( f"Shape mismatch on {name}: {res_w.shape} vs {orig_shape}" ) target_mod.weight.data.copy_(res_w) # Preserve LoRA adapter trainability for lora_attr in ("lora_A", "lora_B", "lora_a", "lora_b"): if hasattr(module, lora_attr): l_mod = getattr(module, lora_attr) if ( isinstance(l_mod, nn.Module) and hasattr(l_mod, "weight") and l_mod.weight is not None ): l_mod.weight.requires_grad = True elif isinstance(l_mod, nn.Parameter): l_mod.requires_grad = True self.compressed_layers.append(name) total_orig_bytes += layer_orig_bytes total_comp_bytes += meta["compressed_bytes"] total_entropy += meta["entropy"] except Exception as e: logger.debug("Huffman exception on %s: %s", name, e) self.fallback_layers.append(name) _freeze_base_only(module) total_orig_bytes += layer_orig_bytes total_comp_bytes += layer_orig_bytes # Ensure all parameters on target device self.model.to(device=_model_device) forward_check_success = None try: with torch.no_grad(): dev = next(self.model.parameters(), torch.tensor(0.0)).device tokenizer = getattr(self.model, "tokenizer", None) or getattr( getattr(self.model, "config", None), "tokenizer", None ) if tokenizer is not None: tok_out = tokenizer("Hello world", return_tensors="pt") tok_out = {k: v.to(dev) for k, v in tok_out.items()} self.model(**tok_out) forward_check_success = True else: # Look for token embeddings has_embed = any( any(kw in n.lower() for kw in ("embed_tokens", "wte", "word_embeddings")) for n, _ in self.model.named_modules() ) if has_embed: dummy_ids = torch.randint(0, 100, (1, 8), device=dev) dummy_mask = torch.ones((1, 8), device=dev) try: self.model(input_ids=dummy_ids, attention_mask=dummy_mask) except TypeError: self.model(dummy_ids) forward_check_success = True else: first_linear = next( (m for m in self.model.modules() if isinstance(m, nn.Linear)), None, ) if first_linear is not None: in_dim = getattr(first_linear, "in_features", 8) self.model(torch.randn(1, 8, in_dim, device=dev)) forward_check_success = True else: forward_check_success = None except Exception as fwd_exc: logger.debug("Huffman forward check failed: %s", fwd_exc) forward_check_success = None stats = self.get_compression_stats() avg_err = ( (sum(self.layer_errors.values()) / max(1, len(self.layer_errors))) if self.layer_errors else 0.0 ) stats["quantize_bits"] = self.quantize_bits stats["avg_entropy_bits"] = round(total_entropy / max(len(self.compressed_layers), 1), 2) stats["total_compressed_bytes"] = total_comp_bytes stats["huffman_compression_ratio"] = round(total_orig_bytes / max(total_comp_bytes, 1), 2) stats["theoretical_compression_ratio"] = stats["huffman_compression_ratio"] stats["num_compressed"] = len(self.compressed_layers) stats["num_fallback"] = len(self.fallback_layers) stats["num_skipped"] = len(self.skipped_layers) stats["compressed_layers"] = self.compressed_layers stats["fallback_layers"] = self.fallback_layers stats["skipped_layers"] = self.skipped_layers stats["avg_reconstruction_error"] = avg_err stats["forward_check_success"] = forward_check_success logger.info( "Compressor huffman finished: %d compressed, %d fallback, avg_err=%.4f, max_err_threshold=%.4f", len(self.compressed_layers), len(self.fallback_layers), avg_err, self.max_error, ) return self.model, statsProfile and apply Huffman entropy coding across all linear layers.
Inherited members
class HuffmanNode (symbol: int | None = None,
freq: int = 0,
left: HuffmanNode | None = None,
right: HuffmanNode | None = None)-
Expand source code
class HuffmanNode: """Node in the Huffman prefix tree.""" def __init__( self, symbol: int | None = None, freq: int = 0, left: HuffmanNode | None = None, right: HuffmanNode | None = None, ) -> None: self.symbol = symbol self.freq = freq self.left = left self.right = right def __lt__(self, other: HuffmanNode) -> bool: return self.freq < other.freqNode in the Huffman prefix tree.