代码实现
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
def tri_gramizer(test_sentence):
trigrams = [ ([test_sentence[i], test_sentence[i+1]], test_sentence[i+2]) for i in range(len(test_sentence) - 2) ]
vocab = set(test_sentence)
word_to_ix = { word: i for i, word in enumerate(vocab) }
print('The vocab length:', len(vocab))
return trigrams, vocab, word_to_ix
class NGramLanguageModeler(nn.Module):
def __init__(self, vocab_size, embedding_dim, context_size):
super(NGramLanguageModeler, self).__init__()
self.embeddings = nn.Embedding(vocab_size, embedding_dim)
self.linear1 = nn.Linear(context_size * embedding_dim, 128)
self.linear2 = nn.Linear(128, vocab_size)
def forward(self, inputs):
embeds = self.embeddings(inputs).view((1, -1))
out = F.relu(self.linear1(embeds))
out = self.linear2(out)
return out
def train(trigrams, vocab, word_to_ix):
print('Training...')
CONTEXT_SIZE = 2
EMBEDDING_DIM = 10
losses = []
loss_function = nn.CrossEntropyLoss()
model = NGramLanguageModeler(len(vocab), EMBEDDING_DIM, CONTEXT_SIZE)
optimizer = optim.SGD(model.parameters(), lr=0.001)
for epoch in range(1000):
print(f'epoch: {epoch}')
total_loss = 0
for context, target in trigrams:
context_idxs = torch.LongTensor(list(map(lambda w: word_to_ix[w], context)))
model.zero_grad()
out = model(context_idxs)
loss = loss_function(out, torch.LongTensor([word_to_ix[target]]))
loss.backward()
optimizer.step()
total_loss += loss.item()
losses.append(total_loss)
print('Finished')
torch.save(model.state_dict(), 'model_state_dict.pth')
return model, losses
def plot_losses(losses):
plt.figure()
plt.plot(losses)
def predict(input_data, model):
first_word, second_word = input_data
if first_word not in vocab or second_word not in vocab:
print('Unknown word')
return '-1'
input_tensor = torch.LongTensor([word_to_ix[first_word], word_to_ix[second_word]])
predict_idx = torch.argmax(model(input_tensor)).item()
predict_word = list(vocab)[predict_idx]
print('input words:', first_word, second_word)
print('predicted word:', predict_word)
return predict_word
if __name__ == '__main__':
test_sentence = """When forty winters shall besiege thy brow,
And dig deep trenches in thy beauty's field,
Thy youth's proud livery so gazed on now,
Will be a totter'd weed of small worth held:
Then being asked, where all thy beauty lies,
Where all the treasure of thy lusty days;
To say, within thine own deep sunken eyes,
Were an all-eating shame, and thriftless praise.
How much more praise deserv'd thy beauty's use,
If thou couldst answer 'This fair child of mine
Shall sum my count, and make my old excuse,'
Proving his beauty by succession thine!
This were to be new made when thou art old,
And see thy blood warm when thou feel'st it cold.""".split()
trigrams, vocab, word_to_ix = tri_gramizer(test_sentence)
CONTEXT_SIZE = 2
EMBEDDING_DIM = 10
model = NGramLanguageModeler(len(vocab), EMBEDDING_DIM, CONTEXT_SIZE)
model.load_state_dict(torch.load('model_state_dict.pth'))
input_data = ['When', 'forty']
word = predict(input_data, model)
参考文章:深度学习新手必学:使用 Pytorch 搭建一个 N-Gram 模型