项目地址:BiDAF-pytorch-with-Self-Attention
参考论文:R-NET(Microsoft Research Asia)
简单的PyTorch练习项目,为现成的BiDAF添加Self-Attention。
这篇博客全当是萌新学习pytorch的笔记就好。
需要修改的文件只有model/model.py。毕竟是练手项目,所以似乎并无什么坑点,只要照着论文一步步实现就好了吧。
核心代码:
def self_attention_layer(v): """ :param v: (batch, c_len ,hidden_size * 2) :return: x: (batch, c_len ,hidden_size * 2) """ c_len = v.size(1) # (batch, c_len) wv = self.att_weight_w(v).squeeze() # (batch, c_len) w2v = self.att_weight_w2(v).squeeze() x = [] for i in range(c_len): # (batch, c_len) -> (batch, 1) w2vi = w2v.index_select(1, torch.LongTensor([i]).to(self.device)) # (batch, 1) -> (batch, c_len) w2vi = w2vi.expand(-1, c_len) # (batch, c_len) + (batch, c_len) -> (batch, c_len) wv3 = wv + w2vi # (batch, c_len) wv3 = self.att_fix * wv3 # (batch, c_len) wv3 = torch.exp(torch.tanh(wv3)) # (batch, 1) su = torch.sum(wv3, 1).unsqueeze(1) # (batch, 1) -> (batch, c_len) su = su.expand(-1, c_len) # (batch, c_len) wv3 = torch.div(wv3, su) # (batch, c_len, 1) wv3 = wv3.unsqueeze(2) # (batch, c_len, 1) -> (batch, 1, c_len) wv3 = wv3.permute(0, 2, 1) # (batch, 1, c_len) * (batch, c_len ,hidden_size * 2) -> (batch, hidden_size * 2) xi = torch.bmm(wv3, v).squeeze() # (1...c_len, batch, hidden_size * 2) x.append(xi) # (batch, hidden_size * 2, c_len) x = torch.stack(x, 2).to(self.device) # (c_len, batch, hidden_size * 2) -> (batch, c_len, hidden_size * 2) x = x.permute(0, 2, 1) return x
主要意义大概就是学习torch的几个函数吧:
torch.size(dim)
显而易见,获取张量dim维的大小。
torch.index_select(dim, index)
将指定张量按照dim维度进行切片,index为引下标的一维张量。
注意临时张量千万别忘记to(device),否则会报错。
expand(dim, new_size)
将张量的dim维由1扩增到new_size,不消耗内存空间。
torch.unsqueeze(dim)
在张量的dim维插入大小为1的维度。
torch.div(x, y)
执行张量除法,对大小相同的张量为逐位除。
torch.sum(x, dim)
对张量x的dim维求和,求和后dim维消失。
torch.permute(...)
对张量各维度进行重排,参数为之前的维度顺序。(若参数为(a, b, c)),则将之前的第(a, b, c)维转化为新的第(0, 1, 2)维。
torch.bmm(x, y)
进行批矩乘。输入x, y为大小为(batch, a, b), (batch, b, c)的向量,则输出大小为(batch, a, c)的向量,(1, 2)维运算同常规矩乘。
torch.stack(x, dim)
将存储张量列表、元组转化为新的张量,dim为新增的维度。
还是别忘了to(device)。
torch.exp() torch.tanh()
标准的算术操作,分别作用于张量的每个位置。
效果并不怎么好的样子,默认参数下连原版baseline都不如。(话说我直接训练原版模型也达不到人家GitHub上说明的成绩(非酋实锤),添加Self-Attention后模型的表现比我训练的原版模型稍好一些)
大概是我写丑了吧。似乎要达到论文中的水平还需要一些奇怪的姿势呢,比如玄学调参、调结构(真·炼丹)。
GTX970用来测试+Debug还是够用的,真正训练直接交给学校的1080和1080ti。
显卡:果然和炼丹相比,还是炼铜更适合我。
所以说,现在N卡炼丹炼铜两不误。A卡呢?在ROCm完全可用之前,开始爪巴比较适合她。真·Game Processing Unit。
(回学校后Debian部署ROCm教程预定)
评论~ NOTHING