MultiHeadAttentionWrapper implements multi-head attention by stacking several single-head CausalAttention modules. Each head performs attention independently, and their results are concatenated. section 3.6.2
Its implementation follows this data flow:
- Create a list of CausalAttention objects, with each object representing one attention head. section 3.6.2
- Run the input through every head independently. section 3.6.2
- Concatenate the outputs from all heads into the multi-head result. section 3.6.2
Two-head comparison
With two heads, the wrapper uses separate query weight matrices, Wq1 and Wq2, to produce Q1 and Q2. The integrated MultiHeadAttention class instead computes one larger query matrix and splits it internally. section 3.6.2
Figure 3.26 In the MultiHeadAttentionWrapper class with two attention heads, we initialized two weight matrices, Wq1 and Wq2, and computed two query matrices, Q1 and Q2 (top). In the MultiheadAttention class, we initialize one larger weight matrix Wq, only perform one matrix multiplication with the inputs to obtain a query matrix Q, and then split the query matrix into Q1 and Q2 (bottom). We do the same for the keys and values, which are not shown to reduce visual clutter.
Compare separate per-head projections with the integrated projection-and-split design. section 3.6.2
