导入所需要的包
import math
import torchtext
import torch
import torch.nn as nn
from torch import Tensor
from torch.nn.utils.rnn import pad_sequence
from torch.utils.data import DataLoader
from collections import Counter
from torchtext.vocab import Vocab
from torch.nn import TransformerEncoder, TransformerDecoder, TransformerEncoderLayer, TransformerDecoderLayer
import io
import time
import pandas as pd
import numpy as np
import pickle
import tqdm
import sentencepiece as spm
torch.manual_seed(0)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# print(torch.cuda.get_device_name(0))
获取并行数据集
我们将使用从JParaCrawl![http://www.kecl.ntt.co.jp/icl/lirg/jparacrawl]]下载的日语-英语并行数据集,该数据集被描述为“NTT创建的最大的公开可用的英语-日语并行语料库”。它主要是通过抓取网络并自动对齐平行句子创建的。
# 导入pandas库
import pandas as pd
# 使用pandas读取文件,文件路径为'./zh-ja/zh-ja.bicleaner05.txt'
# 文件使用制表符(\t)作为分隔符,使用python引擎来解析文件,无表头
df = pd.read_csv('./zh-ja/zh-ja.bicleaner05.txt', sep='\\t', engine='python', header=None)
# 将第三列(索引为2)的值转换为列表,存储在变量trainen中
trainen = df[2].values.tolist()#[:10000]
# 将第四列(索引为3)的值转换为列表,存储在变量trainja中
trainja = df[3].values.tolist()#[:10000]
# 移除列表trainen和trainja中索引为5972的元素
# trainen.pop(5972)
# trainja.pop(5972)
在导入所有日语和英语对应项之后,我删除了数据集中的最后一个数据,因为它有一个缺失的值。总的来说,trainen和trainja中的句子数量都是5,973,071,然而,出于学习目的,通常建议在一次使用所有数据之前对数据进行采样并确保一切正常工作,以节省时间。
准备标记器
与英语或其他按字母顺序排列的语言不同,日语句子不包含空格来分隔单词。我们可以使用JParaCrawl提供的标记器,它是使用sentencepece为日语和英语创建的,您可以访问JParaCrawl网站下载它们
en_tokenizer = spm.SentencePieceProcessor(model_file='enja_spm_models/spm.en.nopretok.model')
ja_tokenizer = spm.SentencePieceProcessor(model_file='enja_spm_models/spm.ja.nopretok.model')
加载标记器之后,您可以测试它们,例如,通过执行下面的代码。
en_tokenizer.encode("All residents aged 20 to 59 years who live in Japan must enroll in public pension system.", out_type='str')
ja_tokenizer.encode("年金 日本に住んでいる20歳~60歳の全ての人は、公的年金制度に加入しなければなりません。", out_type='str')
建立TorchText词汇对象并将句子转换为Torch张量
使用标记器和原始句子,然后构建从TorchText导入的Vocab对象。根据数据集的大小和计算能力,这个过程可能需要几秒钟或几分钟。不同的标记器也会影响构建词汇所需的时间,我尝试了其他几个日语标记器,但sensenepece似乎工作得很好,对我来说足够快。
# 导入Counter类用于统计词频
from collections import Counter
# 导入Vocab类用于创建词汇表
from some_module import Vocab # 假设Vocab类是从some_module导入的
# 定义一个函数,用于构建词汇表
def build_vocab(sentences, tokenizer):
# 创建一个Counter对象,用于统计词频
counter = Counter()
# 遍历所有句子
for sentence in sentences:
# 使用分词器对句子进行编码,并更新词频统计
counter.update(tokenizer.encode(sentence, out_type=str))
# 返回一个Vocab对象,包含词频统计和特殊标记
return Vocab(counter, specials=['<unk>', '<pad>', '<bos>', '<eos>'])
# 使用训练集中的日语句子和日语分词器构建日语词汇表
ja_vocab = build_vocab(trainja, ja_tokenizer)
# 使用训练集中的英语句子和英语分词器构建英语词汇表
en_vocab = build_vocab(trainen, en_tokenizer)
# 导入torch库,用于处理张量
import torch
# 定义一个函数,用于处理数据
def data_process(ja, en):
# 创建一个空列表,用于存储处理后的数据
data = []
# 使用zip函数将日语和英语句子配对遍历
f