import os import torch from d2l import torch as d2l # @save d2l.DATA_HUB['fra-eng'] = (d2l.DATA_URL + 'fra-eng.zip', '94646ad1522d915e7b0f9296181140edcf86a4f5') # 下载数据集 # @save def read_data_nmt(): """载入“英语-法语”数据集""" data_dir = d2l.download_extract('fra-eng') with open(os.path.join(data_dir, 'fra.txt'), 'r', encoding='utf-8') as f: return f.read() raw_text = read_data_nmt() print(raw_text[:75]) # 预处理数据集 def preprocess_nmt(text): def no_space(char, prev_char): return char in set(',.!?') and prev_char != ' ' # 使用空格替换不间断空格 # 使用小写字母替换大写字母 text = text.replace('\u202f', ' ').replace('\xa0', ' ').lower() # 在单词和标点符号之间插入空格 out = [' ' + char if i > 0 and no_space(char, text[i - 1]) else char for i, char in enumerate(text)] return ''.join(out) text = preprocess_nmt(raw_text) print(text[:88]) # 次元化,找出每一个词所对应的法语词 def tokenize_nmt(text, num_example=None): """词元化“英语-法语”数据数据集""" source, target = [], [] for i, line in enumerate(text.split('\n')): if num_example and i > num_example: break parts = line.split('\t') if len(parts) == 2: source.append(parts[0].split(' ')) target.append(parts[1].split(' ')) return source, target source, target = tokenize_nmt(text) print(source[:6], target[:6]) def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist): """绘制列表长度对的直方图""" d2l.set_figsize() _, _, patches = d2l.plt.hist( [[len(l) for l in xlist], [len(l) for l in ylist]]) print(d2l.plt.xlabel(xlabel)) print(d2l.plt.ylabel(ylabel)) for patch in patches[1].patches: patch.set_hatch('/') d2l.plt.legend(legend) d2l.plt.show() show_list_len_pair_hist(['source', 'target'], '# tokens per sequence', 'count', source, target) # 由于机器翻译数据集由语言对组成, 因此我们可以分别为源语言和目标语言构建两个词表。 # 使用单词级词元化时,词表大小将明显大于使用字符级词元化时的词表大小。 为了缓解这一问题, # 这里我们将出现次数少于2次的低频率词元 视为相同的未知(“<unk>”)词元。 # 除此之外,我们还指定了额外的特定词元, 例如在小批量时用于将序列填充到相同长度的填充词元(“<pad>”), 以及序列的开始词元(“<bos>”)和结束词元(“<eos>”)。 # 这些特殊词元在自然语言处理任务中比较常用。 src_vocab = d2l.Vocab(source, min_freq=2, reserved_tokens=['<pad>', '<bos>', '<eos>']) print(len(src_vocab)) # 由于样本具有固定长度,所以我们需要截断或者填充文本 def truncate_pad(line, num_steps, padding_token): if len(line) > num_steps: return line[:num_steps] return line + [padding_token] * (num_steps - len(line)) print(truncate_pad(src_vocab[source[0]], 10, src_vocab['<pad>'])) # 转成小批量进行训练 def build_array_nmt(lines, vocab, num_steps): lines = [vocab[l] for l in lines] lines = [l + [vocab['<eos>']] for l in lines] array = torch.tensor([truncate_pad(l, num_steps, vocab['<pad>']) for l in lines]) valid_len = (array != vocab['<pad>']).type(torch.int32).sum(1) return array, valid_len # 训练模型 def load_data_nmt(batch_size, num_steps, num_examples=600): text = preprocess_nmt(read_data_nmt()) source, target = tokenize_nmt(text, num_examples) src_vocab = d2l.Vocab(source, min_freq=2, reserved_tokens=['<pad>', '<bos>', '<eos>']) tgt_vocab = d2l.Vocab(target, min_freq=2, reserved_tokens=['<pad>', '<bos>', '<eos>']) src_array, src_valid_len = build_array_nmt(source, src_vocab, num_steps) tgt_array, tgt_valid_len = build_array_nmt(target, tgt_vocab, num_steps) data_arrays = (src_array, src_valid_len, tgt_array, tgt_valid_len) data_iter = d2l.load_array(data_arrays, batch_size) return data_iter, src_vocab, tgt_vocab train_iter, src_vocab, tgt_vocab = load_data_nmt(batch_size=2, num_steps=8) for X, X_valid_len, Y, Y_valid_len in train_iter: print('X:', X.type(torch.int32)) print('X的有效长度:', X_valid_len) print('Y:', Y.type(torch.int32)) print('Y的有效长度:', Y_valid_len) break
标签:vocab,nmt,text,len,num,机器翻译,数据,d2l From: https://www.cnblogs.com/o-Sakurajimamai-o/p/17694372.html