Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шолле Ф. - Глубокое обучение на Python (Библиотека программиста) - 2023.pdf
Скачиваний:
6
Добавлен:
07.04.2024
Размер:
11.34 Mб
Скачать

392    Глава 11. Глубокое обучение для текста

Именно.таким.образом.нулями.были.дополнены.пакеты.последовательностей. целых.чисел,.образованных.из.набора.данных.IMDB,.с.которыми.вы.работали. в.главах.4.и.5.

11.2.4. Использование слоя TextVectorization

Все.перечисленные.до.сих.пор.шаги.легко.реализовать.на.чистом.Python..Например,.вы.могли.бы.написать.такой.код:

import string

class Vectorizer:

def standardize(self, text): text = text.lower()

return "".join(char for char in text

if char not in string.punctuation)

def tokenize(self, text):

text = self.standardize(text) return text.split()

def make_vocabulary(self, dataset): self.vocabulary = {"": 0, "[UNK]": 1} for text in dataset:

text = self.standardize(text) tokens = self.tokenize(text) for token in tokens:

if token not in self.vocabulary: self.vocabulary[token] = len(self.vocabulary)

self.inverse_vocabulary = dict(

(v, k) for k, v in self.vocabulary.items())

def encode(self, text):

text = self.standardize(text) tokens = self.tokenize(text)

return [self.vocabulary.get(token, 1) for token in tokens]

def decode(self, int_sequence): return " ".join(

self.inverse_vocabulary.get(i, "[UNK]") for i in int_sequence)

vectorizer = Vectorizer() dataset = [

"I write, erase, rewrite", "Erase again, and then", "A poppy blooms.",

Хайку японского поэта Хокуши

]

vectorizer.make_vocabulary(dataset)

11.2. Подготовка текстовых данных    393

И.с.его.помощью.подготовить.свои.данные:

>>>test_sentence = "I write, rewrite, and still rewrite again"

>>>encoded_sentence = vectorizer.encode(test_sentence)

>>>print(encoded_sentence)

[2, 3, 5, 7, 1, 5, 6]

>>>decoded_sentence = vectorizer.decode(encoded_sentence)

>>>print(decoded_sentence)

"i write rewrite and [UNK] rewrite again"

Однако .это .не .лучшее .решение..На .практике .обычно .используется .слой. TextVectorization .из.библиотеки.Keras..Он.работает.быстро.и.эффективно,. и.его.можно.добавить.непосредственно.в.конвейер.tf.data .или.в.модель.Keras.

Вот.как.создается.слой.TextVectorization:

from tensorflow.keras.layers import TextVectorization text_vectorization = TextVectorization(

)

output_mode="int",

 

Слой настраивается для возврата последовательностей слов,

 

 

 

 

 

представленных в виде целочисленных индексов. Доступно несколько

 

 

 

 

 

 

других режимов вывода, с которыми вы вскоре познакомитесь

По.умолчанию.слой.TextVectorization .использует.режим.стандартизации. «преобразование.символов.в.нижний.регистр.и.удаление.знаков.пунктуации». и.токенизации.«разделение.по.пробелам»..Но,.что.особенно.важно,.вы.можете. передать.свои.функции.для.стандартизации.и.токенизации.—.как.видим,.слой. достаточно.гибок.и.подходит.для.любых.вариантов.использования..Помните,.что. эти.функции.должны.работать.с.тензорами.tf.string,.а.не.с.обычными.строками. Python!.Для.примера.рассмотрим.код.ниже,.представляющий.поведение.слоя. по.умолчанию:

import re

 

 

 

 

 

import string

Преобразовать строки

 

 

import tensorflow as tf

 

 

 

в нижний регистр

 

 

def custom_standardization_fn(string_tensor):

 

Заменить знаки

 

lowercase_string = tf.strings.lower(string_tensor)

 

 

 

пунктуации пустыми

 

 

строками

return tf.strings.regex_replace(

 

 

 

 

 

 

 

 

 

lowercase_string, f"[{re.escape(string.punctuation)}]", "")

def custom_split_fn(string_tensor):

return tf.strings.split(string_tensor)

text_vectorization = TextVectorization( output_mode="int", standardize=custom_standardization_fn, split=custom_split_fn,

)

Разбить строки по пробелам

394    Глава 11. Глубокое обучение для текста

Чтобы.проиндексировать.словарь.корпуса.текста,.достаточно.вызвать.метод. adapt().слоя.с.объектом.Dataset,.возвращающим.строки,.или.просто.со.списком. строк.Python:

dataset = [

"I write, erase, rewrite", "Erase again, and then", "A poppy blooms.",

]

text_vectorization.adapt(dataset)

Обратите.внимание.на.то,.что.созданный.словарь.можно.получить.вызовом. get_vocabulary().—.это.может.пригодиться.в.случае,.если.текст,.представленный.

в.виде.последовательности.целых.чисел,.понадобится.преобразовать.обратно.

в.слова..Первые.две.записи.в.словаре.—.это.токен.маски.(индекс.0).и.несло- варный.токен.(индекс.1)..Записи.в.словаре.отсортированы.по.частоте,.поэтому.

в.реальном.наборе.данных.самые.распространенные.слова,.такие.как.артикли. the.или.a,.будут.находиться.на.первых.местах.

Листинг 11.1. Вывод содержимого словаря

>>> text_vectorization.get_vocabulary() ["", "[UNK]", "erase", "write", ...]

Для.демонстрации.попробуем.закодировать,.а.затем.декодировать.предложение:

>>>vocabulary = text_vectorization.get_vocabulary()

>>>test_sentence = "I write, rewrite, and still rewrite again"

>>>encoded_sentence = text_vectorization(test_sentence)

>>>print(encoded_sentence)

tf.Tensor([ 7 3 5 9 1 5 10], shape=(7,), dtype=int64)

>>>inverse_vocab = dict(enumerate(vocabulary))

>>>decoded_sentence = " ".join(inverse_vocab[int(i)] for i in encoded_sentence)

>>>print(decoded_sentence)

"i write rewrite and [UNK] rewrite again"

СЛОЙ TEXTVECTORIZATION КАК ЧАСТЬ МОДЕЛИ ИЛИ КОНВЕЙЕРА TF.DATA

Важно отметить, что основной операцией в TextVectorization является операция поиска по словарю, которую нельзя выполнить на GPU илиTPU — только на CPU. Поэтому при обучении модели на GPU слой TextVectorization сначала выполнится на CPU — и только потом его выходные данные будут отправлены в GPU. Это имеет важные последствия для производительности.

Есть два способа использования слоя TextVectorization. Первый — поместить его в конвейер tf.data, например — так:

Аргумент num_parallel_calls используется для параллельного выполнения map() на нескольких ядрах CPU

11.2. Подготовка текстовых данных    395

int_sequence_dataset = string_dataset.map( text_vectorization, num_parallel_calls=4)

string_dataset может быть набором данных, возвращающим строковые тензоры

Второй способ — включить слой в состав модели (в конце концов, это слой Keras), как показано ниже:

Определить форму строковых входных данных

 

 

 

Применить

 

text_input = keras.Input(shape=(), dtype="string")

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

векторизацию

vectorized_text = text_vectorization(text_input)

 

 

 

 

 

 

 

 

 

embedded_input = keras.layers.Embedding(...)(vectorized_text)

 

 

 

 

 

 

output = ...

 

 

 

model = keras.Model(text_input, output)

 

 

 

Далее можно добавлять новые слои, как это делается

 

при создании моделей с помощью функционального API

 

Эти два способа имеют важное различие. Если этап векторизации является частью модели, он будет выполняться синхронно с остальной частью модели, то есть на каждом этапе обучения остальная часть модели (выполняющаяся на GPU) будет ждать, пока слой TextVectorization (на CPU) подготовит данные. При размещении же слоя в конвейере tf.data появляется возможность проводить предварительную обработку данных на CPU асинхронно: пока модель на GPU обрабатывает один пакет векторизованных данных, CPU выполняет векторизацию следующего пакета исходных строк.

Поэтому, если модель обучается на GPU или TPU, вероятно, лучше выбрать первый способ, чтобы получить максимальную производительность. Так мы и поступим во всех практических примерах далее в этой главе. Однако при обучении на CPU можно использовать и синхронную обработку: вы в любом случае получите 100%-ную загрузку ядер процессора, независимо от выбранного способа.

Кроме того, если предполагается экспортировать модель в производственное окружение, то предпочтительнее выглядит модель, принимающая исходные строки (как в примере, демонстрирующем второй способ). В противном случае придется повторно реализовать стандартизацию и токенизацию текста в производственном окружении (возможно, на JavaScript?); к тому же увеличивается риск небольших расхождений в процессе предварительной обработки, которые могут ухудшить точность модели. К счастью, слой TextVectorization позволяет вам включить предварительную обработку текста прямо в модель, упрощая ее развертывание, даже если первоначально слой использовался как часть конвейера tf.data. Во врезке «Экспорт модели, обрабатывающей исходные строки» вы узнаете, как экспортировать обученную модель, предназначенную только для прогнозирования, которая

включает предварительную обработку текста.