.. 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
.. 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
Mã hóa
------
Hàm ``tokenize`` sau lấy một danh sách (``lines``) làm đầu vào, trong đó
mỗi phần tử là một chuỗi văn bản (ví dụ, một dòng văn bản). Mỗi chuỗi
văn bản được chia thành danh sách các tokens. Một \* token\* là đơn vị
cơ bản trong văn bản. Cuối cùng, một danh sách các danh sách token được
trả về, trong đó mỗi mã thông báo là một chuỗi.
.. 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
Từ vựng
-------
Loại chuỗi của mã thông báo bất tiện khi được sử dụng bởi các mô hình,
lấy đầu vào số. Bây giờ chúng ta hãy xây dựng một từ điển, thường được
gọi là *vocabulary* là tốt, để ánh xạ chuỗi mã thông báo thành các chỉ
số số bắt đầu từ 0. Để làm như vậy, trước tiên chúng ta đếm các mã thông
báo duy nhất trong tất cả các tài liệu từ bộ đào tạo, cụ thể là một \*
corpus\*, sau đó gán một chỉ số số cho mỗi mã thông báo duy nhất theo
tần số của nó. Hiếm khi xuất hiện thẻ thường được loại bỏ để giảm sự
phức tạp. Bất kỳ mã thông báo nào không tồn tại trong corpus hoặc đã
được gỡ bỏ đều được ánh xạ thành một mã thông báo không xác định đặc
biệt “”. Chúng tôi tùy chọn thêm một danh sách các token dành riêng,
chẳng hạn như “” cho padding, “” để trình bày phần đầu cho một chuỗi, và
“” cho phần cuối của một chuỗi.
.. code:: python
class Vocab: #@save
"""Vocabulary for text."""
def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
if tokens is None:
tokens = []
if reserved_tokens is None:
reserved_tokens = []
# Sort according to frequencies
counter = count_corpus(tokens)
self._token_freqs = sorted(counter.items(), key=lambda x: x[1],
reverse=True)
# The index for the unknown token is 0
self.idx_to_token = [''] + reserved_tokens
self.token_to_idx = {token: idx
for idx, token in enumerate(self.idx_to_token)}
for token, freq in self._token_freqs:
if freq < min_freq:
break
if token not in self.token_to_idx:
self.idx_to_token.append(token)
self.token_to_idx[token] = len(self.idx_to_token) - 1
def __len__(self):
return len(self.idx_to_token)
def __getitem__(self, tokens):
if not isinstance(tokens, (list, tuple)):
return self.token_to_idx.get(tokens, self.unk)
return [self.__getitem__(token) for token in tokens]
def to_tokens(self, indices):
if not isinstance(indices, (list, tuple)):
return self.idx_to_token[indices]
return [self.idx_to_token[index] for index in indices]
@property
def unk(self): # Index for the unknown token
return 0
@property
def token_freqs(self): # Index for the unknown token
return self._token_freqs
def count_corpus(tokens): #@save
"""Count token frequencies."""
# Here `tokens` is a 1D list or 2D list
if len(tokens) == 0 or isinstance(tokens[0], list):
# Flatten a list of token lists into a list of tokens
tokens = [token for line in tokens for token in line]
return collections.Counter(tokens)
Chúng tôi xây dựng một từ vừ bằng cách sử dụng tập dữ liệu máy thời gian
làm cơ thể. Sau đó, chúng tôi in vài mã thông báo thường xuyên đầu tiên
với các chỉ số của chúng.
.. raw:: html
.. raw:: html
.. code:: python
vocab = Vocab(tokens)
print(list(vocab.token_to_idx.items())[:10])
.. parsed-literal::
:class: output
[('', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]
.. raw:: html
.. raw:: html
.. code:: python
vocab = Vocab(tokens)
print(list(vocab.token_to_idx.items())[:10])
.. parsed-literal::
:class: output
[('', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]
.. raw:: html
.. raw:: html
.. code:: python
vocab = Vocab(tokens)
print(list(vocab.token_to_idx.items())[:10])
.. parsed-literal::
:class: output
[('', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]
.. raw:: html
.. raw:: html
Bây giờ chúng ta có thể chuyển đổi mỗi dòng văn bản thành một danh sách
các chỉ số.
.. raw:: html
.. raw:: html
.. code:: python
for i in [0, 10]:
print('words:', tokens[i])
print('indices:', vocab[tokens[i]])
.. parsed-literal::
:class: output
words: ['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
indices: [1, 19, 50, 40, 2183, 2184, 400]
words: ['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
indices: [2186, 3, 25, 1044, 362, 113, 7, 1421, 3, 1045, 1]
.. raw:: html
.. raw:: html
.. code:: python
for i in [0, 10]:
print('words:', tokens[i])
print('indices:', vocab[tokens[i]])
.. parsed-literal::
:class: output
words: ['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
indices: [1, 19, 50, 40, 2183, 2184, 400]
words: ['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
indices: [2186, 3, 25, 1044, 362, 113, 7, 1421, 3, 1045, 1]
.. raw:: html
.. raw:: html
.. code:: python
for i in [0, 10]:
print('words:', tokens[i])
print('indices:', vocab[tokens[i]])
.. parsed-literal::
:class: output
words: ['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
indices: [1, 19, 50, 40, 2183, 2184, 400]
words: ['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
indices: [2186, 3, 25, 1044, 362, 113, 7, 1421, 3, 1045, 1]
.. raw:: html
.. raw:: html
Đặt tất cả mọi thứ lại với nhau
-------------------------------
Sử dụng các hàm trên, chúng ta đóng gói mọi thứ vào hàm
``load_corpus_time_machine``, trả về ``corpus``, danh sách các chỉ số
token và ``vocab``, từ vựng của cơ thể máy thời gian. Các sửa đổi chúng
tôi đã làm ở đây là: (i) chúng tôi mã hóa văn bản thành các ký tự, không
phải từ ngữ, để đơn giản hóa việc đào tạo trong các phần sau; (ii)
``corpus`` là một danh sách duy nhất, không phải là danh sách các danh
sách mã thông báo, vì mỗi dòng văn bản trong tập dữ liệu máy thời gian
không nhất thiết phải là một câu hoặc một đoạn văn.
.. raw:: html
.. raw:: html
.. code:: python
def load_corpus_time_machine(max_tokens=-1): #@save
"""Return token indices and the vocabulary of the time machine dataset."""
lines = read_time_machine()
tokens = tokenize(lines, 'char')
vocab = Vocab(tokens)
# Since each text line in the time machine dataset is not necessarily a
# sentence or a paragraph, flatten all the text lines into a single list
corpus = [vocab[token] for line in tokens for token in line]
if max_tokens > 0:
corpus = corpus[:max_tokens]
return corpus, vocab
corpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)
.. parsed-literal::
:class: output
(170580, 28)
.. raw:: html
.. raw:: html
.. code:: python
def load_corpus_time_machine(max_tokens=-1): #@save
"""Return token indices and the vocabulary of the time machine dataset."""
lines = read_time_machine()
tokens = tokenize(lines, 'char')
vocab = Vocab(tokens)
# Since each text line in the time machine dataset is not necessarily a
# sentence or a paragraph, flatten all the text lines into a single list
corpus = [vocab[token] for line in tokens for token in line]
if max_tokens > 0:
corpus = corpus[:max_tokens]
return corpus, vocab
corpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)
.. parsed-literal::
:class: output
(170580, 28)
.. raw:: html
.. raw:: html
.. code:: python
def load_corpus_time_machine(max_tokens=-1): #@save
"""Return token indices and the vocabulary of the time machine dataset."""
lines = read_time_machine()
tokens = tokenize(lines, 'char')
vocab = Vocab(tokens)
# Since each text line in the time machine dataset is not necessarily a
# sentence or a paragraph, flatten all the text lines into a single list
corpus = [vocab[token] for line in tokens for token in line]
if max_tokens > 0:
corpus = corpus[:max_tokens]
return corpus, vocab
corpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)
.. parsed-literal::
:class: output
(170580, 28)
.. raw:: html
.. raw:: html
Tóm tắt
-------
- Văn bản là một hình thức quan trọng của dữ liệu trình tự.
- Để xử lý trước văn bản, chúng ta thường chia văn bản thành token, xây
dựng một từ vựng để ánh xạ chuỗi token thành các chỉ số số, và chuyển
đổi dữ liệu văn bản thành các chỉ số token cho các mô hình thao tác.
Bài tập
-------
1. Token ization là một bước tiền xử lý chính. Nó thay đổi cho các ngôn
ngữ khác nhau. Cố gắng tìm ba phương pháp thường được sử dụng khác để
mã hóa văn bản.
2. Trong thí nghiệm của phần này, mã hóa văn bản thành các từ và thay
đổi các đối số ``min_freq`` của trường hợp ``Vocab``. Điều này ảnh
hưởng đến kích thước từ vựng như thế nào?
`Discussions `__