Можно использовать три способа для построения модели: использовать Sequential для последовательного построения модели по слоям, использовать функциональный API для создания моделей произвольной структуры, наследовать от базового класса Model для создания пользовательских моделей.
Для моделей с последовательной структурой предпочтительно использовать метод Sequential.
Если модель имеет несколько входов или выходов, либо модели требуется совместное использование весов, либо модель имеет не последовательные структуры, такие как остаточные соединения, рекомендуется использовать для создания функциональный API.
По возможности избегайте использования наследования от класса Model для построения моделей без особой необходимости, хотя этот способ и обеспечивает большую гибкость, но также увеличивает вероятность ошибок.
Ниже мы проиллюстрируем три метода создания моделей на примере задачи классификации отзывов о фильмах IMDB.
import numpy as np
import pandas as pd
import tensorflow as tf
from tqdm import tqdm
from tensorflow.keras import *
train_token_path = "./data/imdb/train_token.csv"
test_token_path = "./data/imdb/test_token.csv"
MAX_WORDS = 10000 # Мы будем рассматривать только первые 10 000 слов в наборе данных
MAX_LEN = 200 # Мы обрежем отзывы после 200 слов
BATCH_SIZE = 20
# Построение конвейера
def parse_line(line):
t = tf.strings.split(line,"\t")
label = tf.reshape(tf.cast(tf.strings.to_number(t[0]),tf.int32),(-1,))
features = tf.cast(tf.strings.to_number(tf.strings.split(t[1]," ")),tf.int32)
return (features,label)
ds_train= tf.data.TextLineDataset(filenames = [train_token_path]) \
.map(parse_line,num_parallel_calls = tf.data.experimental.AUTOTUNE) \
.shuffle(buffer_size = 1000).batch(BATCH_SIZE) \
.prefetch(tf.data.experimental.AUTOTUNE)
ds_test= tf.data.TextLineDataset(filenames = [test_token_path]) \
.map(parse_line,num_parallel_calls = tf.data.experimental.AUTOTUNE) \
.shuffle(buffer_size = 1000).batch(BATCH_SIZE) \
.prefetch(tf.data.experimental.AUTOTUNE)
tf.keras.backend.clear_session()
model = models.Sequential()
model.add(layers.Embedding(MAX_WORDS,7,input_length=MAX_LEN))
model.add(layers.Conv1D(filters = 64,kernel_size = 5,activation = "relu"))
model.add(layers.MaxPool1D(2))
model.add(layers.Conv1D(filters = 32,kernel_size = 3,activation = "relu"))
model.add(layers.MaxPool1D(2))
model.add(layers.Flatten())
model.add(layers.Dense(1,activation = "sigmoid"))
model.compile(optimizer='Nadam',
loss='binary_crossentropy',
metrics=['accuracy',"AUC"])
model.summary()
import datetime
baselogger = callbacks.BaseLogger(stateful_metrics=["AUC"])
logdir = "./data/keras_model/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
history = model.fit(ds_train,validation_data = ds_test,
epochs = 6,callbacks=[baselogger,tensorboard_callback])
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import matplotlib.pyplot as plt
def plot_metric(history, metric):
train_metrics = history.history[metric]
val_metrics = history.history['val_'+metric]
epochs = range(1, len(train_metrics) + 1)
plt.plot(epochs, train_metrics, 'bo--')
plt.plot(epochs, val_metrics, 'ro-')
plt.title('Training and validation '+ metric)
plt.xlabel("Epochs")
plt.ylabel(metric)
plt.legend(["train_"+metric, 'val_'+metric])
plt.show()
plot_metric(history,"AUC")
tf.keras.backend.clear_session()
inputs = layers.Input(shape=[MAX_LEN])
x = layers.Embedding(MAX_WORDS,7)(inputs)
branch1 = layers.SeparableConv1D(64,3,activation="relu")(x)
branch1 = layers.MaxPool1D(3)(branch1)
branch1 = layers.SeparableConv1D(32,3,activation="relu")(branch1)
branch1 = layers.GlobalMaxPool1D()(branch1)
branch2 = layers.SeparableConv1D(64,5,activation="relu")(x)
branch2 = layers.MaxPool1D(5)(branch2)
branch2 = layers.SeparableConv1D(32,5,activation="relu")(branch2)
branch2 = layers.GlobalMaxPool1D()(branch2)
branch3 = layers.SeparableConv1D(64,7,activation="relu")(x)
branch3 = layers.MaxPool1D(7)(branch3)
branch3 = layers.SeparableConv1D(32,7,activation="relu")(branch3)
branch3 = layers.GlobalMaxPool1D()(branch3)
concat = layers.Concatenate()([branch1,branch2,branch3])
outputs = layers.Dense(1,activation = "sigmoid")(concat)
model = models.Model(inputs = inputs,outputs = outputs)
model.compile(optimizer='Nadam',
loss='binary_crossentropy', ```
metrics=['accuracy',"AUC"])
model.summary()
Model: "model"
input_1 (InputLayer) [(None, 200)] 0
embedding (Embedding) (None, 200, 7) 70000 input_1[0][0]
separable_conv1d (SeparableConv) (None, 198, 64) 533 embedding[0][0]
separable_conv1d_2 (SeparableConv) (None, 196, 64) 547 embedding[0][0]
separable_conv1d_4 (SeparableConv) (None, 194, 64) 561 embedding[0][0]
max_pooling1d (MaxPooling1D) (None, 66, 64) 0 separable_conv1d[0][0]
max_pooling1d_1 (MaxPooling1D) (None, 39, 64) 0 separable_conv1d_2[0][0]
max_pooling1d_2 (MaxPooling1D) (None, 27, 64) 0 separable_conv1d_4[0][0]
separable_conv1d_1 (SeparableConv) (None, 64, 32) 2272 max_pooling1d[0][0]
separable_conv1d_3 (SeparableConv) (None, 35, 32) 2400 max_pooling1d_1[0][0]
separable_conv1d_5 (SeparableConv) (None, 21, 32) 2528 max_pooling1d_2[0][0]
global_max_pooling1d (GlobalMax) (None, 32) 0 separable_conv1d_1[0][0]
global_max_pooling1d_1 (GlobalMax) (None, 32) 0 separable_conv1d_3[0][0]
global_max_pooling1d_2 (GlobalMax) (None, 32) 0 separable_conv1d_5[0][0]
concatenate (Concatenate) (None, 96) 0 global_max_pooling1d[0][0]
global_max_pooling1d_1[0][0]
global_max_pooling1d_2[0][0]
Всего параметров: 78 938 Обучаемых параметров: 78 938 Необучаемых параметров: 0
```python
import datetime
logdir = "./data/keras_model/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback =
``` ```
tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
history = model.fit(ds_train, validation_data=ds_test, epochs=6, callbacks=[tensorboard_callback])
Эпоха 1/6
1000/1000 [==============================] - 32с 32мс/шаг - потери: 0.5527 - точность: 0.6758 - AUC: 0.7731 - val_loss: 0.3646 - val_accuracy: 0.8426 - val_AUC: 0.9192
Эпоха 2/6
1000/1000 [==============================] - 24с 24мс/шаг - потери: 0.3024 - точность: 0.8737 - AUC: 0.9444 - val_loss: 0.3281 - val_accuracy: 0.8644 - val_AUC: 0.9350
Эпоха 3/6
1000/1000 [==============================] - 24с 24мс/шаг - потери: 0.2158 - точность: 0.9159 - AUC: 0.9715 - val_loss: 0.3461 - val_accuracy: 0.8666 - val_AUC: 0.9363
Эпоха 4/6
1000/1000 [==============================] - 24с 24мс/шаг - потери: 0.1492 - точность: 0.9464 - AUC: 0.9859 - val_loss: 0.4017 - val_accuracy: 0.8568 - val_AUC: 0.9311
Эпоха 5/6
1000/1000 [==============================] - 24с 24мс/шаг - потери: 0.0944 - точность: 0.9696 - AUC: 0.9939 - val_loss: 0.4998 - val_accuracy: 0.8550 - val_AUC: 0.9233
Эпоха 6/6
1000/1000 [==============================] - 26с 26мс/шаг - потери: 0.0526 - точность: 0.9865 - AUC: 0.9977 - val_loss: 0.6463 - val_accuracy: 0.8462 - val_AUC: 0.9138
plot_metric(history, "AUC")
# 先自定义一个残差模块,为自定义Layer
class ResBlock(layers.Layer):
def __init__(self, kernel_size, **kwargs):
super(ResBlock, self).__init__(**kwargs)
self.kernel_size = kernel_size
def build(self, input_shape):
self.conv1 = layers.Conv1D(filters=64, kernel_size=self.kernel_size,
activation="relu", padding="same")
self.conv2 = layers.Conv1D(filters=32, kernel_size=self.kernel_size,
activation="relu", padding="same")
self.conv3 = layers.Conv1D(filters=input_shape[-1],
kernel_size=self.kernel_size, activation="relu", padding="same")
self.maxpool = layers.MaxPool1D(2)
super(ResBlock,self).build(input_shape) # 相当于设置self.built = True
def call(self, inputs):
x = self.conv1(inputs)
x = self.conv2(x)
x = self.conv3(x)
x = layers.Add()([inputs, x])
x = self.maxpool(x)
return x
# 如果要让自定义的Layer通过Functional API 组合成模型时可以序列化,需要自定义get_config方法。
def get_config(self):
config = super(ResBlock, self).get_config()
config.update({'kernel_size': self.kernel_size})
return config
# 测试ResBlock
resblock = ResBlock(kernel_size=3)
resblock.build(input_shape=(None, 200, 7))
resblock.compute_output_shape(input_shape=(None, 200, 7))
TensorShape([None, 100, 7])
# 自定义模型,实际上也可以使用Sequential或者FunctionalAPI
class ImdbModel(models.Model):
def __init__(self):
super(ImdbModel, self).__init__()
def build(self,input_shape):
self.embedding = layers.Embedding(MAX_WORDS, 7)
self.block1 = ResBlock(7)
self.block2 = ResBlock(5)
self.dense = layers.Dense(1,activation="sigmoid")
super(ImdbModel,self).build(input_shape)
def call(self, x):
x = self.embedding(x)
x = self.block1(x)
x = self.block2(x)
x = layers.Flatten()(x)
x = self.dense(x)
return(x)
tf.keras.backend.clear_session()
model = ImdbModel()
model.build(input_shape =(None,200))
model.summary()
model.compile(optimizer='Nadam',
loss='binary_crossentropy',
metrics=['accuracy',"AUC"])
Model: "imdb_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) multiple 70000
_________________________________________________________________
res_block (ResBlock) multiple 19143
``` ```
res_block_1 (ResBlock) multiple 13703
_________________________________________________________________
dense (Dense) multiple 351
=================================================================
Всего параметров: 103,197
Обучаемые параметры: 103,197
Необучаемые параметры: 0
_________________________________________________________________
import datetime
logdir = "./tflogs/keras_model/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
history = model.fit(ds_train,validation_data = ds_test,
epochs = 6,callbacks=[tensorboard_callback])
Эпоха 1/6
1000/1000 [==============================] - 47с 47мс/шаг - потеря: 0.5629 - точность: 0.6618 - AUC: 0.7548 - val_loss: 0.3422 - val_accuracy: 0.8510 - val_AUC: 0.9286
Эпоха 2/6
1000/1000 [==============================] - 43с 43мс/шаг - потеря: 0.2648 - точность: 0.8903 - AUC: 0.9576 - val_loss: 0.3276 - val_accuracy: 0.8650 - val_AUC: 0.9410
Эпоха 3/6
1000/1000 [==============================] - 42с 42мс/шаг - потеря: 0.1573 - точность: 0.9439 - AUC: 0.9846 - val_loss: 0.3861 - val_accuracy: 0.8682 - val_AUC: 0.9390
Эпоха 4/6
1000/1000 [==============================] - 42с 42мс/шаг - потеря: 0.0849 - точность: 0.9706 - AUC: 0.9950 - val_loss: 0.5324 - val_accuracy: 0.8616 - val_AUC: 0.9292
Эпоха 5/6
1000/1000 [==============================] - 43с 43мс/шаг - потеря: 0.0393 - точность: 0.9876 - AUC: 0.9986 - val_loss: 0.7693 - val_accuracy: 0.8566 - val_AUC: 0.9132
Эпоха 6/6
1000/1000 [==============================] - 44с 44мс/шаг - потеря: 0.0222 - точность: 0.9926 - AUC: 0.9994 - val_loss: 0.9328 - val_accuracy: 0.8584 - val_AUC: 0.9052
plot_metric(history,"AUC")
Если у вас есть какие-либо вопросы по содержанию этой книги, пожалуйста, оставьте комментарий в нашем публичном аккаунте «Алгоритмная кухня». Автор ответит вам, когда у него будет время.
Вы также можете ответить ключевым словом join на заднем плане публичного аккаунта, чтобы присоединиться к группе читателей и обсудить с ними.

Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )