Forward pass; runs the following process: 1. Apply input projection 2. Split heads and prepare for SDPA 3. Run SDPA 4. Apply output projection Args: query (torch.Tensor): query of shape (N, L_t, E_q) key (torch
(self, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor)
| 198 | self.E_head = E_total // nheads |
| 199 | |
| 200 | def forward(self, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor) -> torch.Tensor: |
| 201 | """ |
| 202 | Forward pass; runs the following process: |
| 203 | 1. Apply input projection |
| 204 | 2. Split heads and prepare for SDPA |
| 205 | 3. Run SDPA |
| 206 | 4. Apply output projection |
| 207 | |
| 208 | Args: |
| 209 | query (torch.Tensor): query of shape (N, L_t, E_q) |
| 210 | key (torch.Tensor): key of shape (N, L_s, E_k) |
| 211 | value (torch.Tensor): value of shape (N, L_s, E_v) |
| 212 | |
| 213 | Returns: |
| 214 | attn_output (torch.Tensor): output of shape (N, L_t, E_q) |
| 215 | """ |
| 216 | # Step 1. Apply input projection |
| 217 | # TODO: demonstrate packed projection |
| 218 | query = self.query_proj(query) |
| 219 | key = self.key_proj(key) |
| 220 | value = self.value_proj(value) |
| 221 | |
| 222 | # Step 2. Split heads and prepare for SDPA |
| 223 | # reshape query, key, value to separate by head |
| 224 | # (N, L_t, E_total) -> (N, L_t, nheads, E_head) -> (N, nheads, L_t, E_head) |
| 225 | query = query.unflatten(-1, [self.nheads, self.E_head]).transpose(1, 2) |
| 226 | # (N, L_s, E_total) -> (N, L_s, nheads, E_head) -> (N, nheads, L_s, E_head) |
| 227 | key = key.unflatten(-1, [self.nheads, self.E_head]).transpose(1, 2) |
| 228 | # (N, L_s, E_total) -> (N, L_s, nheads, E_head) -> (N, nheads, L_s, E_head) |
| 229 | value = value.unflatten(-1, [self.nheads, self.E_head]).transpose(1, 2) |
| 230 | |
| 231 | # Step 3. Run SDPA |
| 232 | # (N, nheads, L_t, E_head) |
| 233 | attn_output = F.scaled_dot_product_attention( |
| 234 | query, key, value, dropout_p=dropout_p, is_causal=True) |
| 235 | # (N, nheads, L_t, E_head) -> (N, L_t, nheads, E_head) -> (N, L_t, E_total) |
| 236 | attn_output = attn_output.transpose(1, 2).flatten(-2) |
| 237 | |
| 238 | # Step 4. Apply output projection |
| 239 | # (N, L_t, E_total) -> (N, L_t, E_out) |
| 240 | attn_output = self.out_proj(attn_output) |
| 241 | |
| 242 | return attn_output |
| 243 | |
| 244 | ###################################################################### |
| 245 | # set hyperparameters following `the Transformer paper <https://arxiv.org/pdf/1706.03762.pdf>`__ |
nothing calls this directly
no outgoing calls
no test coverage detected