.. _sec_text_preprocessing:
Preprocessamento de Texto
=========================
Nós revisamos e avaliamos ferramentas estatísticas e desafios de
previsão para dados de sequência. Esses dados podem assumir várias
formas. Especificamente, como vamos nos concentrar em em muitos
capítulos do livro, text é um dos exemplos mais populares de dados de
sequência. Por exemplo, um artigo pode ser visto simplesmente como uma
sequência de palavras ou mesmo uma sequência de caracteres. Para
facilitar nossos experimentos futuros com dados de sequência, vamos
dedicar esta seção para explicar as etapas comuns de pré-processamento
para texto. Normalmente, essas etapas são:
1. Carregar o texto como strings na memória.
2. Dividir as strings em tokens (por exemplo, palavras e caracteres).
3. Construir uma tabela de vocabulário para mapear os tokens divididos
em índices numéricos.
4. Converter o texto em sequências de índices numéricos para que possam
ser facilmente manipulados por modelos.
.. raw:: html
.. raw:: html
.. code:: python
#@save
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt',
'090b5e7e70c295757f55df93cb0a180b9691891a')
def read_time_machine(): #@save
"""Load the time machine dataset into a list of text lines."""
with open(d2l.download('time_machine'), 'r') as f:
lines = f.readlines()
return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]
lines = read_time_machine()
print(f'# text lines: {len(lines)}')
print(lines[0])
print(lines[10])
.. parsed-literal::
:class: output
Downloading ../data/timemachine.txt from http://d2l-data.s3-accelerate.amazonaws.com/timemachine.txt...
# text lines: 3221
the time machine by h g wells
twinkled and his usually pale face was flushed and animated the
.. raw:: html
.. raw:: html
.. code:: python
#@save
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt',
'090b5e7e70c295757f55df93cb0a180b9691891a')
def read_time_machine(): #@save
"""Load the time machine dataset into a list of text lines."""
with open(d2l.download('time_machine'), 'r') as f:
lines = f.readlines()
return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]
lines = read_time_machine()
print(f'# text lines: {len(lines)}')
print(lines[0])
print(lines[10])
.. parsed-literal::
:class: output
Downloading ../data/timemachine.txt from http://d2l-data.s3-accelerate.amazonaws.com/timemachine.txt...
# text lines: 3221
the time machine by h g wells
twinkled and his usually pale face was flushed and animated the
.. raw:: html
.. raw:: html
.. code:: python
#@save
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt',
'090b5e7e70c295757f55df93cb0a180b9691891a')
def read_time_machine(): #@save
"""Load the time machine dataset into a list of text lines."""
with open(d2l.download('time_machine'), 'r') as f:
lines = f.readlines()
return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]
lines = read_time_machine()
print(f'# text lines: {len(lines)}')
print(lines[0])
print(lines[10])
.. parsed-literal::
:class: output
# text lines: 3221
the time machine by h g wells
twinkled and his usually pale face was flushed and animated the
.. raw:: html
.. raw:: html
Tokenização
-----------
A seguinte função ``tokenize`` recebe uma lista (``lines``) como
entrada, onde cada lista é uma sequência de texto (por exemplo, uma
linha de texto). Cada sequência de texto é dividida em uma lista de
tokens. Um *token* é a unidade básica no texto. No fim, uma lista de
listas de tokens é retornada, onde cada token é uma string.
.. raw:: html
.. raw:: html
.. code:: python
def tokenize(lines, token='word'): #@save
"""Split text lines into word or character tokens."""
if token == 'word':
return [line.split() for line in lines]
elif token == 'char':
return [list(line) for line in lines]
else:
print('ERROR: unknown token type: ' + token)
tokens = tokenize(lines)
for i in range(11):
print(tokens[i])
.. parsed-literal::
:class: output
['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
[]
[]
[]
[]
['i']
[]
[]
['the', 'time', 'traveller', 'for', 'so', 'it', 'will', 'be', 'convenient', 'to', 'speak', 'of', 'him']
['was', 'expounding', 'a', 'recondite', 'matter', 'to', 'us', 'his', 'grey', 'eyes', 'shone', 'and']
['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
.. raw:: html
.. raw:: html
.. code:: python
def tokenize(lines, token='word'): #@save
"""Split text lines into word or character tokens."""
if token == 'word':
return [line.split() for line in lines]
elif token == 'char':
return [list(line) for line in lines]
else:
print('ERROR: unknown token type: ' + token)
tokens = tokenize(lines)
for i in range(11):
print(tokens[i])
.. parsed-literal::
:class: output
['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
[]
[]
[]
[]
['i']
[]
[]
['the', 'time', 'traveller', 'for', 'so', 'it', 'will', 'be', 'convenient', 'to', 'speak', 'of', 'him']
['was', 'expounding', 'a', 'recondite', 'matter', 'to', 'us', 'his', 'grey', 'eyes', 'shone', 'and']
['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
.. raw:: html
.. raw:: html
.. code:: python
def tokenize(lines, token='word'): #@save
"""Split text lines into word or character tokens."""
if token == 'word':
return [line.split() for line in lines]
elif token == 'char':
return [list(line) for line in lines]
else:
print('ERROR: unknown token type: ' + token)
tokens = tokenize(lines)
for i in range(11):
print(tokens[i])
.. parsed-literal::
:class: output
['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
[]
[]
[]
[]
['i']
[]
[]
['the', 'time', 'traveller', 'for', 'so', 'it', 'will', 'be', 'convenient', 'to', 'speak', 'of', 'him']
['was', 'expounding', 'a', 'recondite', 'matter', 'to', 'us', 'his', 'grey', 'eyes', 'shone', 'and']
['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
.. raw:: html
.. raw:: html
Vocabulário
-----------
O tipo de string do token é inconveniente para ser usado por modelos,
que usam entradas numéricas. Agora, vamos construir um dicionário,
também chamado de *vocabulário*, para mapear tokens de string em índices
numéricos começando em 0. Para fazer isso, primeiro contamos os tokens
exclusivos em todos os documentos do conjunto de treinamento, ou seja,
um *corpus*, e, em seguida, atribua um índice numérico a cada token
exclusivo de acordo com sua frequência. Os tokens raramente exibidos são
frequentemente removidos para reduzir a complexidade. Qualquer token que
não exista no corpus ou que tenha sido removido é mapeado em um token
especial desconhecido “