Nlp 使用Pytorch生成LSTM文本
我目前正在尝试使用Pytorch使用LSTMs生成报价(字符级)。我目前在理解Pytorch中如何实现隐藏状态方面面临一些问题 一些细节: 我有一个电视连续剧中一个角色的引用列表。我正在使用字典Nlp 使用Pytorch生成LSTM文本,nlp,pytorch,lstm,Nlp,Pytorch,Lstm,我目前正在尝试使用Pytorch使用LSTMs生成报价(字符级)。我目前在理解Pytorch中如何实现隐藏状态方面面临一些问题 一些细节: 我有一个电视连续剧中一个角色的引用列表。我正在使用字典char2idx将它们转换为一个整数序列,每个字符对应一个特定的整数。我还有这个idx2char的倒数,映射是反向的 在那之后,我使用一个滑动窗口,比如说大小window\u size,以及大小step的步骤来准备数据 例如,假设序列是[1,2,3,4,5,0],其中0代表EOS字符。然后使用window
char2idx
将它们转换为一个整数序列,每个字符对应一个特定的整数。我还有这个idx2char
的倒数,映射是反向的
在那之后,我使用一个滑动窗口,比如说大小window\u size
,以及大小step
的步骤来准备数据
例如,假设序列是[1,2,3,4,5,0]
,其中0代表EOS字符。然后使用window\u size=3
和step=2
,我得到x和y的序列为:
x1 = [1, 2, 3], y1 = [2, 3, 4]
x2 = [3, 4, 5], y1 = [4, 5, 0]
x = [x1, x2], y = [y1, y2]
下一步是训练模型。我已经附上了我用来训练模型的代码
注:我没有将隐藏状态从一批传递到另一批,因为(j+1)批的第I个序列可能不是第j批的第I个序列的下一步。(这就是我使用滑动窗口帮助模型记住的原因)。有更好的方法吗
我的主要问题发生在测试期间。我测试的方法有两种
方法1:
我获取初始种子字符串,将其传递到模型中,并获得下一个字符作为预测。现在,我将其添加到起始字符串中,并将整个序列传递到模型中,而不传递隐藏状态。也就是说,我将整个序列输入到模型中,LSTM的初始隐藏状态为0,获取输出,将输出附加到序列中并重复,直到遇到EOS字符
方法2:
我获取初始种子字符串,将其传递到模型中,并获得下一个字符作为预测。现在,我只是将角色和上一个隐藏状态作为下一个输入传递,并继续这样做,直到遇到EOS角色为止
问题
class RNN(nn.Module):
def __init__(self, vocab_size, hidden_size, num_layers, dropout=0.15):
super(RNN, self).__init__()
self.vocab_size = vocab_size
self.hidden_size = hidden_size
self.num_layers = num_layers
self.embedding = nn.Embedding(vocab_size, hidden_size)
self.lstm = nn.LSTM(hidden_size, hidden_size, num_layers, dropout=dropout, batch_first=True)
self.dense1 = nn.Linear(hidden_size, hidden_size*4)
self.dense2 = nn.Linear(hidden_size*4, hidden_size*2)
self.dense3 = nn.Linear(hidden_size*2, vocab_size)
self.drop = nn.Dropout(dropout)
def forward(self, X, h=None, c=None):
if h is None:
h, c = self.init_hidden(X.size(0))
out = self.embedding(X)
out, (h, c) = self.lstm(out, (h, c))
out = self.drop(out)
out = self.dense1(out.reshape(-1, self.hidden_size)) # Reshaping it into (batch_size*seq_len, hidden_size)
out = self.dense2(out)
out = self.dense3(out)
return out, h, c
def init_hidden(self, batch_size):
num_l = self.num_layers
hidden = torch.zeros(num_l, batch_size, self.hidden_size).to(DEVICE)
cell = torch.zeros(num_l, batch_size, self.hidden_size).to(DEVICE)
return hidden, cell
培训代码:
rnn = RNN(VOCAB_SIZE, HIDDEN_SIZE, NUM_LAYERS).to(DEVICE)
optimizer = torch.optim.Adam(rnn.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()
rnn.train()
history = {}
best_loss = 100
for epoch in range(EPOCHS): #EPOCH LOOP
counter = 0
epoch_loss = 0
for x, y in train_loader: #BATCH LOOP
optimizer.zero_grad()
counter += 1
o, h, c = rnn(x)
loss = criterion(o, y.reshape(-1))
epoch_loss += loss.item()
loss.backward()
nn.utils.clip_grad_norm_(rnn.parameters(), 5) # Clipping Gradients
optimizer.step()
if counter%print_every == 0:
print(f"[INFO] EPOCH: {epoch+1}, BATCH: {counter}, TRAINING LOSS: {loss.item()}")
epoch_loss = epoch_loss/counter
history["train_loss"] = history.get("train_loss", []) + [epoch_loss]
print(f"\nEPOCH: {epoch+1} COMPLETED!\nTRAINING LOSS: {epoch_loss}\n")
方法1代码:
with torch.no_grad():
w = None
start_str = "Hey, "
x1 = quote2seq(start_str)[:-1]
while w != EOS_TOKEN:
x1 = torch.tensor(x1, device=DEVICE).unsqueeze(0)
o1, h1, c1 = rnn(x1)
p1 = F.softmax(o1, dim=1).detach()
q1 = np.argmax(p1.cpu(), axis=1)[-1].item()
w = idx2char[q1]
start_str += w
x1 = x1.tolist()[0]+ [q1]
quote = start_str.replace("<EOS>", "")
quote
带火炬的。无梯度()
w=无
start_str=“嘿,”
x1=quote2seq(开始)[:-1]
当w!=EOS_令牌时:
x1=火炬.张量(x1,设备=设备).反求(0)
o1,h1,c1=rnn(x1)
p1=F.softmax(o1,尺寸=1).detach()
q1=np.argmax(p1.cpu(),轴=1)[-1]。项()
w=idx2char[q1]
开始_str+=w
x1=x1.tolist()[0]+[q1]
quote=start\u str.replace(“,”)
引用
方法2代码:
with torch.no_grad():
w = None
start_str = "Are we back"
x1 = quote2seq(start_str)[:-1]
h1, c1 = rnn.init_hidden(1)
while w != EOS_TOKEN:
x1 = torch.tensor(x1, device=DEVICE).unsqueeze(0)
h1, c1 = h1.data, c1.data
o1, h1, c1 = rnn(x1, h1, c1)
p1 = F.softmax(o1, dim=1).detach()
q1 = np.argmax(p1.cpu(), axis=1)[-1].item()
w = idx2char[q1]
start_str += w
x1 = [q1]
quote = start_str.replace("<EOS>", "")
quote
带火炬的。无梯度()
w=无
start\u str=“我们回来了吗”
x1=quote2seq(开始)[:-1]
h1,c1=rnn.init_隐藏(1)
当w!=EOS_令牌时:
x1=火炬.张量(x1,设备=设备).反求(0)
h1,c1=h1.数据,c1.数据
o1,h1,c1=rnn(x1,h1,c1)
p1=F.softmax(o1,尺寸=1).detach()
q1=np.argmax(p1.cpu(),轴=1)[-1]。项()
w=idx2char[q1]
开始_str+=w
x1=[q1]
quote=start\u str.replace(“,”)
引用