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

7.2. Разные способы создания моделей Keras    231

Это.довольно.распространенный.прием.отладки.при.работе.со.слоями,.которые. применяют.сложные.преобразования.к.своим.входным.данным.(например,. со.сверточными.слоями,.о.которых.рассказывается.в.главе.8).

7.2.2. Функциональный API

Модель.Sequential .проста.в.использовании,.но.круг.сфер.ее.применения.чрезвычайно.ограничен:.она.может.выражать.модели.только.с.одним.входом.и.одним. выходом,.последовательно.применяя.слои.друг.за.другом..Но.на.практике.довольно.часто.встречаются.модели.с.несколькими.входами.(например,.изображение.и.его.метаданные),.несколькими.выходами.(разные.признаки,.которые. необходимо.предсказать).или.нелинейной.топологией.

В.таких.случаях.модель.следует.строить.с.помощью.функционального.API.—. именно.такой.подход.для.большинства.моделей.Keras.вы.встретите.в.действительности..Это.мощный.и.увлекательный.способ.конструирования,.напоминающий.игру.с.кубиками.лего.

Простой пример

Начнем.с.чего-нибудь.простого.—.например,.воспроизведем.последовательность. из.двух.слоев,.что.была.создана.в.предыдущем.разделе..Следующий.листинг. иллюстрирует.создание.этой.модели.с.помощью.функционального.API.

Листинг 7.8. Создание простой модели с двумя слоями Dense с помощью функционального API

inputs = keras.Input(shape=(3,), name="my_input") features = layers.Dense(64, activation="relu")(inputs) outputs = layers.Dense(10, activation="softmax")(features) model = keras.Model(inputs=inputs, outputs=outputs)

Рассмотрим.этот.процесс.шаг.за.шагом.

Сначала.объявляется.форма.входных.данных.в.виде.экземпляра.класса.Input . (обратите.внимание,.что.этим.объектам,.как.и.любым.другим,.тоже.можно.присваивать.имена):

inputs = keras.Input(shape=(3,), name="my_input")

Объект.input .хранит.информацию.о.форме.и.типе.данных,.которые.будет.обрабатывать.модель:

>>> inputs.shape

 

Модель будет обрабатывать пакеты, в которых каждый образец

 

 

имеет форму (3,). Количество образцов в пакете может меняться

(None, 3)

 

 

 

 

(о чем говорит значение None, определяющее размер пакета)

 

 

>>> inputs.dtype

 

 

 

 

Данные в пакетах имеют тип float32

 

 

float32

 

 

232    Глава 7. Работа с Keras: глубокое погружение

Такие.объекты.называются.символическими тензорами..Они.не.содержат.никаких.действительных.данных,.но.определяют.параметры.фактических.тензоров,. которые.модель.будет.получать.на.входе..То.есть.они.представляют.будущие. тензоры.данных.

Затем.создается.слой.и.при.создании.ему.передается.информация.о.входных. данных:

features = layers.Dense(64, activation="relu")(inputs)

Любым.слоям.Keras.могут.передаваться.тензоры.с.реальными.данными.или. такие.вот.символические.тензоры..В.последнем.случае.они.возвращают.новый. символический.тензор.с.информацией.о.форме.и.типе.выходных.данных:

>>> features.shape (None, 64)

После.получения.информации.о.выходных.данных.последнего.слоя.создается. экземпляр.модели;.при.этом.конструктору.модели.передаются.сведения.о.входах. и.выходах.

outputs = layers.Dense(10, activation="softmax")(features) model = keras.Model(inputs=inputs, outputs=outputs)

Вот.сводная.информация.о.получившейся.модели:

>>> model.summary() Model: "functional_1"

_________________________________________________________________

Layer (type) Output Shape Param #

=================================================================

my_input (InputLayer) [(None, 3)] 0

_________________________________________________________________

dense_6 (Dense) (None, 64) 256

_________________________________________________________________

dense_7 (Dense) (None, 10) 650

=================================================================

Total params: 906 Trainable params: 906 Non-trainable params: 0

_________________________________________________________________

Модели с несколькими входами и выходами

В.отличие.от.этой.простой.модели.большинство.моделей.глубокого.обучения. не.похожи.на.списки.и.скорее.напоминают.графы..Например,.они.могут.иметь. несколько.входов.или.несколько.выходов..Именно.благодаря.таким.моделям. функциональный.API.предстает.во.всем.блеске.

7.2. Разные способы создания моделей Keras    233

Представьте,.что.вы.создаете.систему.для.ранжирования.заявок.в.службу.поддержки.клиентов.по.важности.и.для.распределения.между.соответствующими. отделами..Ваша.модель.имеет.три.входа:

. название.заявки.(текстовый.вход);

. текст.с.описанием.заявки.(текстовый.вход);

.теги,.добавленные.пользователем.(категориальный.вход;.предполагается,. что.теги.представлены.в.формате.прямого.кодирования).

Входные.текстовые.данные.можно.закодировать.в.виде.массивов.нулей.и.единиц.с.размерами.vocabulary_size .(мы.рассмотрим.методы.кодирования.текста. подробнее.в.главе.11).

Модель.также.имеет.два.выхода:

.оценку .важности .заявки .— .скалярное .значение .от .0 .до .1 .(сигмоидный. выход);

.отдел,.который.должен.обработать.заявку.(результат.применения.функции. softmax .к.множеству.отделов).

С.помощью.функционального.API.данную.модель.можно.построить.несколькими.строками.кода.

Листинг 7.9. Создание модели с несколькими входами и выходами с помощью функционального API

vocabulary_size = 10000 num_tags = 100 num_departments = 4

Объединение входных признаков в один тензор features

Определение входов модели

title = keras.Input(shape=(vocabulary_size,), name="title") text_body = keras.Input(shape=(vocabulary_size,), name="text_body") tags = keras.Input(shape=(num_tags,), name="tags")

features = layers.Concatenate()([title, text_body, tags]) features = layers.Dense(64, activation="relu")(features)

priority = layers.Dense(1, activation="sigmoid", name="priority")(features) department = layers.Dense(

num_departments, activation="softmax", name="department")(features)

model = keras.Model(inputs=[title, text_body, tags], outputs=[priority, department])

Определение выходов модели Создание модели с передачей ей

информации о входах и выходах

Добавление промежуточного слоя для рекомбинации входных признаков в более богатые представления

234    Глава 7. Работа с Keras: глубокое погружение

Функциональный.API.—.это.простой,.как.конструктор.лего,.но.очень.гибкий. способ.определения.произвольных.графов.слоев,.подобных.этому.

Обучение модели с несколькими входами и выходами

Обучаются.модели.с.несколькими.входами.и.выходами.почти.так.же,.как.модели. Sequential,.—.вызовом.функции.fit() .со.списками.входных.и.выходных.дан- ных..Эти.списки.должны.передаваться.в.том.же.порядке,.в.каком.информация. о.входных.данных.передавалась.конструктору.модели.

Листинг 7.10. Обучение модели с передачей массивов входных данных и целей

import numpy as np

 

num_samples = 1280

Фиктивные

входные данные

 

title_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size)) text_body_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size)) tags_data = np.random.randint(0, 2, size=(num_samples, num_tags))

priority_data = np.random.random(size=(num_samples, 1))

department_data = np.random.randint(0, 2, size=(num_samples, num_departments)) model.compile(optimizer="rmsprop",

loss=["mean_squared_error", "categorical_crossentropy"],

metrics=[["mean_absolute_error"], ["accuracy"]])

Фиктивные

model.fit([title_data, text_body_data, tags_data],

целевые данные

[priority_data, department_data],

 

epochs=1)

 

model.evaluate([title_data, text_body_data, tags_data],

 

[priority_data, department_data])

 

priority_preds, department_preds = model.predict(

 

[title_data, text_body_data, tags_data])

 

Чтобы.не.зависеть.от.конкретного.порядка.передачи.аргументов.(например,.у.вашей.модели.много.входов.или.выходов.и.вам.не.хотелось.бы.в.них.запутаться),. можно.также.использовать.имена,.присвоенные.объектам.Input .и.выходным. слоям,.и.передавать.данные.через.словари.

Листинг 7.11. Обучение модели с передачей массивов входных данных и целей в словаре

model.compile(optimizer="rmsprop",

loss={"priority": "mean_squared_error", "department": "categorical_crossentropy"},

7.2. Разные способы создания моделей Keras    235

metrics={"priority": ["mean_absolute_error"], "department": ["accuracy"]})

model.fit({"title": title_data, "text_body": text_body_data, "tags": tags_data},

{"priority": priority_data, "department": department_data}, epochs=1)

model.evaluate({"title": title_data, "text_body": text_body_data, "tags": tags_data},

{"priority": priority_data, "department": department_data}) priority_preds, department_preds = model.predict(

{"title": title_data, "text_body": text_body_data, "tags": tags_data})

Мощь функционального API: доступ к информации о связях между слоями

Функциональная.модель.—.это.графовая.структура.данных..Она.позволяет. исследовать.связи.между.слоями.и.повторно.использовать.предыдущие.узлы. графа.(которые.являются.выходами.слоев).в.новых.моделях..Кроме.того,.она. хорошо.соответствует.«ментальной.модели».(графу.слоев),.которую.используют.многие.исследователи,.рассуждая.о.глубоких.нейронных.сетях,.а.также. поддерживает.два.важных.способа.использования:.визуализацию.модели.и.извлечение.признаков.

Давайте.отобразим.связи.в.только.что.созданной.модели.(ее.топологию)..Получить.изображение.функциональной.модели.в.виде.графа.можно.с.помощью. утилиты.plot_model() .(рис..7.2).

Рис. 7.2. Графическое представление модели классификации заявок, сгенерированное функцией plot_model()

В.эту.диаграмму.можно.добавить.форму.входа.и.выхода.каждого.слоя.в.модели,. что.может.пригодиться.в.процессе.отладки.(рис..7.3).

Рис. 7.3. Графическое представление модели с информацией о форме входов и выходов

layers[4] — это промежуточный слой Dense

7.2. Разные способы создания моделей Keras    237

Слово.None.в.формах.тензоров.представляет.размер.пакета:.данная.модель.может. обрабатывать.пакеты.любого.размера.

Доступность.информации.о.связях.между.слоями.также.означает.возможность. исследовать.и.повторно.использовать.отдельные.узлы.(выходы.слоев).в.графе..

Свойство.модели.model.layers.возвращает.список.слоев.в.модели,.и.для.каждого. слоя.в.этом.списке.можно.исследовать.их.свойства.layer.input .и.layer.output.

Листинг 7.12. Получение входов и выходов слоя в функциональной модели

>>> model.layers

[<tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d358>, <tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d2e8>, <tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d470>, <tensorflow.python.keras.layers.merge.Concatenate at 0x7fa963f9d860>, <tensorflow.python.keras.layers.core.Dense at 0x7fa964074390>, <tensorflow.python.keras.layers.core.Dense at 0x7fa963f9d898>, <tensorflow.python.keras.layers.core.Dense at 0x7fa963f95470>]

>>> model.layers[3].input

[<tf.Tensor "title:0" shape=(None, 10000) dtype=float32>, <tf.Tensor "text_body:0" shape=(None, 10000) dtype=float32>, <tf.Tensor "tags:0" shape=(None, 100) dtype=float32>]

>>> model.layers[3].output

<tf.Tensor "concatenate/concat:0" shape=(None, 20100) dtype=float32>

Это.позволяет.производить.извлечение признаков.в.моделях,.повторно.использующих.промежуточные.признаки.из.другой.модели.

Представьте,.что.вы.решили.добавить.еще.один.выход.в.предыдущую.модель.—. оценку.времени,.которое.потребуется.для.решения.обозначенной.в.заявке.проблемы.(своего.рода.рейтинг.сложности)..Это.можно.сделать.с.помощью.слоя. классификации.по.трем.категориям:.«простая».проблема,.«средняя».и.«сложная».. Причем.вам.не.нужно.воссоздавать.и.повторно.обучать.модель.с.нуля:.можно. начать.с.промежуточных.признаков.предыдущей.модели,.как.показано.ниже.

Листинг 7.13. Создание новой модели, повторно использующей выходы промежуточных слоев

features = model.layers[4].output

difficulty = layers.Dense(3, activation="softmax", name="difficulty")(features)

new_model = keras.Model( inputs=[title, text_body, tags],

outputs=[priority, department, difficulty])

Теперь.получим.графическое.представление.новой.модели.(рис..7.4):

keras.utils.plot_model(

new_model, "updated_ticket_classifier.png", show_shapes=True)

Рис. 7.4. Графическое представление новой модели