【问题标题】:pytorch LSTM to map series of feature vectors to their labelspytorch LSTM 将一系列特征向量映射到它们的标签
【发布时间】:2021-05-24 14:06:08
【问题描述】:

目前我输入了形状为 (50, 25) 的 X,其中有 50 个特征向量,每个向量有 25 个维度。 X的数据例如如下:

X = [[0. 0. 0. ... 1. 1. 1.]
 [0. 0. 0. ... 1. 1. 1.]
 [0. 0. 0. ... 1. 1. 1.]
 ...
 [0. 0. 0. ... 1. 1. 1.]
 [0. 0. 0. ... 1. 1. 1.]
 [0. 0. 0. ... 1. 1. 1.]]

输出标签 y 是 [0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],长度为 50。即每个特征向量都有一个标签,对应于 y 中的一个元素。

如何构建 pytorch LSTM,将输入对象重塑为 3 维,并正确解释输出对象?非常感谢您提前提供的帮助。

目前我有一个这样的 LSTM 模板,因为我的输入已经是数字,我想摆脱编码器/解码器部分,对吗?

class RNNModel(nn.Module):
    """Container module with an encoder, a recurrent module, and a decoder."""

    def __init__(self, rnn_type, ntoken, ninp, nhid, nlayers, dropout=0, tie_weights=False):
        super(RNNModel, self).__init__()
        self.drop = nn.Dropout(dropout)
        self.ntoken = ntoken 
        self.decoder = nn.Linear(nhid, self.ntoken)
        if rnn_type in ['LSTM', 'GRU']:
            self.rnn = getattr(nn, rnn_type)(ninp, nhid, nlayers, dropout=dropout)
        else:
            try:
                nonlinearity = {'RNN_TANH': 'tanh', 'RNN_RELU': 'relu'}[rnn_type]
            except KeyError:
                raise ValueError( """An invalid option for `--model` was supplied,
                                 options are ['LSTM', 'GRU', 'RNN_TANH' or 'RNN_RELU']""")
            self.rnn = nn.RNN(ninp, nhid, nlayers, nonlinearity=nonlinearity, dropout=dropout)

        self.init_weights()

        self.rnn_type = rnn_type
        self.nhid = nhid
        self.nlayers = nlayers

    def init_weights(self):
        initrange = 0.1
        nn.init.zeros_(self.decoder.weight)
        nn.init.uniform_(self.decoder.weight, -initrange, initrange)

    def forward(self, input, hidden):
        emb = self.drop(input)
        emb = emb.transpose(1, 0)

        output, hidden = self.rnn(emb, hidden) #output of shape (length, batchsize, nhid)
        output = self.drop(output)
        output = output[-1, :, :] #shape (batchsize, nhid)

        decoded = self.decoder(output) #shape (batchsize, ntoken)
        return F.log_softmax(decoded, dim=1), hidden 

    def init_hidden(self, bsz):
        weight = next(self.parameters())
        if self.rnn_type == 'LSTM':
            return (weight.new_zeros(self.nlayers, bsz, self.nhid),
                    weight.new_zeros(self.nlayers, bsz, self.nhid))
        else:
            return weight.new_zeros(self.nlayers, bsz, self.nhid)

目前我写的火车是

X = X.reshape((1, 50, 25))
hidden = self.model.init_hidden(1)
for iter in range(0, self.epochs):
    data = torch.from_numpy(X)
    target = torch.LongTensor(y.reshape((1, torch.LongTensor(y).size(0))))
    self.model.zero_grad()
    self.optimizer.zero_grad()
    hidden = self.repackage_hidden(hidden)
  
    output, hidden = self.model(data.float(), hidden)   
    loss = self.criterion(output, target)
    loss.backward() 
    torch.nn.utils.clip_grad_norm_(self.model.parameters(), 0.25) 
    self.optimizer.step()
    self.model.train() 

但我得到了错误:RuntimeError: multi-target not supported at /tmp/pip-req-build-4baxydiv/aten/src/THNN/generic/ClassNLLCriterion.c:22

【问题讨论】:

    标签: machine-learning deep-learning neural-network pytorch lstm


    【解决方案1】:

    rnn 的输出形式为(长度、批量大小、nhid),基于您的标签(每个样本 1 个数字)我假设您正在进行分类,所以通常我们会给分类器(self.decoder)的输出特征最后一个时间步。在这里,我将您的 forward 方法更改为此并得到适合您标签形状的形状 (batchsize, ntoken) 的输出。

    def forward(self, input, hidden):
        emb = self.drop(self.encoder(input))
        emb = emb.transpose(1, 0) #(batchsize, length, ninp) => (length, batchsize, ninp)
    
        output, hidden = self.rnn(emb, hidden) #output of shape (length, batchsize, nhid)
        output = self.drop(output)
        output = output[-1, :, :] #shape (batchsize, nhid)
    
        decoded = self.decoder(output) #shape (batchsize, ntoken)
        return F.log_softmax(decoded, dim=1), hidden 
    

    关于摆脱 self.encoder,它是一个嵌入层,它采用一组索引并将每个索引替换为一个向量。如果您的输入包括某些东西的索引(int / long),您可以使用它,否则(它不是索引,而是一些像温度一样的浮点数,......)您应该摆脱它(因为它是错误的)。对不起,如果我的英语令人困惑。

    【讨论】:

    • 谢谢!你知道如何将我的 2D 特征向量转换为 3D 特征向量吗?每个维度的值应该是多少?这里我认为 ninp 是 25,长度是 50,但是批量大小应该是多少?我也很困惑如何使我的目标(即 y)重塑为正确的大小,以便我可以使用 loss = self.criterion(output, target)
    • 哦,也许我误解了你的问题,你问题中的 X 是一个样本还是它的每一行都是一个样本(我以为它的每一行都是一个样本)?你能告诉我你想解决什么问题吗?批量大小是指您提供给数据的样本数量。关于如何向数据添加维度,您可以使用 X.unsqueeze(dim) 与 dim 是您想要添加它的位置,例如 X.unsqueeze(dim=1) 可能将 X 从 (50, 25) 更改为 ( 50、1、25)。
    • 是的,如果我理解正确的话,它的每一行都是一个示例。基本上我只是想训练模型,最后给模型输入一个特征向量(一个样本),得到标签。我对如何为 LSTM 编写训练函数、输入形状应该是什么(从 X 转换)以及目标形状应该是什么(从 y 转换)感到困惑。我上传了上面的代码,你能看一下吗?谢谢!
    • 如果你使用嵌入层(比如你的模板),你不需要改变任何东西,它会将你的输入张量变成 (batchsize, length, ninp) 在这种情况下是 (50, 25 , ninp),然后你需要使用转置将其更改为 (length, batchsize, ninp) (只是 Torch 的约定,你可以查找它的文档),然后再将其放入 rnn。如果您不使用嵌入层并且您想将 X 的确切值放入 rnn,则使用方法 unsqueeze(-1) 将 X 转换为 (50, 25, 1),然后将 transpose(0, 1) 转换为 (25, 50, 1)(50个样本,每个样本有25个时间步,每个时间步用单个数字表示)
    • 其实特征向量只对应一个时间步,特征向量的每一维对应一个特征,这个时间步总共有25个特征。在这种情况下,配方应该是什么?很抱歉造成混淆,我对 NN 和机器学习非常陌生,感谢您的周到回答!
    猜你喜欢
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 2021-12-03
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多