Примите участие в 25-м дне испытания ноябрьского обновления и узнайте подробности события:Вызов последнего обновления 2021 г.
Эта статья о том, как сделать простую предварительную обработку текста, действительно очень простую. Мы собираемся сделать следующие четыре шага:
- Загрузить текст в память в виде строки.
- Разбить строку на токены (например, слова и символы).
- Создайте словарь, который сопоставляет разделенные токены с числовыми индексами.
- Преобразование текста в последовательность числовых индексов для упрощения работы с моделью.
Это действительно самая простая предварительная обработка текста.За исключением «Learning Deep Learning by Hand», первая предварительная обработка была такой же, когда я читал Yushu. Таким образом, он должен быть подходящим для новичков, чтобы взглянуть.
import collections
import re
from d2l import torch as d2l
чтение набора данных
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt',
'090b5e7e70c295757f55df93cb0a180b9691891a')
def read_time_machine():
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])
Этот код от H.G.Wellмашина времениЗагрузка текста в формате , представляет собой небольшой набор из 3w слов.
-
будет отображаться во время загрузки
Downloading ..\data\timemachine.txt from 2-данные — это 3-ускорение. Amazon AWS.com/time machine…...
-
Сколько рейсов выводится после завершения загрузки и содержимое строк 0 и 10.
>> # text lines: 3221 the time machine by h g wells twinkled and his usually pale face was flushed and animated the
-
read_time_machine()
Это прочитать предложение из загруженного файла, удалить другие символы, кроме прописных и строчных букв, и сохранить его в списке. После этого шага в списке остаются только строчные буквы и пробелы.-
for line in lines
является объектом генератора-
[for line in lines]
состоит в том, чтобы вернуть объект генератора в список -
[对line进行操作 for line in lines]
состоит в том, чтобы работать с каждым элементом в строках списка -
re.sub('[^A-Za-z]+', ' ', line)
Используйте регулярное выражение, чтобы заменить в строке элементы, отличные от букв, и заменить их пробелами.-
re.sub(*pattern*, *repl*, *string*, *count=0*, *flags=0*)
использовать replзаменить вstringпоявление вpatternи вернуть строку результата.
replМожет быть строкой или функцией; если это строка, то будут обработаны любые escape-последовательности обратной косой черты в ней. Это,
\n
будет преобразовано в новую строку,\r
преобразуется в возврат каретки и так далее.необязательные параметрыcountмаксимальное количество замен;countДолжно быть неотрицательным целым числом. Если этот параметр опущен или установлен в 0, все совпадения будут заменены.
-
-
.strip()
Удалить пробелы с обоих концов строки -
.lower()
Преобразование прописных букв в строчные
-
-
лемматизация
Это разделить текст на список слов.Размер является основной единицей текста.
def tokenize(lines, token='word'):
if token == 'word':
return [line.split() for line in lines]
elif token == 'char':
return [list(line) for line in lines]
else:
print('错误:未知词元类型:' + token)
Разделит ли этот шаг текст на слова (или пробелы) или на отдельные буквы (или пробелы),
-
token = word
это разделить на слова -
token = char
это разбить его на буквы
попробуйtokenize
Эффект функции:
-
word
tokens = tokenize(lines) for i in range(10,13): print(f"\nline[{i}]:",lines[i]) print(f"\ntokens[{i}]:",tokens[i])
>> line[10]: twinkled and his usually pale face was flushed and animated the tokens[10]: ['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the'] line[11]: fire burned brightly and the soft radiance of the incandescent tokens[11]: ['fire', 'burned', 'brightly', 'and', 'the', 'soft', 'radiance', 'of', 'the', 'incandescent'] line[12]: lights in the lilies of silver caught the bubbles that flashed and tokens[12]: ['lights', 'in', 'the', 'lilies', 'of', 'silver', 'caught', 'the', 'bubbles', 'that', 'flashed', 'and']
-
char
tokens = tokenize(lines, 'char') for i in range(10,13): print(f"\nline[{i}]:",lines[i]) print(f"\ntokens[{i}]:",tokens[i])
>> line[10]: twinkled and his usually pale face was flushed and animated the tokens[10]: ['t', 'w', 'i', 'n', 'k', 'l', 'e', 'd', ' ', 'a', 'n', 'd', ' ', 'h', 'i', 's', ' ', 'u', 's', 'u', 'a', 'l', 'l', 'y', ' ', 'p', 'a', 'l', 'e', ' ', 'f', 'a', 'c', 'e', ' ', 'w', 'a', 's', ' ', 'f', 'l', 'u', 's', 'h', 'e', 'd', ' ', 'a', 'n', 'd', ' ', 'a', 'n', 'i', 'm', 'a', 't', 'e', 'd', ' ', 't', 'h', 'e'] line[11]: fire burned brightly and the soft radiance of the incandescent tokens[11]: ['f', 'i', 'r', 'e', ' ', 'b', 'u', 'r', 'n', 'e', 'd', ' ', 'b', 'r', 'i', 'g', 'h', 't', 'l', 'y', ' ', 'a', 'n', 'd', ' ', 't', 'h', 'e', ' ', 's', 'o', 'f', 't', ' ', 'r', 'a', 'd', 'i', 'a', 'n', 'c', 'e', ' ', 'o', 'f', ' ', 't', 'h', 'e', ' ', 'i', 'n', 'c', 'a', 'n', 'd', 'e', 's', 'c', 'e', 'n', 't'] line[12]: lights in the lilies of silver caught the bubbles that flashed and tokens[12]: ['l', 'i', 'g', 'h', 't', 's', ' ', 'i', 'n', ' ', 't', 'h', 'e', ' ', 'l', 'i', 'l', 'i', 'e', 's', ' ', 'o', 'f', ' ', 's', 'i', 'l', 'v', 'e', 'r', ' ', 'c', 'a', 'u', 'g', 'h', 't', ' ', 't', 'h', 'e', ' ', 'b', 'u', 'b', 'b', 'l', 'e', 's', ' ', 't', 'h', 'a', 't', ' ', 'f', 'l', 'a', 's', 'h', 'e', 'd', ' ', 'a', 'n', 'd']
Глоссарий
После описанной выше обработки токен, который мы получаем, имеет строковый тип, а ввод, требуемый моделью, — это число, поэтому нам нужно пронумеровать каждый токен, чтобы модель могла использовать номер.
построитьСловарьСловарь, который сопоставляет токены строкового типа с числовыми индексами, начинающимися с 0.
def count_corpus(tokens):
if len(tokens) == 0 or isinstance(tokens[0], list):
# 将词元列表展平成使用词元填充的一个列表
tokens = [token for line in tokens for token in line]
return collections.Counter(tokens)
Эта функция используется для подсчета частоты токенов.
Все документы в обучающей выборке объединяются вместе, подсчитываются их уникальные токены, а полученные статистические результаты называются корпусом. Затем каждому уникальному токену присваивается числовой индекс в зависимости от того, как часто он встречается.
-
if len(tokens) == 0 or isinstance(tokens[0], list)
Возвращает true, когда токены представляют собой пустой список или двумерный список (конечно, трехмерный и четырехмерный также возвращают true, но мы определили, что для предыдущей операции с токенами он не более чем двумерный). -
tokens = [token for line in tokens for token in line]
Используется для выравнивания списка, преобразования исходного двумерного в одномерный. - наконец вернуться к
collections.Counter
.-
class collections.Counter([*iterable-or-mapping*])
Один
Counter
Являетсяdict
подклассЭто коллекция, в которой элементы хранятся как ключи словаря, а их счетчики хранятся как значения. Количество может быть любым целым числом, включая 0 и отрицательные числа.
Counter
Классы немного похожи на сумки или мультимножества в других языках.c = collections.Counter('gallahad') print(c) c = collections.Counter({'red': 4, 'blue': 2}) print(c) c = collections.Counter(['eggs', 'ham']) print(c)
>> Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1}) Counter({'red': 4, 'blue': 2}) Counter({'eggs': 1, 'ham': 1})
Если указанный ключ не имеет записей, верните 0 вместо того, чтобы выталкивать
KeyError
c = collections.Counter('gallahad') print(c['z'])
>> 0
-
При обработке ожиданий удаляются менее часто встречающиеся слова, что может снизить сложность обработки.
.
Мы также можем добавить список для хранения зарезервированных маркеров, например: маркеры заполнения («
Теперь напишите класс для реализации функции текстового словаря:
class Vocab:
def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
if tokens is None:
tokens = []
if reserved_tokens is None:
reserved_tokens = []
# 按出现频率排序
counter = count_corpus(tokens)
self.token_freqs = sorted(counter.items(), key=lambda x: x[1],
reverse=True)
# 未知词元的索引为0
self.unk, uniq_tokens = 0, ['<unk>'] + reserved_tokens
uniq_tokens += [token for token, freq in self.token_freqs
if freq >= min_freq and token not in uniq_tokens]
self.idx_to_token, self.token_to_idx = [], dict()
for token in uniq_tokens:
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]
-
параметр:
- токен: ваш текст классифицируется по слову или символу
- min_freq: установить порог и игнорировать определенные слова, если их частота слишком низкая
- зарезервированные_токены: токен, с которого начинается или заканчивается предложение.
-
Начните с двух операторов if, если это неприемлемо
tokens
илиreserved_tokens
Просто установите его пустым, чтобы предотвратить ошибки. -
использовать
counter
Принять корпус с хорошей статистикой частоты слов -
self.token_freqs
получить словарь, отсортированный по частоте в порядке убывания-
sorted(iterable, key=None, reverse=False)
Описание параметра:
- iterable — итерируемый объект.
- key -- в основном используется для сравнения элемента, параметр всего один, параметр конкретной функции берется из итерируемого объекта, а для сортировки указывается элемент в итерируемом объекте.
- reverse -- сортировка, reverse=True по убыванию, reverse=False по возрастанию (по умолчанию).
-
используя счетчик
.items()
Сортировка, то есть кортеж пар ключ-значение. ключ установлен наx[1]
, Кортеж каждой пары ключ-значение рассматривается как x, а x[1] сортируется в соответствии со следующими значениями.reverse = True
Отсортируйте их в порядке убывания.
-
-
Последняя часть — написать self.idx_to_token и self.token_to_idx, чтобы получить его частоту слов или слов.
-
Эта статья представляет собой примечания к чтению версии pytorch «Обучение глубокому обучению вручную». Другие статьи из этой серии можно найти здесь:Колонка «Практическое глубокое обучение» (juejin.cn)
-
Примечания Адрес Github:DeepLearningNotes/d2l(github.com)
Все еще в процессе обновления......