from transformers import BertModel
Q ==> Linear
K ==> Linear ==> Scaled dot-product Attn ==> concat ==> Linear
V ==> Linear 

书接上回

# 经过W_k,W_q,W_v的
def scaled_dot_product_attention(query,key,value):
	# hidden_size
	dim_k = key.size(-1)
	# batch_size,seq_len,seq_len
	attn_scores = torch.bmm(query,key.transpose(1,2))/np.sqrt(dim_k)
	attn_weights = F.softmax(attn_scores,dim=1)
	
	return torch.bmm(attn_weights,dim=1)
class AttentionHead(nn.Module):
	def __init__(self,embed_dim,head_dim):
		super().__init__()
		self.Wq = nn.Linear(embed_dim,head_dim)
		self.Wk = nn.Linear(embed_dim,head_dim)
		self.Wv = nn.Linear(embed_dim,head_dim)
	def forward(self,hidden_states):
		q = self.Wq(hidden_states)
		k = self.Wk(hidden_states)
		v = self.Wv(hidden_states)
		attn_outputs = scaled_dot_product_attention(q,k,v)
		return attn_outputs
class MultiHeadAttention(nn.Module):
	def __init__(self,config):
		super().__init__()
		embed_dim = config.hidden_size
		num_heads = config.num_attention_heads
		# 768/12 == 64
		head_dim = embed_dim//num_heads
		self.heads = nn.ModuleList([
			AttentionHead(embed_dim,head_dim) for _ in range(num_heads)
		])
		self.output_layer = nn.Linear(embed_dim,embed_dim)
	def forward(self,hidden_size):
		print(f'input hidden_state:{hidden_state.shape}')
		print(f'head(hidden_state):{self.heads[11](hidden_state).shape}')
		x = torch.cat([head(hidden_state) for head in self.heads],dim=-1)
		print(f'cat heads:{x.shape}')
		x = self.output_layer(x)
		return x
from torch import nn
from transformers import AutoConfig,AutoTokenizer,AutoModel
model_ckpt = 'bert-base-uncased'
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)

# hyperparameters
config = AutoConfig.from_pretrained(model_ckpt)
config
mha = MultiHeadAttention(config)
mha(input_embeddings)
from bertviz import head_view
from transformers import AutoModel
model = AutoModel.from_pretrained(model_ckpt,output_attention=True)
sentence_a = "time files like an arrow"
sentence_b = "fruit files like a banana"
viz_inputs = tokenizer(sentence_a,sentence_b,return_tensors='pt')
# nsp (next sentence prediction)
print(viz_inputs)
attention = model(**viz_inputs).attentions
sentence_b_start = (viz_inputs.token_type_ids == 0).sum(dim=1)
print(sentence_b_start)
tokens = tokenizer.convert_ids_to_tokens(viz_tokens.input_ids[0])
head_view(attention,tokens,sentence_b_start,head=[8])