代码
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
torch.manual_seed(1)
# 1) 准备数据
def prepare_sentence(seq, to_ix):
idx = [to_ix[w] for w in seq]
return torch.tensor(idx, dtype=torch.long)
training_data = [
("触诊 心尖 搏动 正常".split(), ["检查", "身体结构", "指标", "特别修饰词"]),
("触诊 心尖部 无 震颤".split(), ["检查", "身体结构", "否定", "患者症状"])
]
word_to_ix = {}
for sen, tag in training_data:
for word in sen:
if word not in word_to_ix:
word_to_ix[word] = len(word_to_ix)
print("word_to_ix = ", word_to_ix)
tag_to_ix = {'检查': 0, "身体结构": 3, "指标": 2, "特别修饰词": 1, "否定": 4, "患者症状": 5}
# 2) 建立模型
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_embedding = nn.Embedding(vocab_size, embedding_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):
return (
torch.zeros(1, 1, self.hidden_dim),
torch.zeros(1, 1, self.hidden_dim)
)
def forward(self, sentence):
embeds = self.word_embedding(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
## train model
# build model
model = LSTMTagger(EMBEDDING_DIM, HIDDEN_DIM, len(word_to_ix), len(tag_to_ix))
# loss func
loss_function = nn.NLLLoss()
# optimizer
optimizer = optim.SGD(model.parameters(), lr=0.1)
with torch.no_grad():
inputs = prepare_sentence(training_data[0][0], word_to_ix)
tag_score = model(inputs)
print("before_tag_score = ", tag_score)
for epoch in range(300):
for sentence, tags in training_data:
# 模型初始化为0
model.zero_grad()
# 每一条新句子需要清除之前的hidden state
model.hidden = model.init_hidden()
# 送入数据
sentence_in = prepare_sentence(sentence, word_to_ix)
# loss, -》 optim
tag_score = model(sentence_in)
right_score = prepare_sentence(tag, tag_to_ix)
loss = loss_function(tag_score, right_score)
loss.backward()
optimizer.step()
if epoch % 50 == 0:
print('loss = ', loss)
# print('tag = ', tag)
# print('right_score = ', right_score)
with torch.no_grad():
# inputs = prepare_sentence(training_data[1][0], word_to_ix)
inputs = prepare_sentence(['触诊', '心尖部', '无', '触诊'], word_to_ix)
tag_score = model(inputs)
# print('\n句子:', training_data[1][0])
# print('\n句子标签:', training_data[1][1])
print("\nafter_tag_score = ", tag_score)
max_ix = torch.max(tag_score, 1)
print('max_ix = ', max_ix)
结果
word_to_ix = {'触诊': 0, '心尖': 1, '搏动': 2, '正常': 3, '心尖部': 4, '无': 5, '震颤': 6}
before_tag_score = tensor([[-1.7210, -1.8784, -1.7632, -1.7896, -1.6580, -1.9715],
[-1.6827, -1.9438, -1.7760, -1.8080, -1.6085, -1.9842],
[-1.7364, -2.1280, -1.7931, -1.6536, -1.4783, -2.1290],
[-1.8069, -2.1224, -1.7809, -1.5439, -1.5314, -2.1385]])
loss = tensor(1.7865, grad_fn=<NllLossBackward>)
loss = tensor(1.7541, grad_fn=<NllLossBackward>)
loss = tensor(1.2348, grad_fn=<NllLossBackward>)
loss = tensor(1.1837, grad_fn=<NllLossBackward>)
loss = tensor(0.7289, grad_fn=<NllLossBackward>)
loss = tensor(0.6032, grad_fn=<NllLossBackward>)
loss = tensor(0.3175, grad_fn=<NllLossBackward>)
loss = tensor(0.2376, grad_fn=<NllLossBackward>)
loss = tensor(0.1546, grad_fn=<NllLossBackward>)
loss = tensor(0.1176, grad_fn=<NllLossBackward>)
loss = tensor(0.0933, grad_fn=<NllLossBackward>)
loss = tensor(0.0729, grad_fn=<NllLossBackward>)
after_tag_score = tensor([[-0.2807, -4.9555, -4.9554, -2.0038, -6.1763, -2.3669],
[-4.0278, -5.3399, -5.0695, -0.0902, -3.3343, -3.8284],
[-7.4119, -6.1997, -6.2174, -3.9869, -0.0544, -3.5133],
[-0.2036, -4.9543, -4.8859, -2.1326, -5.3734, -3.0698]])
max_ix = (tensor([-0.2807, -0.0902, -0.0544, -0.2036]), tensor([0, 3, 4, 0]))