30天干掉tensorflow2.0-day24 构建模型的3种方法

构建模型的3种方法

可以使用以下3种方式构建模型:使用Sequential按层顺序构建模型,使用函数式API构建任意结构模型,继承Model基类构建自定义模型。

对于顺序结构的模型,优先使用Sequential方法构建。

如果模型有多输入或者多输出,或者模型需要共享权重,或者模型具有残差连接等非顺序结构,推荐使用函数式API进行创建。

如果无特定必要,尽可能避免使用Model子类化的方式构建模型,这种方式提供了极大的灵活性,但也有更大的概率出错。

下面以IMDB电影评论的分类问题为例,演示3种创建模型的方法。

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  # We will only consider the top 10,000 words in the dataset
MAX_LEN = 200  # We will cut reviews after 200 words
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)

一,Sequential按层顺序创建模型

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()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 200, 7)            70000     
_________________________________________________________________
conv1d (Conv1D)              (None, 196, 64)           2304      
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 98, 64)            0         
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 96, 32)            6176      
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 48, 32)            0         
_________________________________________________________________
flatten (Flatten)            (None, 1536)              0         
_________________________________________________________________
dense (Dense)                (None, 1)                 1537      
=================================================================
Total params: 80,017
Trainable params: 80,017
Non-trainable params: 0
_________________________________________________________________

在这里插入图片描述

import datetime
import os
baselogger = callbacks.BaseLogger(stateful_metrics=["AUC"])
logdir = os.path.join(".\\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])
Epoch 1/6
1000/1000 [==============================] - 29s 29ms/step - loss: 0.4580 - accuracy: 0.7522 - AUC: 0.8571 - val_loss: 0.3152 - val_accuracy: 0.8628 - val_AUC: 0.9399
Epoch 2/6
1000/1000 [==============================] - 21s 21ms/step - loss: 0.2368 - accuracy: 0.9050 - AUC: 0.9661 - val_loss: 0.3147 - val_accuracy: 0.8676 - val_AUC: 0.9446
Epoch 3/6
1000/1000 [==============================] - 20s 20ms/step - loss: 0.1561 - accuracy: 0.9419 - AUC: 0.9850 - val_loss: 0.3608 - val_accuracy: 0.8662 - val_AUC: 0.9397
Epoch 4/6
1000/1000 [==============================] - 21s 21ms/step - loss: 0.1000 - accuracy: 0.9635 - AUC: 0.9935 - val_loss: 0.4677 - val_accuracy: 0.8570 - val_AUC: 0.9302
Epoch 5/6
1000/1000 [==============================] - 25s 25ms/step - loss: 0.0559 - accuracy: 0.9808 - AUC: 0.9977 - val_loss: 0.6140 - val_accuracy: 0.8570 - val_AUC: 0.9196
Epoch 6/6
1000/1000 [==============================] - 26s 26ms/step - loss: 0.0316 - accuracy: 0.9898 - AUC: 0.9991 - val_loss: 0.7852 - val_accuracy: 0.8504 - val_AUC: 0.9089
%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")

在这里插入图片描述

二,函数式API创建任意结构模型

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"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
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 (SeparableCo (None, 196, 64)      547         embedding[0][0]                  
__________________________________________________________________________________________________
separable_conv1d_4 (SeparableCo (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 (SeparableCo (None, 64, 32)       2272        max_pooling1d[0][0]              
__________________________________________________________________________________________________
separable_conv1d_3 (SeparableCo (None, 35, 32)       2400        max_pooling1d_1[0][0]            
__________________________________________________________________________________________________
separable_conv1d_5 (SeparableCo (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 (GlobalM (None, 32)           0           separable_conv1d_3[0][0]         
__________________________________________________________________________________________________
global_max_pooling1d_2 (GlobalM (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]     
__________________________________________________________________________________________________
dense (Dense)                   (None, 1)            97          concatenate[0][0]                
==================================================================================================
Total params: 78,938
Trainable params: 78,938
Non-trainable params: 0
__________________________________________________________________________________________________

在这里插入图片描述

import datetime
logdir = os.path.join(".\\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])
Epoch 1/6
      1/Unknown - 3s 3s/step - loss: 0.6940 - accuracy: 0.3000 - AUC: 0.5000WARNING:tensorflow:Method (on_train_batch_end) is slow compared to the batch update (0.103473). Check your callbacks.
1000/1000 [==============================] - 44s 44ms/step - loss: 0.5254 - accuracy: 0.7077 - AUC: 0.8061 - val_loss: 0.3750 - val_accuracy: 0.8322 - val_AUC: 0.9183
Epoch 2/6
1000/1000 [==============================] - 31s 31ms/step - loss: 0.2952 - accuracy: 0.8745 - AUC: 0.9469 - val_loss: 0.3405 - val_accuracy: 0.8538 - val_AUC: 0.9318
Epoch 3/6
1000/1000 [==============================] - 29s 29ms/step - loss: 0.2053 - accuracy: 0.9195 - AUC: 0.9743 - val_loss: 0.3667 - val_accuracy: 0.8548 - val_AUC: 0.9305
Epoch 4/6
1000/1000 [==============================] - 32s 32ms/step - loss: 0.1334 - accuracy: 0.9527 - AUC: 0.9888 - val_loss: 0.4461 - val_accuracy: 0.8474 - val_AUC: 0.9254
Epoch 5/6
1000/1000 [==============================] - 32s 32ms/step - loss: 0.0800 - accuracy: 0.9756 - AUC: 0.9953 - val_loss: 0.5410 - val_accuracy: 0.8448 - val_AUC: 0.9180
Epoch 6/6
1000/1000 [==============================] - 32s 32ms/step - loss: 0.0407 - accuracy: 0.9901 - AUC: 0.9983 - val_loss: 0.7223 - val_accuracy: 0.8356 - val_AUC: 0.9069
plot_metric(history,"AUC")

在这里插入图片描述

三,Model子类化创建自定义模型

# 先自定义一个残差模块,为自定义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       
=================================================================
Total params: 103,197
Trainable params: 103,197
Non-trainable params: 0
_________________________________________________________________
import datetime

logdir = os.path.join(".\\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])
Epoch 1/6
1000/1000 [==============================] - 66s 66ms/step - loss: 0.5019 - accuracy: 0.7181 - AUC: 0.8201 - val_loss: 0.3386 - val_accuracy: 0.8508 - val_AUC: 0.9339
Epoch 2/6
1000/1000 [==============================] - 61s 61ms/step - loss: 0.2442 - accuracy: 0.8997 - AUC: 0.9637 - val_loss: 0.3270 - val_accuracy: 0.8640 - val_AUC: 0.9402
Epoch 3/6
1000/1000 [==============================] - 73s 73ms/step - loss: 0.1469 - accuracy: 0.9464 - AUC: 0.9863 - val_loss: 0.3967 - val_accuracy: 0.8576 - val_AUC: 0.9357
Epoch 4/6
1000/1000 [==============================] - 63s 63ms/step - loss: 0.0738 - accuracy: 0.9755 - AUC: 0.9959 - val_loss: 0.5937 - val_accuracy: 0.8574 - val_AUC: 0.9198
Epoch 5/6
1000/1000 [==============================] - 64s 64ms/step - loss: 0.0330 - accuracy: 0.9895 - AUC: 0.9990 - val_loss: 0.8821 - val_accuracy: 0.8546 - val_AUC: 0.9051
Epoch 6/6
1000/1000 [==============================] - 61s 61ms/step - loss: 0.0189 - accuracy: 0.9938 - AUC: 0.9995 - val_loss: 1.0229 - val_accuracy: 0.8462 - val_AUC: 0.8986
plot_metric(history,"AUC")

在这里插入图片描述

原创文章 58 获赞 7 访问量 6188

猜你喜欢

转载自blog.csdn.net/Elenstone/article/details/105805067