model.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. from torch import nn
  2. import math
  3. import torch
  4. # embedding层
  5. class Embeddings(nn.Module):
  6. def __init__(self, vocab_size,d_model):
  7. super().__init__()
  8. self.lut = nn.Embedding(vocab_size,d_model)
  9. self.d_model = d_model
  10. def forward(self,x):
  11. return self.lut(x) * math.sqrt(self.d_model)
  12. # 位置编码层
  13. class PositionalEncoding(nn.Module):
  14. def __init__(self, d_model,max_len=5000,dropout=0.1) -> None:
  15. super().__init__()
  16. self.dropout = nn.Dropout(dropout)
  17. pe = torch.zeros(max_len,d_model)
  18. position = torch.arange(0,max_len).unsqueeze(1)
  19. div_term = torch.exp(torch.arange(0,d_model,2) * -math.log(1000) / d_model)
  20. pe[:,0::2] = torch.sin(position * div_term)
  21. pe[:,1::2] = torch.cos(position * div_term)
  22. pe = pe.unsqueeze(0)
  23. self.register_buffer("pe",pe)
  24. def forward(self,x):
  25. x = x+ self.pe[:,:x.size(1)]
  26. return self.dropout(x)
  27. #注意力机制增加掩码
  28. def get_padding_mask(x,padding_idx):
  29. return (x == padding_idx).unsqueeze(1)
  30. #注意力机制
  31. def attention(q,k,v,mask=None,dropout=None):
  32. d_k = k.size(-1)
  33. scores = torch.matmul(q,k.transpose(-2,-1)) / math.sqrt(d_k)
  34. if mask is not None:
  35. scores = scores.masked_fill(mask,-1e9)
  36. p_attn = torch.softmax(scores,dim=-1)
  37. if dropout is not None:
  38. p_attn = dropout(p_attn)
  39. return torch.matmul(p_attn,v)
  40. #多头注意力机制
  41. class MultiHeadedAttention(nn.Module):
  42. def __init__(self, d_model,n_head,dropout=0.1):
  43. super().__init__()
  44. self.dropout = nn.Dropout(dropout)
  45. #必须能被整除
  46. assert d_model % n_head == 0
  47. self.d_k = d_model // n_head
  48. self.n_head = n_head
  49. #
  50. self.W_Q = nn.Linear(d_model,d_model,bias=False)
  51. self.W_K = nn.Linear(d_model,d_model,bias=False)
  52. self.W_V = nn.Linear(d_model,d_model,bias=False)
  53. self.linear = nn.Linear(d_model,d_model,bias=False)
  54. #norm
  55. self.norm = nn.LayerNorm(d_model)
  56. def forward(self,q,k,v,mask=None):
  57. res = q
  58. #分头
  59. #shape batch_size,seq_len,d_mdoel
  60. q = self.W_Q(q).view(q.shape[0],q.shape[1],self.n_head,self.d_k).transpose(1,2)
  61. k = self.W_K(k).view(k.shape[0],k.shape[1],self.n_head,self.d_k).transpose(1,2)
  62. v = self.W_V(v).view(v.shape[0],v.shape[1],self.n_head,self.d_k).transpose(1,2)
  63. #掩码也需要升维
  64. if mask is not None:
  65. mask = mask.unsqueeze(1)
  66. #计算注意力
  67. context = attention(q,k,v,mask,self.dropout)
  68. #拼接
  69. concat = context.transpose(1,2).reshape(q.shape[0],-1,self.n_head * self.d_k)
  70. output = self.linear(concat)
  71. return self.norm(res+output)
  72. #前馈神经网络
  73. class FeedForwardNet(nn.Module):
  74. def __init__(self, d_model, d_ff, dropout=0.1):
  75. super().__init__()
  76. self.dropout = nn.Dropout(dropout)
  77. self.w1 = nn.Linear(d_model, d_ff)
  78. self.w2 = nn.Linear(d_ff, d_model)
  79. # self.relu = nn.ReLU()
  80. self.gelu = nn.GELU() # GELU 不会像 ReLU 那样简单地把所有负数都设置为 0,而是进行更平滑的处理
  81. self.norm = nn.LayerNorm(d_model) # 对每个token的 d_model 个特征进行归一化,有助于训练稳定
  82. def forward(self, x):
  83. res = x
  84. # x = self.relu(self.w1(x))
  85. x = self.gelu(self.w1(x)) # 执行顺序由内向外
  86. x = self.dropout(self.w2(x))
  87. return self.norm(x + res)
  88. #编码器子层
  89. class EncoderLayer(nn.Module):
  90. def __init__(self,d_model,n_head,d_ff,dropout=0.1):
  91. super().__init__()
  92. self.mha=MultiHeadedAttention(d_model,n_head,dropout)
  93. self.ffn=FeedForwardNet(d_model,d_ff,dropout)
  94. def forward(self,x,mask=None):
  95. output = self.mha(x,x,x,mask)
  96. return self.ffn(output)
  97. #编码器层
  98. class Encoder(nn.Module):
  99. def __init__(self,vocab_size,d_model,n_head,d_ff,N=6,dropout=0.1):
  100. super().__init__()
  101. self.emb = Embeddings(vocab_size,d_model)
  102. self.pos = PositionalEncoding(d_model=d_model,dropout=dropout)
  103. self.layers = nn.ModuleList([
  104. EncoderLayer(d_model,n_head,d_ff,dropout)
  105. for _ in range(N)
  106. ])
  107. def forward(self,x,mask=None):
  108. x = self.emb(x)
  109. x = self.pos(x)
  110. for layer in self.layers:
  111. x = layer(x,mask)
  112. return x
  113. #生成掩码
  114. def get_subsequent_mask(size):
  115. mask_shape=(1,size,size)
  116. return 1-torch.tril(torch.ones(mask_shape)).byte()
  117. #解码器层
  118. class DecoderLayer(nn.Module):
  119. def __init__(self,d_model,n_head,d_ff,dropout=0.1):
  120. super().__init__()
  121. self.self_mha = MultiHeadedAttention(d_model,n_head,dropout)
  122. self.mha = MultiHeadedAttention(d_model,n_head,dropout)
  123. self.ffn = FeedForwardNet(d_model,d_ff,dropout)
  124. def forward(self,x,mask,memory,src_mask):
  125. x = self.self_mha(x,x,x,mask)
  126. x = self.mha(x,memory,memory,src_mask)
  127. return self.ffn(x)
  128. #
  129. class Decoder(nn.Module):
  130. def __init__(self,vocab_size,d_model,n_head,d_ff,N=6,dropout=0.1):
  131. super().__init__()
  132. self.emb = Embeddings(vocab_size,d_model)
  133. self.pos = PositionalEncoding(d_model=d_model,dropout=dropout)
  134. self.layers = nn.ModuleList([
  135. DecoderLayer(d_model,n_head,d_ff,dropout)
  136. for _ in range(N)
  137. ])
  138. def forward(self,x,mask,memory,src_mask):
  139. x =self.emb(x)
  140. x =self.pos(x)
  141. for layer in self.layers:
  142. x = layer(x,mask,memory,src_mask)
  143. return x
  144. #生成器
  145. class Generator(nn.Module):
  146. def __init__(self,d_model,vocab_size):
  147. super().__init__()
  148. self.linear = nn.Linear(d_model,vocab_size)
  149. def forward(self,x):
  150. return self.linear(x)
  151. #return torch.softmax(self.linear(x),dim=-1)
  152. #模型封装
  153. class Transformer(nn.Module):
  154. def __init__(self, src_vocab_size, tgt_vocab_size, d_model, n_head, d_ff, N=6, dropout=0.1):
  155. super().__init__()
  156. self.encoder = Encoder(src_vocab_size, d_model, n_head, d_ff, N, dropout)
  157. self.decoder = Decoder(tgt_vocab_size, d_model, n_head, d_ff, N, dropout)
  158. self.generator = Generator(d_model, tgt_vocab_size)
  159. def forward(self, src_x, src_mask, tgt_x, tgt_mask):
  160. memory = self.encoder(src_x, src_mask)
  161. output = self.decoder(tgt_x, tgt_mask, memory, src_mask)
  162. return self.generator(output)
  163. def make_model(src_vocab_size, tgt_vocab_size, d_model, n_head, d_ff, N=6, dropout=0.1):
  164. model = Transformer(src_vocab_size, tgt_vocab_size, d_model, n_head, d_ff, N, dropout)
  165. for p in model.parameters():
  166. if p.dim() > 1:
  167. nn.init.xavier_uniform_(p)
  168. return model
  169. if __name__ == '__main__':
  170. src_vocab_size = 10
  171. tgt_vocab_size = 20
  172. d_model = 8
  173. n_head = 2
  174. d_ff = 2048
  175. N = 6
  176. dropout = 0.1
  177. model = make_model(src_vocab_size, tgt_vocab_size, d_model, n_head, d_ff, N, dropout)
  178. print(model)
  179. # 输入数据
  180. src_inputs = torch.tensor([
  181. [1, 2, 3],
  182. [4, 5, 0],
  183. ])
  184. src_mask = get_padding_mask(src_inputs, 0)
  185. tgt_inputs = torch.tensor([
  186. [1, 2, 3, 4],
  187. [4, 5, 1, 0],
  188. ])
  189. # 处理mask
  190. tgt_pad_mask = get_padding_mask(tgt_inputs, 0)
  191. subsequent_mask = get_subsequent_mask(4)
  192. tgt_mask = tgt_pad_mask | subsequent_mask
  193. tgt_mask = tgt_mask != 0
  194. predict = model(src_inputs, src_mask, tgt_inputs, tgt_mask)
  195. print(predict.shape)