"Введение«С момента выпуска TensorFlow 2.0 Keras был глубоко интегрирован в инфраструктуру TensorFlow, и Keras API стал лучшим выбором для построения моделей глубокой сети. Разработка модели и итерация с помощью Keras — это фундаментальный навык, которым должен овладеть каждый разработчик данных.Давайте погрузимся в мир Keras и выясним.
Введение в Керас
-
Keras
это использованиеPython
Расширенная нейронная сеть написанаAPI
, которая представляет собой автономную библиотеку, способнуюTensorFlow
,CNTK
илиTheano
Работает как бэкенд.TensorFlow
от1.0
версия, чтобы начать пробовать сKeras
сделать интеграцию, чтобы2.0
После выхода версии он более глубоко интегрированKeras
, и находится в тесной зависимости отtf.keras
как его центральный старшийAPI
, официальный также настоятельно рекомендуется использоватьkeras API
завершить построение глубинной модели. -
tf.keras
Имеет три ключевых преимущества:-
Удобно для новичков:
Keras
Имеет простой и последовательный интерфейс с четкими и действенными предложениями по исправлению пользовательских ошибок.TensorFlow 2.0
Предыдущая версия, из-за сложности ее кодировки,API
Интерфейс сбивает с толку, а совместимость между различными версиями плохая, что неоднократно подвергалось критике.Keras
После унификации нагрузка на разработчиков сильно сократится. -
Модульный и компонуемый:
Keras
Модели связаны между собой сборными модулями без каких-либо ограничений, структура модели понятна, а код легко читается. -
Простота расширения: при написании новых пользовательских модулей очень удобно расширять на основе существующего интерфейса.
-
-
Keras
сделатьTensorFlow
Легче в использовании без ущерба для гибкости и производительности.
Керас модельное здание
существуетTensorFlow 2.x
версия, вы можете использовать три способа сборкиKeras
модели, которыеSequential
,函数式 (Functional) API
а также自定义模型 (Subclassed)
. Три метода построения описаны ниже.
Sequential Model
-
существует
Keras
, обычно несколько слоев (layer
) собираются в модель (model
), наиболее распространенным способом является укладка слоев, которую можно использоватьtf.keras.Sequential
сделать это легко. В качестве примера возьмем модель, показанную на рисунке выше, и ее кодовая реализация выглядит следующим образом:import tensorflow as tf from tensorflow.keras import layers model = tf.keras.Sequential() # Adds a densely-connected layer with 64 units to the model: model.add(layers.Dense(64, activation='relu', input_shape=(16,))) # This is identical to the following: # model.add(layers.Dense(64, activation='relu', input_dim=16)) # model.add(layers.Dense(64, activation='relu', batch_input_shape=(None, 16))) # Add another: model.add(layers.Dense(64, activation='relu')) # Add an output layer with 10 output units: model.add(layers.Dense(10)) # model.build((None, 16)) print(model.weights)
-
Примечание для
Sequential
Первый добавленный слой может содержатьinput_shape
илиinput_dim
илиbatch_input_shape
для указания размерности входных данных, подробности см. в разделе комментариев. когда указаноinput_shape
После ожидания параметров каждый разadd
Для новых слоев модель находится в процессе непрерывного создания, что означает, что весовая матрица каждого слоя в модели была инициализирована и может быть вызвана вызовомmodel.weights
для печати информации о весе модели. -
Конечно, первый слой также не может содержать информацию о размерности входных данных, что называется режимом отложенного создания, то есть модель в это время еще не создана, и матрица весов не существует. позвонив
model.build(batch_input_shape)
метод создания модели вручную. Если не создается вручную, то только при вызовеfit
Или другие методы обучения и оценки, модель будет создана, весовая матрица будет инициализирована, и модель автоматически выведет информацию о своих размерах на основе входных данных. -
input_shape
не указано вbatch
размер и установите его наNone
, потому что обучение и оценкаbatch
Размеры могут не совпадать. Если установлено фиксированное значение, оно будет генерировать ошибки во время обучения или оценки, а если установлено таким образом, оно может быть автоматически выведено моделью.batch
Размер и расчет более надежны. -
В дополнение к этому последовательному добавлению (
add
), также можноlayers
передается в качестве параметраSequential
чтобы построить модель. Пример кода выглядит следующим образом:import tensorflow as tf from tensorflow.keras import layers model = tf.keras.Sequential([ layers.Dense(64, activation='relu', input_shape=(16, )), layers.Dense(64, activation='relu'), layers.Dense(10) ]) # model.build((None, 16)) print(model.weights)
Функциональный API
-
Keras
из函数式 API
чемSequential
Более гибкий способ создания моделей. Он может обрабатывать модели с нелинейной топологией, с общими слоями (layers
) модели и модели с несколькими входами и выходами. Модели глубокого обучения обычно состоят из слоев (layers
) — ориентированный ациклический граф, и函数式 API
является эффективным способом построения такого графа. -
от
Sequential Model
Взяв модель, упомянутую в разделе в качестве примера, используйте函数式 API
Способ его реализации следующий:from tensorflow import keras from tensorflow.keras import layers inputs = keras.Input(shape=(16, )) dense = layers.Dense(64, activation='relu') x = dense(inputs) x = layers.Dense(64, activation='relu')(x) outputs = layers.Dense(10)(x) model = keras.Model(inputs=inputs, outputs=outputs, name='model') model.summary()
-
и использовать
Sequential
Способ, которым метод строит модель, отличается тем, что:函数式 API
пройти черезkeras.Input
ввод указанinputs
и через函数调用
произвел выводoutputs
, и, наконец, используйтеkeras.Model
метод строит всю модель. -
почему это называется
函数式 API
, как видно из кода, различные слои можно использовать как вызовы функций (layers
), такие как определенныеdense
слой, вы можете напрямуюinputs
в видеdense
ввод и получение выводаx
, а потомx
В качестве входных данных для следующего уровня конечное возвращаемое значение функции является выходом всей модели. -
函数式 API
Тот же слой (layers
) в составе нескольких моделей пример кода выглядит следующим образом:from tensorflow import keras from tensorflow.keras import layers encoder_input = keras.Input(shape=(16, ), name='encoder_input') x = layers.Dense(32, activation='relu')(encoder_input) x = layers.Dense(64, activation='relu')(x) encoder_output = layers.Dense(128, activation='relu')(x) encoder = keras.Model(encoder_input, encoder_output, name='encoder') encoder.summary() x = layers.Dense(64, activation='relu')(encoder_output) x = layers.Dense(32, activation='relu')(x) decoder_output = layers.Dense(16, activation='relu')(x) autoencoder = keras.Model(encoder_input, decoder_output, name='autoencoder') autoencoder.summary()
Код содержит две модели, энкодер (
encoder
) и автоэнкодер (autoencoder
), вы можете видеть, что две модели разделяютencoder_out
слоев, включая, конечно,encoder_out
Все слои перед слоем. -
函数式 API
Все созданные модели (models
) могут быть как слои (layers
) тоже называется. Также с автоэнкодером (autoencoder
) в качестве примера, теперь разделите его на энкодеры (encoder
) и декодер (decoder
) на две части, затем используйтеencoder
иdecoder
генерироватьautoencoder
, код показан ниже:from tensorflow import keras from tensorflow.keras import layers encoder_input = keras.Input(shape=(16, ), name='encoder_input') x = layers.Dense(32, activation='relu')(encoder_input) x = layers.Dense(64, activation='relu')(x) encoder_output = layers.Dense(128, activation='relu')(x) encoder = keras.Model(encoder_input, encoder_output, name='encoder') encoder.summary() decoder_input = keras.Input(shape=(128, ), name='decoder_input') x = layers.Dense(64, activation='relu')(decoder_input) x = layers.Dense(32, activation='relu')(x) decoder_output = layers.Dense(16, activation='relu')(x) decoder = keras.Model(decoder_input, decoder_output, name='decoder') decoder.summary() autoencoder_input = keras.Input(shape=(16), name='autoencoder_input') encoded = encoder(autoencoder_input) autoencoder_output = decoder(encoded) autoencoder = keras.Model( autoencoder_input, autoencoder_output, name='autoencoder', ) autoencoder.summary()
Код сначала генерирует две модели
encoder
иdecoder
, а затем сгенерироватьautoencoder
модель, используя模型函数调用
кстати, напрямуюautoencoder_input
иencoded
соответственно какencoder
иdecoder
ввод двух моделей и, наконец, получитьautoencoder
Модель. -
函数式 API
Модели с несколькими входами и несколькими выходами могут быть легко обработаны, чтоSequential API
невозможно. Например, часть входных данных нашей модели类别型特征
, вообще надо пройтиEmbedding
обработка и часть数值型特征
, как правило, никакой специальной обработки не требуется, и очевидно, что эти две функции не могут быть напрямую объединены как один вход для общей обработки, и в настоящее время будет использоваться несколько входов. Иногда мы хотим, чтобы модель возвращала несколько выходных данных для использования в последующих вычислениях, и в этом случае используется модель с несколькими выходными данными. Пример кода для модели с несколькими входами и несколькими выходами показан ниже:from tensorflow import keras from tensorflow.keras import layers categorical_input = keras.Input(shape=(16, )) numeric_input = keras.Input(shape=(32, )) categorical_features = layers.Embedding( input_dim=100, output_dim=64, input_length=16, )(categorical_input) categorical_features = layers.Reshape([16 * 64])(categorical_features) numeric_features = layers.Dense(64, activation='relu')(numeric_input) x = layers.Concatenate(axis=-1)([categorical_features, numeric_features]) x = layers.Dense(128, activation='relu')(x) binary_pred = layers.Dense(1, activation='sigmoid')(x) categorical_pred = layers.Dense(3, activation='softmax')(x) model = keras.Model( inputs=[categorical_input, numeric_input], outputs=[binary_pred, categorical_pred], ) model.summary()
В коде два входа
categorical_input
иnumeric_input
, после различных слоев обработки, два проходят черезConcatenate
Объединены вместе и, наконец, через разные слои обработки, чтобы получить два выхода.binary_pred
иcategorical_pred
. Структура модели показана на следующем рисунке: -
函数式 API
Еще одно хорошее применение — совместное использование слоев моделей, т. е. в модели, в которой слои повторно используются несколько раз, она изучает разные функции из разных входных данных. Общим общим слоем является слой внедрения (Embedding
), код показан ниже:from tensorflow import keras from tensorflow.keras import layers categorical_input_one = keras.Input(shape=(16, )) categorical_input_two = keras.Input(shape=(24, )) shared_embedding = layers.Embedding(100, 64) categorical_features_one = shared_embedding(categorical_input_one) categorical_features_two = shared_embedding(categorical_input_two) categorical_features_one = layers.Reshape([16 * 64])(categorical_features_one) categorical_features_two = layers.Reshape([16 * 64])(categorical_features_two) x = layers.Concatenate(axis=-1)([ categorical_features_one, categorical_features_two, ]) x = layers.Dense(128, activation='relu')(x) outputs = layers.Dense(1, activation='sigmoid')(x) model = keras.Model( inputs=[categorical_input_one, categorical_input_two], outputs=outputs, ) model.summary()
В коде два входа
categorical_input_one
иcategorical_input_two
, они разделяютEmbedding
Этажshared_embedding
. Структура модели показана на следующем рисунке:
Пользовательские слои и модели Keras
-
tf.keras
Под модулем много встроенных слоев (layers
), такой как тот, который мы использовали вышеDense
,Embedding
,Reshape
Ждать. Иногда мы обнаруживаем, что эти встроенные слои не соответствуют нашим потребностям, и очень удобно создавать собственные слои для расширения. пользовательские слои через наследованиеtf.keras.Layer
класс для реализации, а подкласс должен реализовать родительский классbuild
иcall
метод. для встроенногоDense
слой, если вы используете пользовательский слой для реализации, код выглядит следующим образом:import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers class CustomDense(layers.Layer): def __init__(self, units=32): super().__init__() self.units = units def build(self, input_shape): self.w = self.add_weight( shape=(input_shape[-1], self.units), initializer='random_normal', trainable=True, ) self.b = self.add_weight( shape=(self.units, ), initializer='random_normal', trainable=True, ) def call(self, inputs): return tf.matmul(inputs, self.w) + self.b def get_config(self): return {'units': self.units} @classmethod def from_config(cls, config): return cls(**config) inputs = keras.Input((4, )) layer = CustomDense(10) outputs = layer(inputs) model = keras.Model(inputs, outputs) model.summary() # layer recreate config = layer.get_config() new_layer = CustomDense.from_config(config) new_outputs = new_layer(inputs) print(new_layer.weights) print(new_layer.non_trainable_weights) print(new_layer.trainable_weights) # model recreate config = model.get_config() new_model = keras.Model.from_config( config, custom_objects={'CustomDense': CustomDense}, ) new_model.summary()
-
в
__init__
Метод используется для инициализации некоторых основных параметров, необходимых для построения слоя,build
метод создания весовой матрицы, необходимой для этого слояw
и матрица отклоненийb
,call
Методы являются реальными исполнителями построения слоев, превращая ввод в вывод и обратно. На самом деле, создание весовых матриц и т. д. также может быть выполнено в__init__
метод, но во многих случаях мы не можем заранее предсказать размерность входных данных, и нам нужно отложить создание весовой матрицы в определенной точке слоя инстанцирования, поэтому нам нужноbuild
Информация об измерении согласно входным данным в методеinput_shape
для динамического создания весовой матрицы. -
Последовательность вызова вышеуказанных трех методов следующая:
__init__
,build
,call
,в__init__
вызывается при создании экземпляра слоя, иbuild
иcall
вызывается после определения ввода. фактическиLayer
В классе есть встроенный метод__call__
, метод вызывается первым при построении слоя, а внутри методаbuild
иcall
, и только первый звонок__call__
сработает, когдаbuild
, то естьbuild
Переменные в могут быть созданы только один раз, в то время какcall
Его можно вызывать несколько раз, например, для обучения и оценки. -
Если вам нужна поддержка сериализации для этого уровня, вам нужно реализовать
get_config
метод для возврата параметров конструктора этого экземпляра слоя в виде словаря. в данномconfig
После словаря вы можете вызвать слой类方法 (classmethod) from_config
чтобы воссоздать слой,from_config
Реализация по умолчанию показана в коде, повторное создание слоя см.layer recreate
Кодовую часть, конечно, тоже можно переписатьfrom_config
методы класса для предоставления новых методов создания. при воссоздании новой модели (model
) код сlayer
Восстановленный код отличается, он требует помощиkeras.Model.from_config
способ завершения сборки, см.model recreate
раздел кода.
-
-
Пользовательские слои можно комбинировать рекурсивно, что означает, что один слой может использоваться как атрибут другого слоя. Обычно рекомендуется в
__init__
способ создания подслоя, потому что собственный подуровеньbuild
метод будет во внешнем слоеbuild
При вызове он запускается для построения матрицы весов без явного создания ее в родительском слое. Также кSequential Model
Модель, упомянутая в разделе, взята в качестве примера, а код выглядит следующим образом:from tensorflow import keras from tensorflow.keras import layers class MLP(layers.Layer): def __init__(self): super().__init__() self.dense_1 = layers.Dense(64, activation='relu') self.dense_2 = layers.Dense(64, activation='relu') self.dense_3 = layers.Dense(10) def call(self, inputs): x = self.dense_1(inputs) x = self.dense_2(x) x = self.dense_3(x) return x inputs = keras.Input((16, )) mlp = MLP() y = mlp(inputs) print('weights:', len(mlp.weights)) print('trainable weights:', len(mlp.trainable_weights))
Как видно из кода, мы поставили три
Dense
слой какMLP
подслои, а затем использовать их для завершенияMLP
, что может быть достигнуто сSequential Model
Тот же эффект, что и в , и матрицы весов всех подслоев будут существовать как матрицы весов нового слоя. -
Этаж (
layers
) во время процесса сборки, будет рекурсивно собирать потери, сгенерированные во время этого процесса сборки (losses
). переписываниеcall
метод, позвонивadd_loss
метод добавления пользовательских потерь. Все потери слоя включают в себя и потери его подслоев, и все они могут быть получены путемlayer.losses
свойство, которое представляет собой список (list
), следует отметить, что потеря регулярного члена включается автоматически. Пример кода выглядит следующим образом:import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers class CustomLayer(layers.Layer): def __init__(self, rate=1e-2, l2_rate=1e-3): super().__init__() self.rate = rate self.l2_rate = l2_rate self.dense = layers.Dense( units=32, kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) def call(self, inputs): self.add_loss(self.rate * tf.reduce_sum(inputs)) return self.dense(inputs) inputs = keras.Input((16, )) layer = CustomLayer() x = layer(inputs) print(layer.losses)
-
слой или модель
call
Предустановка метода имеетtraining
параметр, этоbool
Переменная типа, указывающая, находится ли она в состоянии обучения, установит значение в соответствии с вызываемым методом, когда обучение будетTrue
, когда оценивается какFalse
. потому что есть несколько слоев, таких какBatchNormalization
иDropout
Обычно он используется только в процессе обучения и обычно не используется в процессе оценки и прогнозирования, поэтому этот параметр можно использовать для управления различными процессами вычислений, выполняемыми моделью в разных состояниях. -
Пользовательская модель реализуется аналогично пользовательскому слою, но модель должна наследоваться от
tf.keras.Model
,Model
некоторые из классаAPI
С участиемLayer
Класс тот же, например, кастомная модель тоже должна быть реализована__init__
,build
иcall
метод. Однако между ними есть и различия.Model
Имеет интерфейсы обучения, оценки и прогнозирования, а во-вторых, к нему можно получить доступ черезmodel.layers
Просмотр информации обо всех встроенных слоях, а такжеModel
Класс также предоставляет интерфейс для сохранения и сериализации модели. отAutoEncoder
Например, пример кода для полной пользовательской модели выглядит следующим образом:from tensorflow import keras from tensorflow.keras import layers class Encoder(layers.Layer): def __init__(self, l2_rate=1e-3): super().__init__() self.l2_rate = l2_rate def build(self, input_shape): self.dense1 = layers.Dense( units=32, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) self.dense2 = layers.Dense( units=64, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) self.dense3 = layers.Dense( units=128, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) def call(self, inputs): x = self.dense1(inputs) x = self.dense2(x) x = self.dense3(x) return x class Decoder(layers.Layer): def __init__(self, l2_rate=1e-3): super().__init__() self.l2_rate = l2_rate def build(self, input_shape): self.dense1 = layers.Dense( units=64, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) self.dense2 = layers.Dense( units=32, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) self.dense3 = layers.Dense( units=16, activation='relu', kernel_regularizer=keras.regularizers.l2(self.l2_rate), ) def call(self, inputs): x = self.dense1(inputs) x = self.dense2(x) x = self.dense3(x) return x class AutoEncoder(keras.Model): def __init__(self): super().__init__() self.encoder = Encoder() self.decoder = Decoder() def call(self, inputs): x = self.encoder(inputs) x = self.decoder(x) return x model = AutoEncoder() model.build((None, 16)) model.summary() print(model.layers) print(model.weights)
Приведенный выше код реализует
AutoEncoder Model
класс, который состоит из двух слоев, а именноEncoder
иDecoder
, и эти два слоя также являются пользовательскими. позвонивmodel.weights
Вы можете просмотреть всю информацию о весе модели, конечно, вся информация о весе в подслое включена сюда. -
Для пользовательского слоя или модели при вызове его
summary
,weights
,variables
,trainable_weights
,losses
При ожидании метода или свойства убедитесь, что слой или модель созданы, иначе он может сообщить об ошибке или вернуть пустое значение.Обратите внимание на это при отладке модели.
Уровень конфигурации (уровень)
существуетtf.keras.layers
Под модулем находится множество предопределенных слоев, и большинство из этих слоев имеют одинаковые параметры конструктора. Ниже представлены некоторые часто используемые параметры.Чтобы узнать об уникальных параметрах каждого слоя и значении параметров, при их использовании вы можете запросить официальные документы.Объяснения документов, как правило, очень подробные.
-
activation
Относится к функции активации, которая может быть установлена в виде строки, такой какrelu
илиactivations
объектtf.keras.activations.relu()
, что по умолчаниюNone
, что означает линейную зависимость. -
kernel_initializer
иbias_initializer
, указывающий метод инициализации матрицы весов и матрицы смещения в слое, который можно задать в виде строки, напримерGlorotuniform
илиinitializers
объектtf.keras.initializers.GlorotUniform()
, что по умолчаниюGlorotuniform
метод инициализации. -
kernel_regularizer
иbias_regularizer
, указывающий метод регуляризации матрицы весов и матрицы отклонений, как описано выше, может бытьL1
илиL2
регуляризация, напримерtf.keras.regularizers.l2(1e-3)
, по умолчанию нет обычного термина.
Сравнение методов создания модели
-
При построении более простых моделей используйте
Sequential
Конечно способ самый удобный и быстрый, можно воспользоваться существующимLayer
Завершите процесс быстрого построения и проверки. -
Если модель более сложная, лучше использовать
函数式 API
или нестандартная модель. как правило函数式 API
Это более продвинутый, простой и безопасный способ реализации, а также он имеет некоторые функции, которых нет в пользовательских моделях. Однако пользовательские модели обеспечивают большую гибкость при построении моделей, которые нелегко представить в виде ориентированных ациклических графов. -
函数式 API
Проверка модели может быть выполнена заблаговременно, поскольку она проходитInput
Метод задает размерность входных данных модели заранее, поэтому, когда входные данные не соответствуют спецификации, они будут найдены раньше, что полезно для отладки, в то время как пользовательская модель не указывает размерность входных данных в начале. начало, оно основано на входных данных во время запущенного процесса. -
использовать
函数式 API
Модульность написания кода несильна, и его немного сложно читать, но, настроив модель, можно четко понять общую структуру модели, которую легко понять. -
В реальном использовании,
函数式 API
Используется в сочетании с пользовательскими моделями для удовлетворения наших различных потребностей в построении моделей.
Советы по созданию модели Keras
-
При написании кода модели вы можете ссылаться на методы построения моделей других людей, и иногда вы много выиграете.
-
ищете то, что вам нужно
tensorflow
метод, еслиkeras
Если в модуле предусмотрена реализация, этот метод будет использоваться первым, если нет, найтиtf
Достаточно метода под модулем, который может сделать код более совместимым и надежным. -
В процессе создания модели используйте встроенные методы и свойства моделей и слоев, такие как
summary
,weights
И т. д., чтобы мы могли посмотреть на структуру модели с глобальной точки зрения и помочь найти некоторые потенциальные проблемы. -
так как
TensorFlow 2.x
Модель использует значение по умолчаниюEager Execution
Механизм динамического графика для запуска кода, поэтому вы можете печатать прямо в любом месте кодаTensor
для просмотра его значений и размеров и другой информации, что очень полезно при отладке модели.