Visual Token Pruning by Attention Mass
Problem Statement
Inference-time VLM speedups (FastV, and friends) drop the visual tokens the language model barely attends to. Given the LM's attention over visual tokens, keep the smallest set of tokens covering a target fraction of the attention mass and report the FLOPs saved.
Background
Let attn be the total attention weight each visual token receives (summed over the query tokens that look at it). Normalize it to a distribution, sort tokens by mass descending (ties broken by smaller original index), and keep tokens one by one until their cumulative mass first reaches keep_fraction. The rest are pruned.
Because self-attention cost scales with the number of tokens squared, dropping from N to k visual tokens cuts the visual-attention FLOPs by **1 - (k/N)2.
Your Task
Implement:
def prune_visual_tokens(attn, keep_fraction):
Return a dict:
- "kept": sorted list of original indices of the kept tokens.
- "num_kept": how many were kept.
- "flops_saved": **1 - (num_kept/N)2, rounded to 4 decimals.
Input Format
- attn: list of N non-negative attention weights.
- keep_fraction (float) in (0, 1].
Output Format
- A dict with the three keys above.
Sample
print(prune_visual_tokens([0.5, 0.3, 0.1, 0.1], 0.75))
Output:
{'kept': [0, 1], 'num_kept': 2, 'flops_saved': 0.75}
Example
print(prune_visual_tokens([0.5, 0.3, 0.1, 0.1], 0.75))
{'kept': [0, 1], 'num_kept': 2, 'flops_saved': 0.75}Normalized mass is [0.5,0.3,0.1,0.1]. Take token 0 (0.5), then token 1 (cum 0.8 >= 0.75) and stop. Kept {0,1}; 2 of 4 tokens; FLOPs saved 1-(2/4)^2 = 0.75.
Constraints
1 <= N <= 100000, allattn[i] >= 0, not all zero.- Normalize to a distribution; sort by mass descending, ties to smaller index.
- Keep until cumulative mass first reaches
keep_fraction. keptis returned sorted ascending;flops_savedrounded to 4 decimals.