美文网首页
LSTM做词性标注

LSTM做词性标注

作者: IT_小马哥 | 来源:发表于2020-01-10 11:15 被阅读0次

    训练数据的预处理、

    • 创建一个word_to_ix
      训练数据是有监督的,将句子切分为列表,每个单词对应一个词性。
    training_data = [
        ("The dog ate the apple".split(), ["DET", "NN", "V", "DET", "NN"]), # 前边是单词,后边是词性
        ("Everybody read that book".split(), ["NN", "V", "DET", "NN"])
    ]
    word_to_ix = {}
    for sent, tags in training_data:
        for word in sent:
            if word not in word_to_ix:
                word_to_ix[word] = len(word_to_ix)
    print(word_to_ix)
    

    创建的word_to_ix:

    {'The': 0, 'dog': 1, 'ate': 2, 'the': 3, 'apple': 4, 'Everybody': 5, 'read': 6, 'that': 7, 'book': 8}
    

    神经网络的搭建

    • 这里用的是LSTM
    # 实际中通常使用更大的维度如32维, 64维.
    # 这里我们使用小的维度, 为了方便查看训练过程中权重的变化.
    EMBEDDING_DIM = 6
    HIDDEN_DIM = 6
    
    class LSTMTagger(nn.Module):
        def __init__(self, embedding_dim, hidden_dim, vocab_size, tagset_size):
            super(LSTMTagger, self).__init__()
            self.hidden_dim = hidden_dim
    
            self.word_embeddings = nn.Embedding(vocab_size, embedding_dim)
    
            # LSTM以word_embeddings作为输入, 输出维度为 hidden_dim 的隐藏状态值
            self.lstm = nn.LSTM(embedding_dim, hidden_dim)
    
            # 线性层将隐藏状态空间映射到标注空间
            self.hidden2tag = nn.Linear(hidden_dim, tagset_size)
            self.hidden = self.init_hidden()
    
        def init_hidden(self):
            # 一开始并没有隐藏状态所以我们要先初始化一个
            # 各个维度的含义是 (num_layers, minibatch_size, hidden_dim)
            return (torch.zeros(1, 1, self.hidden_dim),
                    torch.zeros(1, 1, self.hidden_dim))
    
        def forward(self, sentence):
            embeds = self.word_embeddings(sentence)
            lstm_out, self.hidden = self.lstm(
                embeds.view(len(sentence), 1, -1), self.hidden)
            tag_space = self.hidden2tag(lstm_out.view(len(sentence), -1))
            tag_scores = F.log_softmax(tag_space, dim=1)
            return tag_scores
    

    初始化神经网络

    model = LSTMTagger(EMBEDDING_DIM, HIDDEN_DIM, len(word_to_ix), len(tag_to_ix))
    

    损失函数选择

    loss_function = nn.NLLLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.1)
    

    训练

    • 先准备一个将词或者词性转换为tensor的函数
    def prepare_sequence(seq, to_ix):
        idxs = [to_ix[w] for w in seq]
        return torch.tensor(idxs, dtype=torch.long)
    
    • 然后开始训练
    for epoch in range(300):
        for sentence , tags in training_data:
            
            # 清空梯度
            model.zero_grad()
            
            #情空lstm历史状态
            
            model.hidden = model.init_hidden()
            
            #准备网络输入,将其变为词索引的tensor类型数据
            
            sentence_in = prepare_sequence(sentence, word_to_ix)
            targets = prepare_sequence(tags, tag_to_ix)
            
            # 向前传播
            tag_scores = model(sentence_in)
            
            # 第四步,损失函数。更细梯度
            loss = loss_function(tag_scores, targets)
            # 反向传播
            loss.backward()
    
            # 更新参数
            optimizer.step()
    

    测试效果

    with torch.no_grad():
        inputs = prepare_sequence(training_data[0][0], word_to_ix)# S输入测试样例,The dog ate the apple
        tag_scores = model(inputs)
     
        print(tag_scores) # 查看得分,最高的下标是  0 1 2 0 1
    

    句子是 "the dog ate the apple", i,j 表示对于单词 i, 标签 j 的得分.
    我们采用得分最高的标签作为预测的标签. 从下面的输出我们可以看到, 预测得
    到的结果是0 1 2 0 1. 因为 索引是从0开始的, 因此第一个值0表示第一行的
    最大值, 第二个值1表示第二行的最大值, 以此类推. 所以最后的结果是 DET
    NOUN VERB DET NOUN, 整个序列都是正确的!

    • 输出的结果,可以发现概率最大的下标为 0 1 2 0 1
    
    tensor([[-0.0726, -2.9010, -4.1978],
            [-4.0754, -0.1101, -2.4391],
            [-3.4370, -2.0435, -0.1764],
            [-0.0322, -4.1292, -4.1580],
            [-4.2778, -0.0268, -4.3764]])
    

    相关文章

      网友评论

          本文标题:LSTM做词性标注

          本文链接:https://www.haomeiwen.com/subject/sfepactx.html