data_loader.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. from config import *
  2. from utils import *
  3. import torch.utils.data as data
  4. from torch.nn.utils.rnn import pad_sequence
  5. import json
  6. import torch
  7. from model import get_padding_mask,get_subsequent_mask
  8. class Dataset(data.Dataset):
  9. def __init__(self,type="train"):
  10. super().__init__()
  11. if type == 'train':
  12. file_path = TRAIN_SAMPLE_PATH
  13. elif type == 'val':
  14. file_path = VAL_SAMPLE_PATH
  15. # 读取文件
  16. with open(file_path, encoding='utf-8') as file:
  17. self.lines = json.loads(file.read())
  18. # 词表引入
  19. _, self.en_vocab2id = get_vocab('en')
  20. _, self.zh_vocab2id = get_vocab('zh')
  21. def __len__(self):
  22. return len(self.lines)
  23. def __getitem__(self, index):
  24. en_text, zh_text = self.lines[index]
  25. source = [self.en_vocab2id.get(v.lower(), UNK_ID) for v in divided_en(en_text)] # 英文转换成编号
  26. # 原代码没有过滤Jieba返回的纯空白token,空格不在中文词表中,
  27. # 因此会在训练和验证时被错误地转换为<unk>。
  28. # target = [self.zh_vocab2id.get(v.lower(), UNK_ID) for v in divided_zh(zh_text)]
  29. # 数据映射改进:与data_processor.py生成词表时的规则保持一致,
  30. # 只过滤空格、制表符等纯空白token,正常的中文、英文名称和标点均保留。
  31. target = [
  32. self.zh_vocab2id.get(v.lower(), UNK_ID)
  33. for v in divided_zh(zh_text)
  34. if v.strip()
  35. ] # 中文转换成编号
  36. return source, target, zh_text
  37. #数据对齐和整理
  38. #因为每个批次中不同的句子长度不一致,需要把一个批次中的所有句子的长度处理成一样的长度
  39. def collate_fn(self, batch):
  40. #利用 * 号操作符,可以将元组解压为列表
  41. batch_src, batch_tgt, tgt_text = zip(*batch)
  42. #处理encoder的输入
  43. src_x = pad_sequence([torch.LongTensor(src) for src in batch_src], True, PAD_ID)
  44. src_mask = get_padding_mask(src_x, PAD_ID)
  45. #处理decoder的输入
  46. tgt_x = [torch.LongTensor([SOS_ID] + tgt) for tgt in batch_tgt]
  47. tgt_x = pad_sequence(tgt_x, True, PAD_ID)
  48. tgt_pad_mask = get_padding_mask(tgt_x, PAD_ID)
  49. tgt_subsqueent_mask = get_subsequent_mask(tgt_x.size(1))
  50. tgt_mask = tgt_pad_mask | tgt_subsqueent_mask
  51. tgt_mask = tgt_mask != 0
  52. #处理标签
  53. tgt_y = [torch.LongTensor(tgt+[EOS_ID]) for tgt in batch_tgt]
  54. tgt_y = pad_sequence(tgt_y, True, PAD_ID)
  55. return src_x, src_mask, tgt_x, tgt_mask, tgt_y, tgt_text
  56. if __name__ == '__main__':
  57. val = Dataset('train')
  58. loader = data.DataLoader(val, batch_size=2, collate_fn=val.collate_fn)
  59. print(next(iter(loader)))