| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import jieba
- import re
- from config import *
- import torch
- from model import get_padding_mask,get_subsequent_mask
- import sacrebleu
- # 中文分词
- def divided_zh(sentence):
- return jieba.lcut(sentence)
- # 英文分词
- def divided_en(sentence):
- # 使用正则表达式匹配单词和标点符号
- pattern = r'\w+|[^\w\s]'
- return re.findall(pattern, sentence)
- def get_vocab(lang='en'):
- if lang == 'en':
- file_path = EN_VOCAB_PATH
- elif lang == 'zh':
- file_path = ZH_VOCAB_PATH
-
- with open(file_path, encoding='utf-8') as file:
- lines = file.read()
- id2vocab = lines.split('\n')
- vocab2id = {v:k for k,v in enumerate(id2vocab)}
- return id2vocab, vocab2id
- #逐字生成预测值
- def batch_greedy_decode(model, src_x, src_mask, max_len=MAX_LEN):
- src_x= src_x.to(device)
- src_mask=src_mask.to(device)
- #获取中文词表
- zh_id2vocab, _ = get_vocab('zh')
- #encoder 输出
- memory = model.encoder(src_x, src_mask)
- # 初始化decoder 输入
- prob_x = torch.tensor([[SOS_ID]] * src_x.size(0))
- prob_x = prob_x.to(device)
- for _ in range(max_len):
- #推理时mask
- # prob_mask = get_padding_mask(prob_x, PAD_ID).to(device)
- prob_pad_mask = get_padding_mask(prob_x, PAD_ID).to(device)
- prob_subsqueent_mask = get_subsequent_mask(prob_x.size(1)).to(device)
- prob_mask = prob_pad_mask | prob_subsqueent_mask
- prob_mask = prob_mask != 0
-
- decoder_output = model.decoder(prob_x, prob_mask, memory, src_mask) # shape 3,1,512
- output = model.generator(decoder_output[:, -1, :]) #shape 3,19
- output = torch.softmax(output,dim=-1)
- predict = torch.argmax(output, dim=-1, keepdim=True)
- #把之前的值拼到一起
- prob_x = torch.concat([prob_x, predict], dim=-1)
- #如果预测的当前值是eos,则表示整个序列结束
- if torch.all(predict==EOS_ID).item():
- break
- #把预测出的索引值,转成对应的词
- batch_prob_text = []
- for prob in prob_x:
- prob_text = []
- for prob_id in prob:
- if prob_id == SOS_ID:
- continue
- if prob_id == EOS_ID:
- break
- prob_text.append(zh_id2vocab[prob_id])
- batch_prob_text.append(''.join(prob_text))
- return batch_prob_text
- def bleu_score(hyp, refs):
- bleu = sacrebleu.corpus_bleu(hyp, refs, tokenize='zh')
- return round(bleu.score, 2)
- if __name__ == '__main__':
- target = '我喜欢读书'
- vocabs = divided_zh(target)
- _, zh_vocab2id = get_vocab('zh')
- tokens = [zh_vocab2id.get(v, UNK_ID) for v in vocabs]
- print(tokens)
|