记录学习仅此而已:
cuda11.0
torch1.7.1
pos=位置
2i,2i+1=位置
d = 总维度
class positionalEncoder(nn.Module):
def __init__(self,d_model,max_seq_len=80):
super().__init__()
self.d_model = d_model
#make a tensor by pe,pe_dim.shape is (max_seq_len,d_model)
pe = torch.zeros(max_seq_len,d_model)
for pos in range(max_seq_len):
for i in range(max_seq_len):
pe[pos,i] = math.sin(pos/( 10000 ** ( i / d_model )))
pe[pos,i+1] = math.cos(pos/( 10000 ** ( i / d_model )))
pe = pe.unsqueeze(0)
self.register_buffer('pe',pe)
def forward(self,x):
x = x * math.sqrt(self.d_model)
seq_len = x.size(1)
x = x + self.pe[:,seq_len].to(device='cuda:0')
return x
# print(positionalEncoder(d_model=100)(torch.zeros(80,1).to(device='cuda:0')).size())
问题1:为什么用sin,cos进行位置编码的添加?
sin,cos为[-1,1]间,因此由作为添加入x中并不会导致因为加入的量太大而导致影响原先词向量和语意信息,并且可以得到具有线性关系的组合。
问题2:为什么不只用一单个三角函数来进行位置编码的添加?
因为为了确保位置编码能够更好地捕捉序列中不同位置之间的相对关系,并且能够提供充分的区分度,Transformer 模型中选择使用 sin 和 cos 函数的组合来生成位置编码是更为合适的做法,用间隔添加的话更能获得其不同位置的差异性。