Hec*_*zos 4 python lstm pytorch
我正在尝试https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html中提供的示例,但我使用的是 LSTM 模型而不是 RNN。该数据集由不同的名称(不同大小)及其对应的语言(语言总数为18种)组成,目标是训练一个模型,给定某个名称输出其所属的语言。
我现在的问题是:
(#characters of name, #target classes)
但我只想获取形状(1,#target of classes)
,以便确定每个名称对应于哪个类。我试图只得到最后一行,但结果非常糟糕。class LSTM(nn.Module):
def __init__(self, embedding_dim, hidden_dim, vocab_size, tagset_size):
super(LSTM, self).__init__()
self.hidden_dim = hidden_dim
self.word_embeddings = nn.Embedding(vocab_size, embedding_dim)
# The LSTM takes word embeddings as inputs, and outputs hidden states
# with dimensionality hidden_dim.
self.lstm = nn.LSTM(embedding_dim, hidden_dim)
# The linear layer that maps from hidden state space to tag space
self.hidden2tag = nn.Linear(hidden_dim, tagset_size)
self.softmax = nn.LogSoftmax(dim = 1)
def forward(self, word):
embeds = self.word_embeddings(word)
lstm_out, _ = self.lstm(embeds.view(len(word), 1, -1))
tag_space = self.hidden2tag(lstm_out.view(len(word), -1))
tag_scores = self.softmax(tag_space)
return tag_scores
def initHidden(self):
return Variable(torch.zeros(1, self.hidden_dim))
Run Code Online (Sandbox Code Playgroud)
lstm = LSTM(n_embedding_dim,n_hidden,n_characters,n_categories)
optimizer = torch.optim.SGD(lstm.parameters(), lr=learning_rate)
criterion = nn.NLLLoss()
def train(category_tensor, line_tensor):
# i.e. line_tensor = tensor([37, 4, 14, 13, 19, 0, 17, 0, 10, 8, 18]) and category_tensor = tensor([11])
optimizer.zero_grad()
output = lstm(line_tensor)
loss = criterion(output[-1:], category_tensor) # VERY BAD
loss.backward()
optimizer.step()
return output, loss.data.item()
Run Code Online (Sandbox Code Playgroud)
其中line_tensor
是可变大小(取决于每个名称的大小)并且 是字符与其在字典中的索引之间的映射
让我们一步步深入研究解决方案
根据您的问题陈述,您将必须使用 LSTM 进行分类,而不是使用典型的标记。LSTM 在一定的时间步长内展开,这就是循环模型的输入和输出维度为
batch size X time steps X input size
batch size X time steps X hidden size
现在既然你想用它来分类,你有两个选择:
因此,我们 LSTM 模型的输入是每个 LSTM 时间步长作为一个字符输入的名称,输出将是与其语言相对应的类。
我们这里又有两个选择。
不会。嵌入层通常用于学习单词的良好向量表示。但在字符模型的情况下,输入是字符而不是单词,因此添加嵌入层没有帮助。字符可以直接编码为数字,嵌入层在捕获不同字符之间的关系方面作用很小。您仍然可以使用嵌入层,但我坚信它不会有帮助。
玩具角色LSTM模型代码
import numpy as np
import torch
import torch.nn as nn
# Model architecture
class Recurrent_Model(nn.Module):
def __init__(self, output_size, time_steps=10):
super(Recurrent_Model, self).__init__()
self.time_steps = time_steps
self.lstm = nn.LSTM(1,32, bidirectional=True, num_layers=2)
self.linear = nn.Linear(32*2*time_steps, output_size)
def forward(self, x):
lstm_out, _ = self.lstm(x)
return self.linear(lstm_out.view(-1,32*2*self.time_steps))
# Sample input and output
names = ['apple', 'dog', 'donkey', "elephant", "hippopotamus"]
lang = [0,1,2,1,0]
def pad_sequence(name, max_len=10):
x = np.zeros((len(name), max_len))
for i, name in enumerate(names):
for j, c in enumerate(name):
if j >= max_len:
break
x[i,j] = ord(c)
return torch.FloatTensor(x)
x = pad_sequence(names)
x = torch.unsqueeze(x, dim=2)
y = torch.LongTensor(lang)
model = Recurrent_Model(3)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), 0.01)
for epoch in range(500):
model.train()
output = model(x)
loss = criterion(output, y)
print (f"Train Loss: {loss.item()}")
optimizer.zero_grad()
loss.backward()
optimizer.step()
Run Code Online (Sandbox Code Playgroud)
那么如何确保您的模型架构没有错误或正在学习。正如 Andrej karpathy 所说,在小数据集上过度拟合模型,如果过度拟合,那么我们就可以了。