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

122    Глава 3. Введение в Keras и TensorFlow

Рис. 3.8. Наша модель изображена как прямая линия

В.этом.и.заключается.суть.линейного.классификатора:.поиск.параметров.линии. (или,.в.многомерных.пространствах,.гиперплоскости),.аккуратно.разделяющей. два.класса.данных.

3.6. АНАТОМИЯ НЕЙРОННОЙ СЕТИ: ЗНАКОМСТВО С ОСНОВАМИ KERAS

Теперь,.зная.основы.библиотеки.TensorFlow,.вы.сможете.реализовать.с.нуля. простую.модель.линейного.классификатора,.подобную.той,.что.была.показана. в.предыдущем.разделе,.или.несложной.нейронной.сети,.представленной.в.конце. главы.2..Это.солидный.фундамент,.на.котором.уже.можно.что-то.построить..

А.сейчас.пришло.время.встать.на.более.продуктивный.и.надежный.путь.к.глубокому.обучению:.начать.использовать.библиотеку.Keras.

3.6.1. Слои: строительные блоки глубокого обучения

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

Разным.слоям.соответствуют.тензоры.разных.форматов.и.разные.виды.обработки.данных..Например,.простые.векторные.данные,.хранящиеся.в.двумерных.

3.6. Анатомия нейронной сети: знакомство с основами Keras    123

тензорах.с.формой.(образцы,.признаки),.часто.обрабатываются.плотно связанными.слоями,.которые.также.называют.полносвязными.или.плотными.слоями. (класс.Dense .в.Keras)..Ряды.данных.хранятся.в.трехмерных.тензорах.с.формой. (образцы,.метки_времени,.признаки).и.обычно.обрабатываются.рекуррентными. слоями,.такими.как.LSTM,.или.одномерными.сверточными.слоями.(Conv1D).. Изображения.хранятся.в.четырехмерных.тензорах.и.обычно.обрабатываются. двумерными.сверточными.слоями.(Conv2D).

Слои.можно.считать.кубиками.лего.глубокого.обучения..Библиотеки,.подобные. Keras,.делают.это.сравнение.еще.более.явным:.создание.моделей.глубокого.обучения.в.Keras.осуществляется.путем.объединения.совместимых.слоев.в.конвейеры.обработки.данных.

Базовый класс Layer в Keras

Простой .прикладной .интерфейс .(API) .должен .иметь .единую .абстракцию,. лежащую.в.основе.всего..В.Keras.такой.абстракцией.служит.класс.слоев.Layer.. Все.в.Keras.является.либо.слоем.Layer,.либо.чем-то.еще,.что.тесно.взаимодей- ствует.со.слоем.Layer.

Слой.—.это.объект,.инкапсулирующий.некоторое.состояние.(веса).и.некоторые. вычисления.(прямой.проход)..Веса.обычно.определяются.с.помощью.метода. build().(но.также.могут.инициализироваться.в.конструкторе.__init__()),.а.вычисления.определяются.в.методе.call().

В.предыдущей.главе.мы.реализовали.класс.NaiveDense,.содержавший.два.веса,. W .и.b,.и.применили.вычисления.output .= .activation(dot(input, .W) .+ .b)..Вот.как. тот.же.слой.выглядел.бы.в.Keras.

Листинг 3.22. Слой Dense, реализованный как подкласс класса Layer

from tensorflow import keras

Все классы слоев в Keras наследуют

 

 

class SimpleDense(keras.layers.Layer):

 

базовый класс Layer

 

 

def __init__(self, units, activation=None):

super().__init__()

add_weight() — это вспомогательный метод для создания

self.units = units

весов. Также имеется возможность создать отдельные

self.activation = activation

переменные и связать их с атрибутами слоя, например:

 

self.W = tf.Variable(tf.random.uniform(w_shape))

def build(self, input_shape):

 

Веса создаются в методе build()

 

input_dim = input_shape[-1]

self.W = self.add_weight(shape=(input_dim, self.units),

 

 

initializer="random_normal")

self.b = self.add_weight(shape=(self.units,),

initializer="zeros")

def call(self, inputs):

 

 

Вычисления, выполняемые

 

 

y = tf.matmul(inputs, self.W) + self.b

во время прямого прохода,

if self.activation is not None:

 

 

 

 

определяются в методе call()

y = self.activation(y)

 

 

 

 

return y

 

 

 

 

124    Глава 3. Введение в Keras и TensorFlow

Мы.еще.вернемся.к.методам.build().и.call().в.следующем.разделе.и.рассмотрим. их.подробнее,.поэтому.не.волнуйтесь,.если.вы.чего-то.не.поняли!

Создав.такой.слой,.его.можно.использовать.как.функцию,.принимающую.на. входе.тензор.TensorFlow:

>>> my_dense = SimpleDense(units=32, activation=tf.nn.relu)

>>> input_tensor = tf.ones(shape=(2, 784))

 

Создать экземпляр

>>> output_tensor = my_dense(input_tensor)

 

 

слоя, который мы

>>> print(output_tensor.shape)

 

 

определили выше

 

 

(2,

32))

Вызвать слой подобно функции

 

 

Сформировать некоторые

 

 

 

 

 

и передать ему входные данные

 

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

Вам,.наверное,.интересно.узнать,.зачем.нужно.было.реализовать.методы.call() . и.build(),.если.в.итоге.мы.использовали.наш.слой,.просто.вызвав.его.как.функцию,.то.есть.с.помощью.его.метода.__call__()?.Причина.проста:.нам.нужно,. чтобы.состояние.создавалось.динамически,.на.лету..Давайте.посмотрим,.как. это.работает.

Автоматическое определение формы: построение слоев на лету

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

from tensorflow.keras import layers

 

Полносвязный слой

 

layer = layers.Dense(32, activation="relu")

 

 

с 32 выходами

 

 

Слой.возвращает.тензор,.первое.измерение.которого.равно.32..Данный.слой. можно.связать.со.слоем.ниже,.только.если.тот.принимает.32-мерные.векторы.

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

from tensorflow.keras import models from tensorflow.keras import layers model = models.Sequential([

layers.Dense(32, activation="relu"), layers.Dense(32)

])

Слои.не.получают.никакой.информации.о.форме.входных.данных.—.они.авто- матически.определяют.ее.по.форме.первого.измерения.своих.входных.данных.

3.6. Анатомия нейронной сети: знакомство с основами Keras    125

В.упрощенной.версии.слоя.Dense,.реализованной.нами.в.главе.2.(и.названной. NaiveDense),.требовалось.явно.передать.размер.входных.данных.конструктору,. чтобы.получить.возможность.создать.веса..Это.не.очень.удобно,.поскольку.тогда. при.конструировании.моделей.мы.вынуждены.будем.явно.указывать.в.каждом. новом.слое.форму.выходных.данных.предыдущего.слоя:

model = NaiveSequential([

NaiveDense(input_size=784, output_size=32, activation="relu"), NaiveDense(input_size=32, output_size=64, activation="relu"), NaiveDense(input_size=64, output_size=32, activation="relu"), NaiveDense(input_size=32, output_size=10, activation="softmax")

])

Было.бы.еще.хуже,.если.бы.при.выборе.формы.своих.выходных.данных.слой. руководствовался .сложными .правилами..Допустим, .наш .слой .возвращает. выходные.данные.с.формой.(batch, .input_size .* .2 if input_size % 2 == 0 else input_size * 3).

Если.бы.мы.повторно.реализовали.слой.NaiveDense .как.слой.Keras,.поддерживающий.автоматическое.определение.формы.входных.данных,.то.он.выглядел.бы.как.предыдущий.слой.SimpleDense .(см..листинг.3.22).с.его.методами. build() .и.call().

В.SimpleDense .мы.не.создаем.веса.в.конструкторе,.как.это.делали.в.примере. NaiveDense;.теперь.они.создаются.в.специальном.методе.конструирования.состояния.build(),.который.принимает.в.аргументе.форму.первого.измерения. входных.данных..Метод.build() .вызывается.автоматически.при.первом.вызове. слоя.(через.метод.__call__())..Именно.поэтому.мы.определили.вычисления. в.отдельном.методе.call(),.а.не.в.методе.__call__() .непосредственно..В.общих. чертах.метод.__call__() .базового.слоя.выглядит.примерно.так:

def __call__(self, inputs): if not self.built:

self.build(inputs.shape) self.built = True

return self.call(inputs)

Благодаря.автоматическому.определению.формы.наш.предыдущий.пример. становится.простым.и.понятным:

model = keras.Sequential([ SimpleDense(32, activation="relu"), SimpleDense(64, activation="relu"), SimpleDense(32, activation="relu"), SimpleDense(10, activation="softmax")

])