机器翻译之数据处理

目录

1.导包 

 2.读取本地数据

3.定义函数:数据预处理 

 4.定义函数:词元化

 5.统计每句话的长度的分布情况

6. 获取词汇表

7. 截断或者填充文本序列

 8.将机器翻译的文本序列转换成小批量tensor

 9.加载数据

10.知识点个人理解


1.导包 

#导包
import os
import torch
import dltools

 2.读取本地数据

#读取本地数据
with open('./fra-eng/fra.txt', 'r', encoding='utf-8') as f:
    raw_text = f.read()  #一次读取所有数据

print(raw_text[:75])

 

Go.	Va !
Hi.	Salut !
Run!	Cours !
Run!	Courez !
Who?	Qui ?
Wow!	Ça alors !

3.定义函数:数据预处理 

#数据预处理
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)  #合并out

#测试:数据预处理
text = preprocess_nmt(raw_text)
print(text[:80])
go .	va !
hi .	salut !
run !	cours !
run !	courez !
who ?	qui ?
wow !	ça alors !

 4.定义函数:词元化

#定义函数:词元化
def tokenize_nmt(text, num_examples=None):
    """
    text:传入的数据文本
    num_examples=None:样本数量为空,判断数据集中剩余的数据量是否满足一批所取的数据量
    """
    source, target = [], []
    #以换行符号\n划分每一行
    for i, line in enumerate(text.split('\n')):
        #if num_examples  表示不是空,相当于 if num_examples != None
        if num_examples and i > num_examples:
            break
            
        #从每一行数据中 以空格键tab分割数据
        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)
source[:6], target[:6]

 

([['go', '.'],
  ['hi', '.'],
  ['run', '!'],
  ['run', '!'],
  ['who', '?'],
  ['wow', '!']],
 [['va', '!'],
  ['salut', '!'],
  ['cours', '!'],
  ['courez', '!'],
  ['qui', '?'],
  ['ça', 'alors', '!']])

 5.统计每句话的长度的分布情况

#统计每句话的长度的分布情况
def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist):
    dltools.set_figsize()  #创建一个适当的画布
    _,_,patches = dltools.plt.hist([[len(l) for l in xlist], [len(l) for l in ylist]])
    dltools.plt.xlabel(xlabel) #添加x标签
    dltools.plt.ylabel(ylabel)  #添加y标签
    for patch in patches[1].patches:  #为patches[1]的柱体添加斜线
        patch.set_hatch('/')
        
    dltools.plt.legend(legend) #添加标注
    
#测试代码:统计每句话的长度的分布情况
show_list_len_pair_hist(['source', 'target'], '# tokens per sequence', 'count', source, target)

 

6. 获取词汇表

#获取词汇表
src_vocab = dltools.Vocab(source, min_freq=2, reserved_tokens=['<pad>', '<bos>', '<eos>'])
len(src_vocab)

 10012

7. 截断或者填充文本序列

def truncate_pad(line, num_steps, padding_token):
    """
    line:传入的数据
    num_steps:子序列长度
    padding_token:需要填充的词元
    """
    if len(line) > num_steps:
        return line[:num_steps]  #太长就截断
    #太短就补充
    return line + [padding_token] * (num_steps - len(line))  #填充

#测试
#source[0]表示英文单词
truncate_pad(src_vocab[source[0]], 10, src_vocab['<pad>'])

 [47, 4, 1, 1, 1, 1, 1, 1, 1, 1]

 8.将机器翻译的文本序列转换成小批量tensor

def build_array_nmt(lines, vocab, num_steps):
    #通过vocab拿到line的索引
    lines = [vocab[l] for l in lines]
    #每个序列结束之后+一个'eos'
    lines = [l + [vocab['eos']] for l in lines]
    #对每一行文本 截断或者填充文本序列,再转化为tensor
    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

 9.加载数据

def load_data_nmt(batch_size, num_steps, num_examples=600):
    # 需要返回数据集的迭代器和词表
    text = preprocess_nmt(raw_text)
    source, target = tokenize_nmt(text, num_examples)
    src_vocab = dltools.Vocab(source, min_freq=2, reserved_tokens=['<pad>', '<bos>', '<eos>'])
    tgt_vocab = dltools.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 = dltools.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
X: tensor([[17, 20,  4,  0,  1,  1,  1,  1],
        [ 7, 84,  4,  0,  1,  1,  1,  1]], dtype=torch.int32)
X的有效长度: tensor([4, 4])
Y: tensor([[ 11,  61, 144,   4,   0,   1,   1,   1],
        [  6,  33,  17,   4,   0,   1,   1,   1]], dtype=torch.int32)
Y的有效长度: tensor([5, 5])

10.知识点个人理解

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值