Skip to content

Commit 7acd9f5

Browse files
committed
Release v0.2.4
- Add universal DataLoader format support for analyze_layer_importance - Support dict, tuple/list, and single tensor batch formats - Add _prepare_batch_inputs utility function - Document L2 norm neuron selection method - Add TensorDataset examples to notebook and docs - 16 new tests (11 unit + 5 integration) Closes #12, #17, #18
1 parent 6c0d86a commit 7acd9f5

27 files changed

Lines changed: 1899 additions & 735 deletions

CHANGELOG.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,65 @@
11
## [Unreleased]
22

3+
---
4+
5+
## [0.2.4] - 2026-01-10
6+
7+
### 🎉 New Features
8+
9+
#### Universal DataLoader Format Support for `analyze_layer_importance`
10+
- **Multi-Format Batch Handling**: `analyze_layer_importance` now automatically detects and handles multiple DataLoader batch formats without requiring HuggingFace dataset utilities
11+
- **Supported Formats**:
12+
- **Dictionary**: HuggingFace-style `{'input_ids': tensor, 'attention_mask': tensor}`
13+
- **Tuple/List**: PyTorch `TensorDataset` format `(input_ids, attention_mask, ...)`
14+
- **Single Tensor**: Direct tensor input treated as `input_ids`
15+
- **Positional Mapping**: Tuple/list elements automatically map to standard transformer arguments: `[0]=input_ids`, `[1]=attention_mask`, `[2]=token_type_ids`, etc.
16+
- **Internal Utility**: New `_prepare_batch_inputs()` function normalizes all formats transparently
17+
- **Debug Logging**: Optional DEBUG-level logging shows format detection and positional mapping
18+
- **Zero Breaking Changes**: Existing code with dict-based DataLoaders works exactly as before
19+
20+
**Closes Issues**: #12, #17, #18
21+
322
### 📝 Documentation Updates
423

524
#### Terminology Update: MAW → PPM
625
- **New Nomenclature**: The neuron selection method previously known as "MAW (Maximum Absolute Weight)" is now officially documented as **PPM (Peak-to-Peak Magnitude)**, which more accurately describes the calculation method (max + |min|).
726
- **Backward Compatibility**: The parameter value `"MAW"` is maintained for full backward compatibility and maps to the PPM method.
827
- **Research Foundation**: PPM is formally described in: *Martra, P. (2025). Fragile Knowledge, Robust Instruction-Following: The Width Pruning Dichotomy in Llama-3.2. ArXiv. https://arxiv.org/abs/2512.22671*
928
- **Updated Documentation**: All documentation files now reference PPM as the primary name with MAW noted as the legacy parameter value.
10-
- **No Breaking Changes**: No code changes required; all existing code using `neuron_selection_method="MAW"` continues to work exactly as before.
29+
30+
#### Clarification: L2 Norm Neuron Selection Method
31+
- **Existing Feature**: The L2 norm method (`neuron_selection_method="L2"`) has been available since early versions
32+
- **How It Works**: Calculates neuron importance using L2 (Euclidean) norms of weight values: `||gate_weight||₂ + ||up_weight||₂`
33+
- **Static Only**: Supports **weight-only (static) pruning** exclusively - not compatible with data-driven mode (dataloader)
34+
- **Documentation Enhancement**: Added explicit warnings in usage guides about L2 limitations vs PPM/MAW data-driven capabilities
35+
36+
### 🧪 Testing
37+
38+
#### Comprehensive Test Coverage for Batch Format Support
39+
- **Unit Tests**: 11 new tests for `_prepare_batch_inputs()` covering all format variations
40+
- **Integration Tests**: 5 new tests for `analyze_layer_importance()` with different DataLoader types
41+
- **Test Coverage**: Dict batches, 2-element tuples, 3+ element tuples, lists, single tensors, None handling, device placement
42+
- **All Tests Pass**: 16 new tests + 95 existing tests = 111 total passing tests
43+
44+
### 🔧 Technical Details
45+
46+
#### Implementation
47+
- **File**: `optipfair/pruning/utils.py`
48+
- **New Function**: `_prepare_batch_inputs(batch, device)` - internal utility with underscore prefix
49+
- **Modified Function**: `analyze_layer_importance()` in `optipfair/pruning/depth.py` now uses normalized batch handling
50+
- **Device Handling**: All tensors automatically moved to model device regardless of input format
51+
- **Error Handling**: Clear ValueError with format hints for unsupported batch types
52+
53+
#### Enhanced Examples
54+
- **layer_importance_analysis.ipynb**: Added section demonstrating TensorDataset (tuple format) usage
55+
- **docs/usage.md**: New examples showing analyze_layer_importance with various DataLoader formats
56+
57+
### 🔒 Compatibility
58+
59+
- **Fully Backward Compatible**: All existing code continues to work without modification
60+
- **No API Changes**: Function signatures unchanged, new functionality is transparent
61+
- **Python**: Requires Python >=3.8 (unchanged)
62+
- **Dependencies**: No new dependencies added
1163

1264
---
1365

docs/usage.md

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,4 +653,88 @@ pruned_model = prune_model(
653653
pruning_type="DEPTH",
654654
layer_indices=layers_to_remove
655655
)
656-
```
656+
```
657+
658+
### DataLoader Format Support (v0.2.4+)
659+
660+
Starting from OptiPFair v0.2.4, `analyze_layer_importance` automatically handles multiple DataLoader batch formats, making it compatible with both HuggingFace datasets and native PyTorch structures.
661+
662+
#### Supported Batch Formats
663+
664+
**1. Dictionary Format (HuggingFace)**
665+
666+
```python
667+
from datasets import load_dataset
668+
from torch.utils.data import DataLoader
669+
670+
# HuggingFace datasets return dict batches
671+
dataset = load_dataset('wikitext', 'wikitext-2-raw-v1', split='train[:100]')
672+
tokenized = dataset.map(tokenize_function, batched=True)
673+
tokenized.set_format(type='torch', columns=['input_ids', 'attention_mask'])
674+
dataloader = DataLoader(tokenized, batch_size=8)
675+
676+
# Batch format: {'input_ids': tensor, 'attention_mask': tensor}
677+
importance_scores = analyze_layer_importance(model, dataloader)
678+
```
679+
680+
**2. Tuple Format (TensorDataset)**
681+
682+
```python
683+
from torch.utils.data import DataLoader, TensorDataset
684+
685+
# Tokenize texts manually
686+
inputs = tokenizer(
687+
texts,
688+
truncation=True,
689+
padding='max_length',
690+
max_length=512,
691+
return_tensors='pt'
692+
)
693+
694+
# TensorDataset returns tuples
695+
dataset = TensorDataset(inputs['input_ids'], inputs['attention_mask'])
696+
dataloader = DataLoader(dataset, batch_size=8)
697+
698+
# Batch format: (input_ids, attention_mask)
699+
# Automatically mapped: [0]=input_ids, [1]=attention_mask
700+
importance_scores = analyze_layer_importance(model, dataloader)
701+
```
702+
703+
**3. List Format (Custom Datasets)**
704+
705+
```python
706+
class CustomDataset(Dataset):
707+
def __getitem__(self, idx):
708+
return [self.input_ids[idx], self.attention_mask[idx]]
709+
710+
# Batch format: [input_ids, attention_mask]
711+
# Same positional mapping as tuples
712+
importance_scores = analyze_layer_importance(model, dataloader)
713+
```
714+
715+
**4. Single Tensor Format**
716+
717+
```python
718+
# Dataset with only input_ids (no attention_mask)
719+
dataset = TensorDataset(input_ids_tensor)
720+
dataloader = DataLoader(dataset, batch_size=8)
721+
722+
# Batch format: single tensor
723+
# Automatically treated as input_ids
724+
importance_scores = analyze_layer_importance(model, dataloader)
725+
```
726+
727+
#### Positional Mapping for Tuple/List Formats
728+
729+
When using tuple or list batches, elements are automatically mapped to standard transformer arguments:
730+
731+
- `[0]``input_ids` (required)
732+
- `[1]``attention_mask` (optional)
733+
- `[2]``token_type_ids` (optional)
734+
- `[3]``position_ids` (optional)
735+
- `[4]``head_mask` (optional)
736+
- `[5]``inputs_embeds` (optional)
737+
738+
**Note**: All formats are fully backward compatible. Existing code continues to work without modifications.
739+
740+
---

0 commit comments

Comments
 (0)