LSTM做词性标注

2020-01-10  本文已影响0人  IT_小马哥

训练数据的预处理、

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}

神经网络的搭建

# 实际中通常使用更大的维度如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)

训练

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, 整个序列都是正确的!


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]])
上一篇 下一篇

猜你喜欢

热点阅读