0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyTorch教程-10.5。机器翻译和数据集

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:44 次阅读

在引起人们对现代 RNN 广泛兴趣的重大突破中,有一项是统计机器翻译应用领域的重大进展 。在这里,模型以一种语言的句子呈现,并且必须预测另一种语言的相应句子。请注意,由于两种语言的语法结构不同,这里的句子可能有不同的长度,并且两个句子中相应的词可能不会以相同的顺序出现。

许多问题都具有这种在两个这样的“未对齐”序列之间进行映射的风格。示例包括从对话提示到回复或从问题到答案的映射。广义上,此类问题称为 序列到序列(seq2seq) 问题,它们是本章剩余部分和 第 11 节大部分内容的重点。

在本节中,我们将介绍机器翻译问题和我们将在后续示例中使用的示例数据集。几十年来,语言间翻译的统计公式一直很流行 (Brown等人,1990 年,Brown等人,1988 年),甚至在研究人员使神经网络方法起作用之前(这些方法通常被统称为神经机器翻译)。

首先,我们需要一些新代码来处理我们的数据。与我们在9.3 节中看到的语言建模不同,这里的每个示例都包含两个单独的文本序列,一个是源语言,另一个(翻译)是目标语言。以下代码片段将展示如何将预处理后的数据加载到小批量中进行训练。

import os
import torch
from d2l import torch as d2l

import os
from mxnet import np, npx
from d2l import mxnet as d2l

npx.set_np()

import os
from jax import numpy as jnp
from d2l import jax as d2l

No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)

import os
import tensorflow as tf
from d2l import tensorflow as d2l

10.5.1。下载和预处理数据集

首先,我们 从 Tatoeba Project 下载由双语句子对组成的英法数据集。数据集中的每一行都是一个制表符分隔的对,由一个英文文本序列和翻译后的法文文本序列组成。请注意,每个文本序列可以只是一个句子,也可以是一段多句。在这个英语翻译成法语的机器翻译问题中,英语被称为源语言,法语被称为目标语言。

class MTFraEng(d2l.DataModule): #@save
  """The English-French dataset."""
  def _download(self):
    d2l.extract(d2l.download(
      d2l.DATA_URL+'fra-eng.zip', self.root,
      '94646ad1522d915e7b0f9296181140edcf86a4f5'))
    with open(self.root + '/fra-eng/fra.txt', encoding='utf-8') as f:
      return f.read()

data = MTFraEng()
raw_text = data._download()
print(raw_text[:75])

Downloading ../data/fra-eng.zip from http://d2l-data.s3-accelerate.amazonaws.com/fra-eng.zip...
Go. Va !
Hi. Salut !
Run!    Cours !
Run!    Courez !
Who?    Qui ?
Wow!    Ça alors !

class MTFraEng(d2l.DataModule): #@save
  """The English-French dataset."""
  def _download(self):
    d2l.extract(d2l.download(
      d2l.DATA_URL+'fra-eng.zip', self.root,
      '94646ad1522d915e7b0f9296181140edcf86a4f5'))
    with open(self.root + '/fra-eng/fra.txt', encoding='utf-8') as f:
      return f.read()

data = MTFraEng()
raw_text = data._download()
print(raw_text[:75])

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

class MTFraEng(d2l.DataModule): #@save
  """The English-French dataset."""
  def _download(self):
    d2l.extract(d2l.download(
      d2l.DATA_URL+'fra-eng.zip', self.root,
      '94646ad1522d915e7b0f9296181140edcf86a4f5'))
    with open(self.root + '/fra-eng/fra.txt', encoding='utf-8') as f:
      return f.read()

data = MTFraEng()
raw_text = data._download()
print(raw_text[:75])

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

class MTFraEng(d2l.DataModule): #@save
  """The English-French dataset."""
  def _download(self):
    d2l.extract(d2l.download(
      d2l.DATA_URL+'fra-eng.zip', self.root,
      '94646ad1522d915e7b0f9296181140edcf86a4f5'))
    with open(self.root + '/fra-eng/fra.txt', encoding='utf-8') as f:
      return f.read()

data = MTFraEng()
raw_text = data._download()
print(raw_text[:75])

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

下载数据集后,我们对原始文本数据进行几个预处理步骤。例如,我们将不间断空格替换为空格,将大写字母转换为小写字母,在单词和标点符号之间插入空格。

@d2l.add_to_class(MTFraEng) #@save
def _preprocess(self, text):
  # Replace non-breaking space with space
  text = text.replace('u202f', ' ').replace('xa0', ' ')
  # Insert space between words and punctuation marks
  no_space = lambda char, prev_char: char in ',.!?' and prev_char != ' '
  out = [' ' + char if i > 0 and no_space(char, text[i - 1]) else char
      for i, char in enumerate(text.lower())]
  return ''.join(out)

text = data._preprocess(raw_text)
print(text[:80])

go .    va !
hi .    salut !
run !    cours !
run !    courez !
who ?    qui ?
wow !    ça alors !

@d2l.add_to_class(MTFraEng) #@save
def _preprocess(self, text):
  # Replace non-breaking space with space
  text = text.replace('u202f', ' ').replace('xa0', ' ')
  # Insert space between words and punctuation marks
  no_space = lambda char, prev_char: char in ',.!?' and prev_char != ' '
  out = [' ' + char if i > 0 and no_space(char, text[i - 1]) else char
      for i, char in enumerate(text.lower())]
  return ''.join(out)

text = data._preprocess(raw_text)
print(text[:80])

go .    va !
hi .    salut !
run !    cours !
run !    courez !
who ?    qui ?
wow !    ça alors !

@d2l.add_to_class(MTFraEng) #@save
def _preprocess(self, text):
  # Replace non-breaking space with space
  text = text.replace('u202f', ' ').replace('xa0', ' ')
  # Insert space between words and punctuation marks
  no_space = lambda char, prev_char: char in ',.!?' and prev_char != ' '
  out = [' ' + char if i > 0 and no_space(char, text[i - 1]) else char
      for i, char in enumerate(text.lower())]
  return ''.join(out)

text = data._preprocess(raw_text)
print(text[:80])

go .    va !
hi .    salut !
run !    cours !
run !    courez !
who ?    qui ?
wow !    ça alors !

@d2l.add_to_class(MTFraEng) #@save
def _preprocess(self, text):
  # Replace non-breaking space with space
  text = text.replace('u202f', ' ').replace('xa0', ' ')
  # Insert space between words and punctuation marks
  no_space = lambda char, prev_char: char in ',.!?' and prev_char != ' '
  out = [' ' + char if i > 0 and no_space(char, text[i - 1]) else char
      for i, char in enumerate(text.lower())]
  return ''.join(out)

text = data._preprocess(raw_text)
print(text[:80])

go .    va !
hi .    salut !
run !    cours !
run !    courez !
who ?    qui ?
wow !    ça alors !

10.5.2。代币化

与第 9.3 节中的字符级标记化不同 ,对于机器翻译,我们在这里更喜欢单词级标记化(当今最先进的模型使用更复杂的标记化技术)。以下_tokenize方法对第一个max_examples文本序列对进行分词,其中每个分词要么是一个单词,要么是一个标点符号。我们将特殊的“”标记附加到每个序列的末尾,以指示序列的结束。当模型通过生成一个接一个标记的序列标记进行预测时,“”标记的生成表明输出序列是完整的。最后,下面的方法返回两个令牌列表列表:src和tgt。具体来说,src[i]是来自ith源语言(此处为英语)的文本序列和tgt[i]目标语言(此处为法语)的文本序列。

@d2l.add_to_class(MTFraEng) #@save
def _tokenize(self, text, max_examples=None):
  src, tgt = [], []
  for i, line in enumerate(text.split('n')):
    if max_examples and i > max_examples: break
    parts = line.split('t')
    if len(parts) == 2:
      # Skip empty tokens
      src.append([t for t in f'{parts[0]} '.split(' ') if t])
      tgt.append([t for t in f'{parts[1]} '.split(' ') if t])
  return src, tgt

src, tgt = data._tokenize(text)
src[:6], tgt[:6]

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

@d2l.add_to_class(MTFraEng) #@save
def _tokenize(self, text, max_examples=None):
  src, tgt = [], []
  for i, line in enumerate(text.split('n')):
    if max_examples and i > max_examples: break
    parts = line.split('t')
    if len(parts) == 2:
      # Skip empty tokens
      src.append([t for t in f'{parts[0]} '.split(' ') if t])
      tgt.append([t for t in f'{parts[1]} '.split(' ') if t])
  return src, tgt

src, tgt = data._tokenize(text)
src[:6], tgt[:6]

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

@d2l.add_to_class(MTFraEng) #@save
def _tokenize(self, text, max_examples=None):
  src, tgt = [], []
  for i, line in enumerate(text.split('n')):
    if max_examples and i > max_examples: break
    parts = line.split('t')
    if len(parts) == 2:
      # Skip empty tokens
      src.append([t for t in f'{parts[0]} '.split(' ') if t])
      tgt.append([t for t in f'{parts[1]} '.split(' ') if t])
  return src, tgt

src, tgt = data._tokenize(text)
src[:6], tgt[:6]

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

@d2l.add_to_class(MTFraEng) #@save
def _tokenize(self, text, max_examples=None):
  src, tgt = [], []
  for i, line in enumerate(text.split('n')):
    if max_examples and i > max_examples: break
    parts = line.split('t')
    if len(parts) == 2:
      # Skip empty tokens
      src.append([t for t in f'{parts[0]} '.split(' ') if t])
      tgt.append([t for t in f'{parts[1]} '.split(' ') if t])
  return src, tgt

src, tgt = data._tokenize(text)
src[:6], tgt[:6]

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

让我们绘制每个文本序列的标记数量的直方图。在这个简单的英法数据集中,大多数文本序列的标记少于 20 个。

#@save
def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist):
  """Plot the histogram for list length pairs."""
  d2l.set_figsize()
  _, _, patches = d2l.plt.hist(
    [[len(l) for l in xlist], [len(l) for l in ylist]])
  d2l.plt.xlabel(xlabel)
  d2l.plt.ylabel(ylabel)
  for patch in patches[1].patches:
    patch.set_hatch('/')
  d2l.plt.legend(legend)

show_list_len_pair_hist(['source', 'target'], '# tokens per sequence',
            'count', src, tgt);

poYBAGR9N2iABw1YAAF3AJUP1Cw291.svg

#@save
def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist):
  """Plot the histogram for list length pairs."""
  d2l.set_figsize()
  _, _, patches = d2l.plt.hist(
    [[len(l) for l in xlist], [len(l) for l in ylist]])
  d2l.plt.xlabel(xlabel)
  d2l.plt.ylabel(ylabel)
  for patch in patches[1].patches:
    patch.set_hatch('/')
  d2l.plt.legend(legend)

show_list_len_pair_hist(['source', 'target'], '# tokens per sequence',
            'count', src, tgt);

poYBAGR9N2iABw1YAAF3AJUP1Cw291.svg

#@save
def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist):
  """Plot the histogram for list length pairs."""
  d2l.set_figsize()
  _, _, patches = d2l.plt.hist(
    [[len(l) for l in xlist], [len(l) for l in ylist]])
  d2l.plt.xlabel(xlabel)
  d2l.plt.ylabel(ylabel)
  for patch in patches[1].patches:
    patch.set_hatch('/')
  d2l.plt.legend(legend)

show_list_len_pair_hist(['source', 'target'], '# tokens per sequence',
            'count', src, tgt);

poYBAGR9N2iABw1YAAF3AJUP1Cw291.svg

#@save
def show_list_len_pair_hist(legend, xlabel, ylabel, xlist, ylist):
  """Plot the histogram for list length pairs."""
  d2l.set_figsize()
  _, _, patches = d2l.plt.hist(
    [[len(l) for l in xlist], [len(l) for l in ylist]])
  d2l.plt.xlabel(xlabel)
  d2l.plt.ylabel(ylabel)
  for patch in patches[1].patches:
    patch.set_hatch('/')
  d2l.plt.legend(legend)

show_list_len_pair_hist(['source', 'target'], '# tokens per sequence',
            'count', src, tgt);

poYBAGR9N2iABw1YAAF3AJUP1Cw291.svg

10.5.3。固定长度的加载序列

回想一下,在语言建模中,每个示例序列(一个句子的一部分或多个句子的跨度)都有固定的长度。这是由第 9.3 节num_steps中的(时间步数或标记数)参数指定的。在机器翻译中,每个示例都是一对源文本序列和目标文本序列,其中这两个文本序列可能具有不同的长度。

为了计算效率,我们仍然可以通过截断和填充一次处理一小批文本序列。假设同一个小批量中的每个序列都应该具有相同的长度 num_steps。如果文本序列少于num_steps标记,我们将继续在其末尾附加特殊的“”标记,直到其长度达到num_steps. num_steps否则,我们将通过仅获取其第一个标记并丢弃其余标记来截断文本序列。这样,每个文本序列将具有相同的长度,以相同形状的小批量加载。此外,我们还记录了不包括填充标记的源序列长度。我们稍后将介绍的某些模型将需要此信息

由于机器翻译数据集由多对语言组成,我们可以分别为源语言和目标语言构建两个词汇表。使用词级标记化,词汇量将明显大于使用字符级标记化的词汇量。为了减轻这一点,在这里,我们将看上去不到2倍相同的未知数(“”)令牌视为罕见的令牌。正如我们稍后将解释的(图 10.7.1),当使用目标序列进行训练时,解码器输出(标签标记)可以是相同的解码器输入(目标标记),移动一个标记;特殊的序列开头“”标记将用作预测目标序列的第一个输入标记(图 10.7.3)。

@d2l.add_to_class(MTFraEng) #@save
def __init__(self, batch_size, num_steps=9, num_train=512, num_val=128):
  super(MTFraEng, self).__init__()
  self.save_hyperparameters()
  self.arrays, self.src_vocab, self.tgt_vocab = self._build_arrays(
    self._download())

@d2l.add_to_class(MTFraEng) #@save
def _build_arrays(self, raw_text, src_vocab=None, tgt_vocab=None):
  def _build_array(sentences, vocab, is_tgt=False):
    pad_or_trim = lambda seq, t: (
      seq[:t] if len(seq) > t else seq + [''] * (t - len(seq)))
    sentences = [pad_or_trim(s, self.num_steps) for s in sentences]
    if is_tgt:
      sentences = [[''] + s for s in sentences]
    if vocab is None:
      vocab = d2l.Vocab(sentences, min_freq=2)
    array = torch.tensor([vocab[s] for s in sentences])
    valid_len = (array != vocab['']).type(torch.int32).sum(1)
    return array, vocab, valid_len
  src, tgt = self._tokenize(self._preprocess(raw_text),
               self.num_train + self.num_val)
  src_array, src_vocab, src_valid_len = _build_array(src, src_vocab)
  tgt_array, tgt_vocab, _ = _build_array(tgt, tgt_vocab, True)
  return ((src_array, tgt_array[:,:-1], src_valid_len, tgt_array[:,1:]),
      src_vocab, tgt_vocab)

@d2l.add_to_class(MTFraEng) #@save
def __init__(self, batch_size, num_steps=9, num_train=512, num_val=128):
  super(MTFraEng, self).__init__()
  self.save_hyperparameters()
  self.arrays, self.src_vocab, self.tgt_vocab = self._build_arrays(
    self._download())

@d2l.add_to_class(MTFraEng) #@save
def _build_arrays(self, raw_text, src_vocab=None, tgt_vocab=None):
  def _build_array(sentences, vocab, is_tgt=False):
    pad_or_trim = lambda seq, t: (
      seq[:t] if len(seq) > t else seq + [''] * (t - len(seq)))
    sentences = [pad_or_trim(s, self.num_steps) for s in sentences]
    if is_tgt:
      sentences = [[''] + s for s in sentences]
    if vocab is None:
      vocab = d2l.Vocab(sentences, min_freq=2)
    array = np.array([vocab[s] for s in sentences])
    valid_len = (array != vocab['']).astype(np.int32).sum(1)
    return array, vocab, valid_len
  src, tgt = self._tokenize(self._preprocess(raw_text),
               self.num_train + self.num_val)
  src_array, src_vocab, src_valid_len = _build_array(src, src_vocab)
  tgt_array, tgt_vocab, _ = _build_array(tgt, tgt_vocab, True)
  return ((src_array, tgt_array[:,:-1], src_valid_len, tgt_array[:,1:]),
      src_vocab, tgt_vocab)

@d2l.add_to_class(MTFraEng) #@save
def __init__(self, batch_size, num_steps=9, num_train=512, num_val=128):
  super(MTFraEng, self).__init__()
  self.save_hyperparameters()
  self.arrays, self.src_vocab, self.tgt_vocab = self._build_arrays(
    self._download())

@d2l.add_to_class(MTFraEng) #@save
def _build_arrays(self, raw_text, src_vocab=None, tgt_vocab=None):
  def _build_array(sentences, vocab, is_tgt=False):
    pad_or_trim = lambda seq, t: (
      seq[:t] if len(seq) > t else seq + [''] * (t - len(seq)))
    sentences = [pad_or_trim(s, self.num_steps) for s in sentences]
    if is_tgt:
      sentences = [[''] + s for s in sentences]
    if vocab is None:
      vocab = d2l.Vocab(sentences, min_freq=2)
    array = jnp.array([vocab[s] for s in sentences])
    valid_len = (array != vocab['']).astype(jnp.int32).sum(1)
    return array, vocab, valid_len
  src, tgt = self._tokenize(self._preprocess(raw_text),
               self.num_train + self.num_val)
  src_array, src_vocab, src_valid_len = _build_array(src, src_vocab)
  tgt_array, tgt_vocab, _ = _build_array(tgt, tgt_vocab, True)
  return ((src_array, tgt_array[:,:-1], src_valid_len, tgt_array[:,1:]),
      src_vocab, tgt_vocab)

@d2l.add_to_class(MTFraEng) #@save
def __init__(self, batch_size, num_steps=9, num_train=512, num_val=128):
  super(MTFraEng, self).__init__()
  self.save_hyperparameters()
  self.arrays, self.src_vocab, self.tgt_vocab = self._build_arrays(
    self._download())

@d2l.add_to_class(MTFraEng) #@save
def _build_arrays(self, raw_text, src_vocab=None, tgt_vocab=None):
  def _build_array(sentences, vocab, is_tgt=False):
    pad_or_trim = lambda seq, t: (
      seq[:t] if len(seq) > t else seq + [''] * (t - len(seq)))
    sentences = [pad_or_trim(s, self.num_steps) for s in sentences]
    if is_tgt:
      sentences = [[''] + s for s in sentences]
    if vocab is None:
      vocab = d2l.Vocab(sentences, min_freq=2)
    array = tf.constant([vocab[s] for s in sentences])
    valid_len = tf.reduce_sum(
      tf.cast(array != vocab[''], tf.int32), 1)
    return array, vocab, valid_len
  src, tgt = self._tokenize(self._preprocess(raw_text),
               self.num_train + self.num_val)
  src_array, src_vocab, src_valid_len = _build_array(src, src_vocab)
  tgt_array, tgt_vocab, _ = _build_array(tgt, tgt_vocab, True)
  return ((src_array, tgt_array[:,:-1], src_valid_len, tgt_array[:,1:]),
      src_vocab, tgt_vocab)

10.5.4。读取数据集

最后,我们定义get_dataloader返回数据迭代器的方法。

@d2l.add_to_class(MTFraEng) #@save
def get_dataloader(self, train):
  idx = slice(0, self.num_train) if train else slice(self.num_train, None)
  return self.get_tensorloader(self.arrays, train, idx)

让我们从英法数据集中读取第一个小批量。

data = MTFraEng(batch_size=3)
src, tgt, src_valid_len, label = next(iter(data.train_dataloader()))
print('source:', src.type(torch.int32))
print('decoder input:', tgt.type(torch.int32))
print('source len excluding pad:', src_valid_len.type(torch.int32))
print('label:', label.type(torch.int32))

source: tensor([[ 83, 174,  2,  3,  4,  4,  4,  4,  4],
    [ 84, 32, 91,  2,  3,  4,  4,  4,  4],
    [144, 174,  0,  3,  4,  4,  4,  4,  4]], dtype=torch.int32)
decoder input: tensor([[ 3,  6,  0,  4,  5,  5,  5,  5,  5],
    [ 3, 108, 112, 84,  2,  4,  5,  5,  5],
    [ 3, 87,  0,  4,  5,  5,  5,  5,  5]], dtype=torch.int32)
source len excluding pad: tensor([4, 5, 4], dtype=torch.int32)
label: tensor([[ 6,  0,  4,  5,  5,  5,  5,  5,  5],
    [108, 112, 84,  2,  4,  5,  5,  5,  5],
    [ 87,  0,  4,  5,  5,  5,  5,  5,  5]], dtype=torch.int32)

data = MTFraEng(batch_size=3)
src, tgt, src_valid_len, label = next(iter(data.train_dataloader()))
print('source:', src.astype(np.int32))
print('decoder input:', tgt.astype(np.int32))
print('source len excluding pad:', src_valid_len.astype(np.int32))
print('label:', label.astype(np.int32))

source: [[84 5 2 3 4 4 4 4 4]
 [84 5 2 3 4 4 4 4 4]
 [59 9 2 3 4 4 4 4 4]]
decoder input: [[ 3 108  6  2  4  5  5  5  5]
 [ 3 105  6  2  4  5  5  5  5]
 [ 3 203  0  4  5  5  5  5  5]]
source len excluding pad: [4 4 4]
label: [[108  6  2  4  5  5  5  5  5]
 [105  6  2  4  5  5  5  5  5]
 [203  0  4  5  5  5  5  5  5]]

data = MTFraEng(batch_size=3)
src, tgt, src_valid_len, label = next(iter(data.train_dataloader()))
print('source:', src.astype(jnp.int32))
print('decoder input:', tgt.astype(jnp.int32))
print('source len excluding pad:', src_valid_len.astype(jnp.int32))
print('label:', label.astype(jnp.int32))

source: [[ 86 43  2  3  4  4  4  4  4]
 [176 165  2  3  4  4  4  4  4]
 [143 111  2  3  4  4  4  4  4]]
decoder input: [[ 3 108 183 98  2  4  5  5  5]
 [ 3  6 42  0  4  5  5  5  5]
 [ 3  6  0  4  5  5  5  5  5]]
source len excluding pad: [4 4 4]
label: [[108 183 98  2  4  5  5  5  5]
 [ 6 42  0  4  5  5  5  5  5]
 [ 6  0  4  5  5  5  5  5  5]]

data = MTFraEng(batch_size=3)
src, tgt, src_valid_len, label = next(iter(data.train_dataloader()))
print('source:', tf.cast(src, tf.int32))
print('decoder input:', tf.cast(tgt, tf.int32))
print('source len excluding pad:', tf.cast(src_valid_len, tf.int32))
print('label:', tf.cast(label, tf.int32))

source: tf.Tensor(
[[ 92 115  2  3  4  4  4  4  4]
 [155 168  2  3  4  4  4  4  4]
 [ 86 121  2  3  4  4  4  4  4]], shape=(3, 9), dtype=int32)
decoder input: tf.Tensor(
[[ 3 37  6  2  4  5  5  5  5]
 [ 3  6 192  2  4  5  5  5  5]
 [ 3 108 202 30  2  4  5  5  5]], shape=(3, 9), dtype=int32)
source len excluding pad: tf.Tensor([4 4 4], shape=(3,), dtype=int32)
label: tf.Tensor(
[[ 37  6  2  4  5  5  5  5  5]
 [ 6 192  2  4  5  5  5  5  5]
 [108 202 30  2  4  5  5  5  5]], shape=(3, 9), dtype=int32)

下面我们展示了一对由上述方法处理的源序列和目标序列_build_arrays(以字符串格式)。

@d2l.add_to_class(MTFraEng) #@save
def build(self, src_sentences, tgt_sentences):
  raw_text = 'n'.join([src + 't' + tgt for src, tgt in zip(
    src_sentences, tgt_sentences)])
  arrays, _, _ = self._build_arrays(
    raw_text, self.src_vocab, self.tgt_vocab)
  return arrays

src, tgt, _, _ = data.build(['hi .'], ['salut .'])
print('source:', data.src_vocab.to_tokens(src[0].type(torch.int32)))
print('target:', data.tgt_vocab.to_tokens(tgt[0].type(torch.int32)))

source: ['hi', '.', '', '', '', '', '', '', '']
target: ['', 'salut', '.', '', '', '', '', '', '']

@d2l.add_to_class(MTFraEng) #@save
def build(self, src_sentences, tgt_sentences):
  raw_text = 'n'.join([src + 't' + tgt for src, tgt in zip(
    src_sentences, tgt_sentences)])
  arrays, _, _ = self._build_arrays(
    raw_text, self.src_vocab, self.tgt_vocab)
  return arrays

src, tgt, _, _ = data.build(['hi .'], ['salut .'])
print('source:', data.src_vocab.to_tokens(src[0].astype(np.int32)))
print('target:', data.tgt_vocab.to_tokens(tgt[0].astype(np.int32)))

source: ['hi', '.', '', '', '', '', '', '', '']
target: ['', 'salut', '.', '', '', '', '', '', '']

@d2l.add_to_class(MTFraEng) #@save
def build(self, src_sentences, tgt_sentences):
  raw_text = 'n'.join([src + 't' + tgt for src, tgt in zip(
    src_sentences, tgt_sentences)])
  arrays, _, _ = self._build_arrays(
    raw_text, self.src_vocab, self.tgt_vocab)
  return arrays

src, tgt, _, _ = data.build(['hi .'], ['salut .'])
print('source:', data.src_vocab.to_tokens(src[0].astype(jnp.int32)))
print('target:', data.tgt_vocab.to_tokens(tgt[0].astype(jnp.int32)))

source: ['hi', '.', '', '', '', '', '', '', '']
target: ['', 'salut', '.', '', '', '', '', '', '']

@d2l.add_to_class(MTFraEng) #@save
def build(self, src_sentences, tgt_sentences):
  raw_text = 'n'.join([src + 't' + tgt for src, tgt in zip(
    src_sentences, tgt_sentences)])
  arrays, _, _ = self._build_arrays(
    raw_text, self.src_vocab, self.tgt_vocab)
  return arrays

src, tgt, _, _ = data.build(['hi .'], ['salut .'])
print('source:', data.src_vocab.to_tokens(tf.cast(src[0], tf.int32)))
print('target:', data.tgt_vocab.to_tokens(tf.cast(tgt[0], tf.int32)))

source: ['hi', '.', '', '', '', '', '', '', '']
target: ['', 'salut', '.', '', '', '', '', '', '']

10.5.5。概括

在自然语言处理中,机器翻译是指将代表源语言文本字符串的序列自动映射到代表目标语言中合理翻译的字符串的任务。使用词级标记化,词汇量将明显大于使用字符级标记化,但序列长度会短得多。为了减轻大词汇量,我们可以将不常见的标记视为一些“未知”标记。我们可以截断和填充文本序列,以便它们都具有相同的长度以加载到小批量中。现代实现通常将具有相似长度的序列存储起来,以避免在填充上浪费过多的计算。

10.5.6。练习

max_examples在 方法中尝试不同的参数值_tokenize。这如何影响源语言和目标语言的词汇量?

某些语言(例如中文和日文)中的文本没有字界指示符(例如,空格)。对于这种情况,词级标记化仍然是一个好主意吗?为什么或者为什么不?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据集
    +关注

    关注

    4

    文章

    1179

    浏览量

    24356
  • pytorch
    +关注

    关注

    2

    文章

    763

    浏览量

    12836
收藏 人收藏

    评论

    相关推荐

    机器翻译三大核心技术原理 | AI知识科普

    ,应用场景越多,需要的规则也越来越多,规则之间的冲突也逐渐出现。于是很多科研学家开始思考,是否能让机器自动从数据库里学习相应的规则,1993年IBM提出基于词的统计翻译模型标志着第二代机器翻译
    发表于 07-06 10:30

    机器翻译三大核心技术原理 | AI知识科普 2

    本帖最后由 讯飞开放平台 于 2018-7-6 10:47 编辑 神经机器翻译讲完了基于规则的机器翻译和基于统计的机器翻译,接下来我们来看下基于端到端的神经机器翻译。神经
    发表于 07-06 10:46

    神经机器翻译的方法有哪些?

    目前,神经机器翻译(NMT)已经成为在学术界和工业界最先进的机器翻译方法。最初的这种基于编码器-解码器架构的机器翻译系统都针对单个语言对进行翻译。近期的工作开始探索去扩展这种办法以支持
    发表于 11-23 12:14

    从冷战到深度学习_机器翻译历史不简单

    实现高质量机器翻译的梦想已经存在了很多年,很多科学家都为这一梦想贡献了自己的时间和心力。从早期的基于规则的机器翻译到如今广泛应用的神经机器翻译机器翻译的水平不断提升,已经能满足很多场
    发表于 06-01 14:47 1043次阅读
    从冷战到深度学习_<b class='flag-5'>机器翻译</b>历史不简单

    阿里巴巴机器翻译在跨境电商场景下的应用和实践

    摘要:  本文将与大家分享机器翻译相关背景知识,再深入介绍机器翻译在阿里生态中的具体应用实践,介绍基于机器翻译技术搭建的一套完善的电商多语言解决方案,最后将会从技术角度介绍阿里机器翻译
    发表于 07-31 17:22 225次阅读
    阿里巴巴<b class='flag-5'>机器翻译</b>在跨境电商场景下的应用和实践

    从冷战到深度学习,机器翻译历史不简单!

    深度学习机器翻译 实现高质量机器翻译的梦想已经存在了很多年,很多科学家都为这一梦想贡献了自己的时间和心力。从早期的基于规则的机器翻译到如今广泛应用的神经机器翻译
    发表于 09-17 09:23 311次阅读

    机器翻译的真实水平如何,梦想与现实的距离到底有多远?

    近年来,随着计算机性能的提高,云计算、大数据机器学习等相关技术迅速发展,人工智能再度崛起,机器翻译重新成为人们关注的焦点。一时间,机器翻译系统如雨后春笋般涌现,各种报道随之呈井喷式爆
    的头像 发表于 03-22 14:08 3842次阅读

    换个角度来聊机器翻译

    同时期国内科技企业在机器翻译上的进展也非常迅速,以语音和语义理解见长的科大讯飞在2014年国际口语翻译大赛IWSLT上获得中英和英中两个翻译方向的全球第一名,在2015年又在由美国国家标准技术研究院组织的
    的头像 发表于 04-24 13:55 3227次阅读
    换个角度来聊<b class='flag-5'>机器翻译</b>

    机器翻译走红的背后是什么

    未来需要新的算法和语义层面的综合性突破,促进机器翻译产品的迭代和产业全面升级。
    发表于 07-14 10:02 928次阅读

    基于模板驱动的神经机器翻译模型综述

    基于模板驱动的神经机器翻译模型综述
    发表于 06-24 15:31 16次下载

    基于DNN与规则学习的机器翻译算法综述

    基于DNN与规则学习的机器翻译算法综述
    发表于 06-29 15:44 33次下载

    基于句子级上下文的神经机器翻译综述

    基于句子级上下文的神经机器翻译综述
    发表于 06-29 16:26 64次下载

    PyTorch教程10.5机器翻译和数据

    电子发烧友网站提供《PyTorch教程10.5机器翻译和数据集.pdf》资料免费下载
    发表于 06-05 15:14 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>10.5</b>之<b class='flag-5'>机器翻译</b><b class='flag-5'>和数据</b>集

    PyTorch教程10.7之用于机器翻译的编码器-解码器Seq2Seq

    电子发烧友网站提供《PyTorch教程10.7之用于机器翻译的编码器-解码器Seq2Seq.pdf》资料免费下载
    发表于 06-05 18:14 0次下载
    <b class='flag-5'>PyTorch</b>教程10.7之用于<b class='flag-5'>机器翻译</b>的编码器-解码器Seq2Seq

    机器翻译研究进展

    成为主流,如神经网络机器翻译。神经网络机器翻译机器从大量数据中自动学习翻译知识,而不依靠人类专家撰写规则,可以显著提升
    的头像 发表于 07-06 11:19 420次阅读
    <b class='flag-5'>机器翻译</b>研究进展