v9.1.1
Menu

Q-Former Output Shape and Parameter Count

easyFREEBridge Modules: Projectors, Q-Former & Cross-AttentionVision-Language ModelsVLM 1: Vision-Language Models

Problem Statement

Size a BLIP-2 style Q-Former: given the number of learned query tokens, the widths involved and the number of cross-attention blocks, report the output shape, the parameter count, and the compression ratio it achieves over the raw visual tokens.

Background

A linear projector maps every one of the vision encoder's tokens into the LLM, so a 257-token ViT costs 257 LLM positions. A Q-Former breaks that coupling: it owns a fixed set of num_queries learned query embeddings (32 in BLIP-2) that cross-attend to the image features and emit exactly num_queries output tokens - no matter how many image tokens came in. That is the compression ratio:

compression = num_image_tokens / num_queries

Count the parameters with this simplified model:

  • Learned queries: num_queries * d_query
  • Each of num_layers cross-attention blocks has four projections, all with a bias:
    • W_Q: d_query x d_query + d_query
    • W_K: d_image x d_query + d_query
    • W_V: d_image x d_query + d_query
    • W_O: d_query x d_query + d_query
  • Final projector into the LLM: d_query x d_llm + d_llm

W_K and W_V read the frozen vision encoder's width d_image (1408 for EVA-ViT-g) and write the Q-Former's own width d_query (768), which is why the two widths appear asymmetrically.

Notice what is missing from the list: num_image_tokens. Sequence length never appears in a parameter count - only in the activation/FLOP cost. The Q-Former's size is identical whether it consumes 257 or 4097 image tokens.

Your Task

Implement:

def qformer_stats(num_queries, d_query, d_image, num_image_tokens, num_layers, d_llm):

Return [num_image_tokens, num_queries, d_llm, total_params, compression] where the first four are ints and compression is num_image_tokens / num_queries rounded to 4 decimals.

Input Format

Six positive integers, as named above.

Output Format

[int, int, int, int, float]

Sample

print(qformer_stats(32, 768, 1408, 256, 12, 4096))

Output:

[256, 32, 4096, 43319296, 8.0]

Example

Input
print(qformer_stats(32, 768, 1408, 256, 12, 4096))
Output
[256, 32, 4096, 43319296, 8.0]
Reasoning
  • Inputs: 32 learned queries of width dquery=768d_{query}=768, a vision encoder of width dimage=1408d_{image}=1408 emitting 256 tokens, 12 cross-attention blocks, and an LLM of width dllm=4096d_{llm}=4096.
  • One block: the two 768×768768 \times 768 projections cost 7682+768=590,592768^2 + 768 = 590{,}592 each, the two 1408×7681408 \times 768 ones cost 1,081,344+768=1,082,1121{,}081{,}344 + 768 = 1{,}082{,}112 each, so a block holds 2(590,592)+2(1,082,112)=3,345,4082(590{,}592) + 2(1{,}082{,}112) = 3{,}345{,}408 parameters. Twelve blocks give 40,144,89640{,}144{,}896.
  • The rest: the queries add 32×768=24,57632 \times 768 = 24{,}576 and the projector adds 768×4096+4096=3,149,824768 \times 4096 + 4096 = 3{,}149{,}824, for a total of 43,319,29643{,}319{,}296.
  • Compression: 256/32=8256 / 32 = 8, so the output is [256, 32, 4096, 43319296, 8.0]: 256 visual tokens in, 32 tokens of width 4096 out.
  • Notice the token count only enters the ratio. With 4096 image tokens the total stays 43,319,29643{,}319{,}296 while the ratio jumps to 128128.

Constraints

  • All inputs are positive integers
  • Every projection carries a bias vector of length equal to its output width
  • W_K and W_V map d_image -> d_query; W_Q and W_O map d_query -> d_query
  • The parameter count must NOT depend on num_image_tokens
  • Round compression to 4 decimals; return the counts as plain Python ints

Learn this in

More from VLM 1: Vision-Language Models

solution.py

Test results

Sign in to run your code against the test cases.