如何在NLP上使用pytorch实现丢失?

如何在NLP上使用pytorch实现丢失?,nlp,lstm,dimension,loss,cross-entropy,Nlp,Lstm,Dimension,Loss,Cross Entropy,我正在用Pytork研究NLP,它只是一个简单的玩具项目(只是生成文本)。当我在网上引用一些示例代码时,遇到了一个我无法理解的问题 以下是代码(一些代码已被省略,尚未完成): LSTM模型(utils.py) main.py 所以,我不明白的是,为什么张量logits(main.py末尾的代码)必须被转置 登录的形状和标签为: logits : torch.Size([16, 19, 10002]) # [batch_size, setence_length, vocab_size] label

我正在用Pytork研究NLP,它只是一个简单的玩具项目(只是生成文本)。当我在网上引用一些示例代码时,遇到了一个我无法理解的问题

以下是代码(一些代码已被省略,尚未完成):

  • LSTM模型(utils.py)
  • main.py
  • 所以,我不明白的是,为什么张量
    logits
    (main.py末尾的代码)必须被转置

    登录的形状和标签为:

    logits : torch.Size([16, 19, 10002]) # [batch_size, setence_length, vocab_size]
    label : torch.Size([16, 19])         # [batch_size, setence_length]
    
    在我看来,要用交叉熵来计算损失,标签的形状和数据的形状必须是相同的维度,但事实并非如此。(标签形状:[批次大小、设置长度]->[批次大小、设置长度、声音大小])

    我怎么能理解呢?为什么它会起作用

    我在下面的网站上引用了! :
    https://machinetalk.org/2019/02/08/text-generation-with-pytorch/

    nn.CrossEntropyLoss()
    不接受一个热向量。相反,它接受类值。因此,您的登录和目标将不具有相同的维度。Logits必须是维度
    (num\u示例,vocab\u大小)
    ,但标签只需包含真实类的索引,这样它的形状将是
    (num\u示例)
    而不是
    (num\u示例,vocab\u大小)
    。只有在输入一个热编码向量时,才需要该形状

    至于为什么需要转置logits向量,
    nn.CrossEntropyLoss()
    希望logits向量的维度为
    (批次大小、数量类、损失大小)
    ,其中损失大小是每个批次中的令牌数

    if __name__=="__main__":
       
        """ 데이터 불러오기.
        """
        corpus, word2id, id2word, weight = load_data()
        corpus = torch.LongTensor(corpus)
        
        """ 하이퍼 파라미터.
        """
        # 훈련
        epochs = 10
        learning_rate = 0.003
        batch_size = 16   
        hidden_size = 32 # lstm hidden 값 차원수 
        gradients_norm=5 # 기울기 클리핑.
    
        # 문장 
        seq_size=len(corpus[0])        # 문장 1개 길이.
        embedding_size=len(weight[0]) # 임베딩 벡터 사이즈.
        vocab_size = len(word2id)
        
        # 테스트
        # initial_words=['I', 'am']
        predict_top_k=5
        checkpoint_path='./checkpoint'
            
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        
        print('# corpus size : {} / vocab_size : {}'.format(len(corpus), vocab_size))
        print('# batch size : {}  / num of cell : {}'.format(batch_size, hidden_size))
        print("# 디바이스      : ", device)
    
        print('-'*30+"데이터 불러오기 및 하이퍼 파라미터 설정 분할 완료.")
    
        """ data/label 분할
        """
        c = corpus.numpy() # corpus가 Tensor 형태이므로 정상적인 slicing을 위해 numpy 형태로 바꾸어준다.
        data, label = make_data_label(c)
        
        dataset = CommentDataset(data, label)
        dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
    
        print('-'*30 + "Data Loader 준비 완료.")
        
        """ Model 정의 및 생성.
        """    
        net = RNNModule(vocab_size, seq_size,
                        embedding_size, hidden_size)
        net = net.to(device)
    
        loss_f = nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)
        
        for batch_idx, sample in enumerate(dataloader) :
            data, label = sample
            data = data.to(device)
            label = label.to(device)
            
            state_h, state_c = net.zero_state(batch_size) # initial h, c
            state_h = state_h.to(device)
            state_c = state_c.to(device)
            
            logits, (state_h, state_c) = net.forward(data, (state_h, state_c))
            
            print(logits.transpose(1, 2).size())        
            print(label.size())        
            
            loss = loss_f(logits.transpose(1, 2), label)
    
            loss.backward()
            optimizer.step()
        
            break
    
    logits : torch.Size([16, 19, 10002]) # [batch_size, setence_length, vocab_size]
    label : torch.Size([16, 19])         # [batch_size, setence_length]