Neural network 立正

Neural network 立正,neural-network,deep-learning,pytorch,tensor,attention-model,Neural Network,Deep Learning,Pytorch,Tensor,Attention Model,我试图将注意力机制添加到堆叠的LSTMs实现中 所有在线示例都使用编码器-解码器体系结构,这是我不想使用的(我是否必须使用注意机制?) 基本上,我用过 这个模型正在训练,但与没有注意模型的模型相比,我的损失相当大。注意的全部要点是,不同语言中的词序是不同的,因此在解码目标语言中的第5个单词时,可能需要注意第3个单词(或第3个单词的编码)在源语言中,因为这些是相互对应的单词。这就是为什么您经常看到编码器-解码器结构使用注意力的原因 如果我理解正确,你是在做下一个单词预测吗?在这种情况下,使用注意

我试图将注意力机制添加到堆叠的LSTMs实现中

所有在线示例都使用编码器-解码器体系结构,这是我不想使用的(我是否必须使用注意机制?)

基本上,我用过


这个模型正在训练,但与没有注意模型的模型相比,我的损失相当大。

注意的全部要点是,不同语言中的词序是不同的,因此在解码目标语言中的第5个单词时,可能需要注意第3个单词(或第3个单词的编码)在源语言中,因为这些是相互对应的单词。这就是为什么您经常看到编码器-解码器结构使用注意力的原因

如果我理解正确,你是在做下一个单词预测吗?在这种情况下,使用注意力可能仍然有意义,因为下一个单词可能高度依赖于过去的单词4步骤

所以基本上你需要的是:

rnn:接收形状
MBxnIP的
输入
和形状
MBxnhid的
隐藏
,并输出形状
MBxnhid的
h

h, next_hidden = rnn(input, hidden)
注意:它按照
h
和最后一个
h\u last
的顺序,通过给每一个权重
w
来决定它们的重要性

w = attention(hs, h_last)
其中,
w
为形状
序列号x MB x 1
hs
为形状
序列号x MB x nhid
h\u last
为形状
MB x nhid

h, next_hidden = rnn(input, hidden)
现在,通过
w
hs
进行称重:

h_att = torch.sum(w*hs, dim=0) #shape MB x n_hid
现在的重点是,您需要为每个时间步骤执行以下操作:

h_att_list = []
h_list = []
hidden = hidden_init
for word in embedded_words:
    h, hidden = rnn(word, hidden)
    h_list.append(h)
    h_att = attention(torch.stack(h_list), h)
    h_att_list.append(h_att)

然后你可以在
h_att_list

上应用解码器(可能需要一个MLP,而不仅仅是一个线性变换),我理解你的问题,但要理解你的代码并找到损失没有减少的原因有点困难。此外,还不清楚为什么要将RNN的最后一个隐藏状态与每个时间步的所有隐藏状态进行比较

请注意,如果您以正确的方式使用,则特定的技巧/机制非常有用。 你尝试使用注意力机制的方式,我不确定这是不是正确的方式。所以,不要期望因为你在模型中使用了注意技巧,你会得到好的结果!!你应该想一想,为什么注意力机制会给你想要的任务带来好处


你没有明确提到你的目标是什么?因为您已经指出了一个包含语言建模代码的repo,所以我猜任务是:给定一个令牌序列,预测下一个令牌

我在代码中看到的一个可能的问题是:在emb:
循环中的
for item中,您将始终使用嵌入作为每个LSTM层的输入,因此对我来说,使用堆叠的LSTM没有意义


现在,让我首先回答您的问题,然后逐步演示如何构建所需的NN体系结构

我是否需要使用编码器-解码器体系结构来使用注意机制

编码器-解码器体系结构被称为序列到序列的学习,广泛应用于许多生成任务,例如机器翻译。您的问题的答案是否定的,您不需要使用任何特定的神经网络架构来使用注意机制


图中显示的结构有点含糊不清,但应该易于实现。由于我不清楚您的执行情况,我正试图引导您找到更好的执行方式。在下面的讨论中,我假设我们正在处理文本输入

比如说,我们有一个shape
16 x 10
的输入,其中
16
batch\u size
10
seq\u len
。我们可以假设在一个小批量中有16个句子,每个句子的长度是10

batch_size, vocab_size = 16, 100
mat = np.random.randint(vocab_size, size=(batch_size, 10))
input_var = Variable(torch.from_numpy(mat))
这里,
100
可被视为词汇表大小。需要注意的是在我提供的整个示例中,我假设
batch_size
是所有相应张量/变量的第一维度

现在,让我们嵌入输入变量

embedding = nn.Embedding(100, 50)
embed = embedding(input_var)
嵌入后,我们得到一个形状变量
16 x 10 x 50
,其中
50
是嵌入大小

现在,让我们定义一个两层单向LSTM,每层有100个隐藏单元

rnns = nn.ModuleList()
nlayers, input_size, hidden_size = 2, 50, 100
for i in range(nlayers):
    input_size = input_size if i == 0 else hidden_size
    rnns.append(nn.LSTM(input_size, hidden_size, 1, batch_first=True))
然后,我们可以将输入输入到这个2层LSTM以获得输出

sent_variable = embed
outputs, hid = [], []
for i in range(nlayers):
    if i != 0:
        sent_variable = F.dropout(sent_variable, p=0.3, training=True)
    output, hidden = rnns[i](sent_variable)
    outputs.append(output)
    hid.append(hidden[0].squeeze(0))
    sent_variable = output

rnn_out = torch.cat(outputs, 2)
hid = torch.cat(hid, 1)
现在,您可以简单地使用
hid
来预测下一个单词。我建议你那样做。这里,
hid
的形状是
batch\u size x(num\u layers*hidden\u size)

但是,由于您希望使用注意来计算最后一个隐藏状态与LSTM层生成的每个隐藏状态之间的软对齐分数,所以让我们这样做

sent_variable = embed
hid, con = [], []
for i in range(nlayers):
    if i != 0:
        sent_variable = F.dropout(sent_variable, p=0.3, training=True)
    output, hidden = rnns[i](sent_variable)
    sent_variable = output

    hidden = hidden[0].squeeze(0) # batch_size x hidden_size
    hid.append(hidden)
    weights = torch.bmm(output[:, 0:-1, :], hidden.unsqueeze(2)).squeeze(2)  
    soft_weights = F.softmax(weights, 1)  # batch_size x seq_len
    context = torch.bmm(output[:, 0:-1, :].transpose(1, 2), soft_weights.unsqueeze(2)).squeeze(2)
    con.append(context)

hid, con = torch.cat(hid, 1), torch.cat(con, 1)
combined = torch.cat((hid, con), 1)
这里,我们计算最后一个状态与每个时间步的所有状态之间的软对齐分数。然后我们计算一个上下文向量,它只是所有隐藏状态的线性组合。我们将它们组合成一个表示形式

请注意,我已从
输出
输出[:,0:-1,:]
中删除了上次隐藏状态,因为您正在与上次隐藏状态本身进行比较

最后的
组合
表示存储在每一层生成的最后隐藏状态和上下文向量。您可以直接使用此表示来预测下一个单词

decoder = nn.Linear(nlayers * hidden_size * 2, vocab_size)
dec_out = decoder(combined)
预测下一个单词是直截了当的,使用简单的线性层就可以了


编辑:我们可以做以下操作来预测下一个单词

decoder = nn.Linear(nlayers * hidden_size * 2, vocab_size)
dec_out = decoder(combined)
这里,
dec\u out
的形状是
batch\u size x vocab\u size
。现在,我们可以计算负对数似然损失,这将用于以后的反向传播

在计算负对数前
criterion = nn.NLLLoss()
loss = criterion(dec_out, target)
print(loss)
Variable containing:
 4.6278
[torch.FloatTensor of size 1]