When I read the code for multi-head attention, I noticed all people consider the batch_size in the forward()

For example, the code below was provided by GPT:

class MultiHeadAttention(nn.Module):
    def __init__(self, embed_size, heads):
        super(MultiHeadAttention, self).__init__()
        self.embed_size = embed_size
        self.heads = heads
        self.head_dim = embed_size // heads
        assert self.head_dim * heads == embed_size, "Embedding size needs to be divisible by heads"
        self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.fc_out = nn.Linear(heads * self.head_dim, embed_size)
    def forward(self, values, keys, query, mask):
        N = query.shape[0]
        value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]
        # Split the embedding into self.heads different pieces
        values = values.reshape(N, value_len, self.heads, self.head_dim)
        keys = keys.reshape(N, key_len, self.heads, self.head_dim)
        queries = query.reshape(N, query_len, self.heads, self.head_dim)
        values = self.values(values)
        keys = self.keys(keys)
        queries = self.queries(queries)
        # Dot product attention
        energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])
        if mask is not None:
            energy = energy.masked_fill(mask == 0, float("-1e20"))
        attention = torch.softmax(energy / (self.embed_size ** (1 / 2)), dim=3)
        out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(N, query_len, self.heads * self.head_dim)
        # Apply the final linear layer and return
        out = self.fc_out(out)
        return out

I don't understand why we need N=query.shape[0]. I know the N here represents the batchsize, but I don't know why it is necessary considering pytorch would automatically deal with the batchsize as it did in CNN. Instead, I think values=values.reshape(value_len,self.heads, self.head_dim) is better.

And I asked GPT, he told me the batchsize is important when split the queries into multiple-head. But I think $d_{model}=n_{head}\cdot d_k$, therefore it is nothing to do with the batchsize.



You must log in to answer this question.

Browse other questions tagged .