tensorflow Keras的搭建训练步骤

一、数据集加载

1.图片数据

方法1:数据管道Datasets

创建 load_image的映射函数

import tensorflow as tf 
from tensorflow.keras import datasets,layers,models

BATCH_SIZE = 100

def load_image(img_path,size = (32,32)):
    label = tf.constant(1,tf.int8) if tf.strings.regex_full_match(img_path,".*automobile.*") \
            else tf.constant(0,tf.int8)
    img = tf.io.read_file(img_path)
    img = tf.image.decode_jpeg(img) #注意此处为jpeg格式
    img = tf.image.resize(img,size)/255.0
    return(img,label)
#使用并行化预处理num_parallel_calls 和预存数据prefetch来提升性能
ds_train = tf.data.Dataset.list_files("../../data/cifar2/train/*/*.jpg") \
           .map(load_image, num_parallel_calls=tf.data.experimental.AUTOTUNE) \
           .shuffle(buffer_size = 1000).batch(BATCH_SIZE) \
           .prefetch(tf.data.experimental.AUTOTUNE)  

ds_test = tf.data.Dataset.list_files("../../data/cifar2/test/*/*.jpg") \
           .map(load_image, num_parallel_calls=tf.data.experimental.AUTOTUNE) \
           .batch(BATCH_SIZE) \
           .prefetch(tf.data.experimental.AUTOTUNE)  

另外还可以用:tf.data.TFRecordDataset加载tfrecords,以及tf.data.Dataset.from_tensor_slices从python list中加载。

方法2:生成器generator

(1)利用函数tf.keras.preprocessing.image.ImageDataGenerator()生成

函数原型:

tf.keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=False, samplewise_center=False,
    featurewise_std_normalization=False, samplewise_std_normalization=False,
    zca_whitening=False, zca_epsilon=1e-06, rotation_range=0, width_shift_range=0.0,
    height_shift_range=0.0, brightness_range=None, shear_range=0.0, zoom_range=0.0,
    channel_shift_range=0.0, fill_mode='nearest', cval=0.0,
    horizontal_flip=False, vertical_flip=False, rescale=None,
    preprocessing_function=None, data_format=None, validation_split=0.0, dtype=None
)

a.结合 flow_from_director(),仅加载源图像:

train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
        'data/train',
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
        'data/validation',
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
model.fit(
        train_generator,
        steps_per_epoch=2000,
        epochs=50,
        validation_data=validation_generator,
        validation_steps=800)

b.用于实例分割或者语义分割,同时加载图像和MASK

# we create two instances with the same arguments
data_gen_args = dict(featurewise_center=True,
                     featurewise_std_normalization=True,
                     rotation_range=90,
                     width_shift_range=0.1,
                     height_shift_range=0.1,
                     zoom_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
# Provide the same seed and keyword arguments to the fit and flow methods
seed = 1
image_datagen.fit(images, augment=True, seed=seed)
mask_datagen.fit(masks, augment=True, seed=seed)
image_generator = image_datagen.flow_from_directory(
    'data/images',
    class_mode=None,
    seed=seed)
mask_generator = mask_datagen.flow_from_directory(
    'data/masks',
    class_mode=None,
    seed=seed)
# combine generators into one which yields image and masks
train_generator = zip(image_generator, mask_generator)
model.fit(
    train_generator,
    steps_per_epoch=2000,
    epochs=50)

(2)利用python的生成器

利用yield生成数据,这是python的高级特性;tensorflow版本的MASK-RCNN就是这种加载数据集的方式。

def generate_batch_data_random(x, y, batch_size):
	ylen = len(y)
	loopcount = ylen // batch_size
	while (True):
		i = randint(0,loopcount)
		yield x[i * batch_size:(i + 1) * batch_size], y[i * batch_size:(i + 1) * batch_size]

train_generator = generate_batch_data_random(x_train, y_train, batch_size)
test_generator = generate_batch_data_random(x_test, y_test, batch_size)

2.文本数据

keras的函数tf.keras.preprocessing.text_dataset_from_directory

tf.keras.preprocessing.text_dataset_from_directory(
    directory, labels='inferred', label_mode='int',
    class_names=None, batch_size=32, max_length=None, shuffle=True, seed=None,
    validation_split=None, subset=None, follow_links=False
)

或者tf的函数tf.data.TextLineDataset

tf.data.TextLineDataset(
    filenames, compression_type=None, buffer_size=None, num_parallel_reads=None
)

使用方式:

dataset = tf.data.TextLineDataset(['/tmp/text_lines0.txt',
                                   '/tmp/text_lines1.txt'])

二、模型的构建

1.利用网络的API直接搭建,从INPUT开始

import tensorflow as tf

#MODEL
inputs = tf.keras.Input(shape=(3,))
x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(inputs)
outputs = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)

model = tf.keras.Model(inputs=inputs, outputs=outputs)

2.自定义model

继承tf.keras.Model

import tensorflow as tf

class MyModel(tf.keras.Model):

  def __init__(self):
    super(MyModel, self).__init__()
    self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)
    self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)

  def call(self, inputs):
    x = self.dense1(inputs)
    return self.dense2(x)

model = MyModel()
model.build(input_shape = (None,100))

3.自定义Layer

重要的三个函数:__init__,build,call;__init__是初始化函数,可以把网络放到此函数中初始化化,build函数可以用来初始化网络层以及创建参数,call函数是实际网络的部分。
例1:

class SimpleDense(Layer):

  def __init__(self, units=32):
      super(SimpleDense, self).__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)
      super(SimpleDense,self).build(input_shape) #self.built = True

  def call(self, inputs):
      return tf.matmul(inputs, self.w) + self.b

例2:

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
        
resblock = ResBlock(kernel_size = 3)
resblock.build(input_shape = (None,200,7))

4.利用提供的网络模型

函数:

DenseNet121(...): Instantiates the Densenet121 architecture.

DenseNet169(...): Instantiates the Densenet169 architecture.

DenseNet201(...): Instantiates the Densenet201 architecture.

EfficientNetB0(...): Instantiates the EfficientNetB0 architecture.

EfficientNetB1(...): Instantiates the EfficientNetB1 architecture.

EfficientNetB2(...): Instantiates the EfficientNetB2 architecture.

EfficientNetB3(...): Instantiates the EfficientNetB3 architecture.

EfficientNetB4(...): Instantiates the EfficientNetB4 architecture.

EfficientNetB5(...): Instantiates the EfficientNetB5 architecture.

EfficientNetB6(...): Instantiates the EfficientNetB6 architecture.

EfficientNetB7(...): Instantiates the EfficientNetB7 architecture.

InceptionResNetV2(...): Instantiates the Inception-ResNet v2 architecture.

InceptionV3(...): Instantiates the Inception v3 architecture.

MobileNet(...): Instantiates the MobileNet architecture.

MobileNetV2(...): Instantiates the MobileNetV2 architecture.

MobileNetV3Large(...): Instantiates the MobileNetV3Large architecture.

MobileNetV3Small(...): Instantiates the MobileNetV3Small architecture.

NASNetLarge(...): Instantiates a NASNet model in ImageNet mode.

NASNetMobile(...): Instantiates a Mobile NASNet model in ImageNet mode.

ResNet101(...): Instantiates the ResNet101 architecture.

ResNet101V2(...): Instantiates the ResNet101V2 architecture.

ResNet152(...): Instantiates the ResNet152 architecture.

ResNet152V2(...): Instantiates the ResNet152V2 architecture.

ResNet50(...): Instantiates the ResNet50 architecture.

ResNet50V2(...): Instantiates the ResNet50V2 architecture.

VGG16(...): Instantiates the VGG16 model.

VGG19(...): Instantiates the VGG19 architecture.

Xception(...): Instantiates the Xception architecture.

三、模型的编译(定义优化方法、损失函数、评价)

例:

#定义损失函数
def myloss(y_true,y_pred):
    return tf.reduce_mean(y_pred)
#定义优化器
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
#编译
#1
model.compile(optimizer = optimizer ,loss = myloss)
#2
model.compile(optimizer='Nadam',
            loss='binary_crossentropy',
            metrics=['accuracy',"AUC"])

内置优化器:

Adadelta: Optimizer that implements the Adadelta algorithm.

Adagrad: Optimizer that implements the Adagrad algorithm.

Adam: Optimizer that implements the Adam algorithm.

Adamax: Optimizer that implements the Adamax algorithm.

Ftrl: Optimizer that implements the FTRL algorithm.

Nadam: Optimizer that implements the NAdam algorithm.

RMSprop: Optimizer that implements the RMSprop algorithm.

SGD: Gradient descent (with momentum) optimizer.

内置损失函数:

KLD(...):计算y_true和之间的 Kullback-Leibler 散度损失y_pred。

MAE(...):计算标签和预测之间的平均绝对误差。

MAPE(...):计算y_true和之间的平均绝对百分比误差y_pred。

MSE(...):计算标签和预测之间的均方误差。

MSLE(...):计算y_true和之间的均方对数误差y_pred。

binary_crossentropy(...):计算二元交叉熵损失。

categorical_crossentropy(...):计算分类交叉熵损失。

categorical_hinge(...):计算y_true和之间的分类铰链损失y_pred。

cosine_similarity(...):计算标签和预测之间的余弦相似度。

deserialize(...):反序列化一个序列化的损失类/函数实例。

get(...):检索 Keras 损失作为function/Loss类实例。

hinge(...):计算y_true和之间的铰链损失y_pred。

huber(...):计算 Huber 损失值。

kl_divergence(...):计算y_true和之间的 Kullback-Leibler 散度损失y_pred。

kld(...):计算y_true和之间的 Kullback-Leibler 散度损失y_pred。

kullback_leibler_divergence(...):计算y_true和之间的 Kullback-Leibler 散度损失y_pred。

log_cosh(...):预测误差的双曲余弦的对数。

logcosh(...):预测误差的双曲余弦的对数。

mae(...):计算标签和预测之间的平均绝对误差。

mape(...):计算y_true和之间的平均绝对百分比误差y_pred。

mean_absolute_error(...):计算标签和预测之间的平均绝对误差。

mean_absolute_percentage_error(...):计算y_true和之间的平均绝对百分比误差y_pred。

mean_squared_error(...):计算标签和预测之间的均方误差。

mean_squared_logarithmic_error(...):计算y_true和之间的均方对数误差y_pred。

mse(...):计算标签和预测之间的均方误差。

msle(...):计算y_true和之间的均方对数误差y_pred。

poisson(...):计算 y_true 和 y_pred 之间的泊松损失。

serialize(...):序列化损失函数或Loss实例。

sparse_categorical_crossentropy(...):计算稀疏分类交叉熵损失。

squared_hinge(...):计算y_true和之间的平方铰链损失y_pred。

自定义损失函数

a.函数的形式

例:

def loss(y_true, y_pred,num):
    y_true_f = y_true.flatten()
    y_pred_f = y_pred.flatten()
    loss = 0
    count=0
    for i in range(len(y_true_f)):
        if y_true_f[i] > num:
            loss += abs(y_true_f[i] - y_pred_f[i])
            count+=1
        else:
            pass
    return loss/count

另外还可以用model.add_loss()model.add_metric()函数添加损失函数和评估指标。

b.类的形式

继承Loss类,重写call函数,利用y_truey_pred计算损失值。

例:

class MeanSquaredError(Loss):

  def call(self, y_true, y_pred):
    y_pred = tf.convert_to_tensor_v2(y_pred)
    y_true = tf.cast(y_true, y_pred.dtype)
    return tf.reduce_mean(math_ops.square(y_pred - y_true), axis=-1)

四、回调函数callback

内置回调函数的类:

class BaseLogger:累积指标的时代平均值的回调。

class CSVLogger:将纪元结果流式传输到 CSV 文件的回调。

class Callback:用于构建新回调的抽象基类。

class CallbackList: 抽象回调列表的容器。

class EarlyStopping:当受监控的指标停止改进时停止训练。

class History: 将事件记录到History对象中的回调。

class LambdaCallback:用于即时创建简单的自定义回调的回调。

class LearningRateScheduler:学习率调度程序。

class ModelCheckpoint:回调以在某个频率保存 Keras 模型或模型权重。

class ProgbarLogger:将指标打印到标准输出的回调。

class ReduceLROnPlateau:当指标停止改进时降低学习率。

class RemoteMonitor: 用于将事件流式传输到服务器的回调。

class TensorBoard:为 TensorBoard 启用可视化。

class TerminateOnNaN:遇到 NaN 损失时终止训练的回调。

自定义回调函数

继承tf.keras.callbacks.Callback重写以下函数实现自定义:

class MyCallback(tf.keras.callbacks.Callback):
  def set_params(self, params):
    self.params = params
  def set_model(self, model):
    self.model = model
    
  def on_batch_begin(self, batch, logs=None):
  def on_batch_end(self, batch, logs=None):
  
  def on_epoch_begin(self, epoch, logs=None):
  def on_epoch_end(self, epoch, logs=None):
  
  def on_train_batch_begin(self, batch, logs=None):
  def on_train_batch_end(self, batch, logs=None):
  
  def on_test_batch_begin(self, batch, logs=None):
  def on_test_batch_end(self, batch, logs=None):
  
  def on_predict_batch_begin(self, batch, logs=None):
  def on_predict_batch_end(self, batch, logs=None):
  
  def on_train_begin(self, logs=None):
  def on_train_end(self, logs=None):
  
  def on_test_begin(self, logs=None):
  def on_test_end(self, logs=None):
  
  def on_predict_begin(self, logs=None):
  def on_predict_end(self, logs=None):

例:

  >>> training_finished = False
  >>> class MyCallback(tf.keras.callbacks.Callback):
  ...   def on_train_end(self, logs=None):
  ...     global training_finished
  ...     training_finished = True
  >>> model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
  >>> model.compile(loss='mean_squared_error')
  >>> model.fit(tf.constant([[1.0]]), tf.constant([[1.0]]),
  ...           callbacks=[MyCallback()])
  >>> assert training_finished == True

五、模型的训练

1.fit

函数原型:

fit(
    x=None, y=None, batch_size=None, epochs=1, verbose='auto',
    callbacks=None, validation_split=0.0, validation_data=None, shuffle=True,
    class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None,
    validation_steps=None, validation_batch_size=None, validation_freq=1,
    max_queue_size=10, workers=1, use_multiprocessing=False
)

2.train_on_batch

train_on_batch(
    x, y=None, sample_weight=None, class_weight=None, reset_metrics=True,
    return_dict=False
)

例:

def train_model(model,ds_train,ds_valid,epoches):

    for epoch in tf.range(1,epoches+1):
        model.reset_metrics()

        # 在后期降低学习率
        if epoch == 5:
            model.optimizer.lr.assign(model.optimizer.lr/2.0)
            tf.print("Lowering optimizer Learning Rate...\n\n")

        for x, y in ds_train:
            train_result = model.train_on_batch(x, y)

        for x, y in ds_valid:
            valid_result = model.test_on_batch(x, y,reset_metrics=False)

        if epoch%1 ==0:
            printbar()
            tf.print("epoch = ",epoch)
            print("train:",dict(zip(model.metrics_names,train_result)))
            print("valid:",dict(zip(model.metrics_names,valid_result)))
            print("")

3.apply_gradients

分为三步:
1.使用tf.GradientTape()计算梯度
2.处理得到的梯度
3.用apply_gradients函数应用处理过的梯度

例1:

# Create an optimizer.
opt = tf.keras.optimizers.SGD(learning_rate=0.1)

# Compute the gradients for a list of variables.
with tf.GradientTape() as tape:
  loss = <call_loss_function>
vars = <list_of_variables>
grads = tape.gradient(loss, vars)

# Process the gradients, for example cap them, etc.
# capped_grads = [MyCapper(g) for g in grads]
processed_grads = [process_gradient(g) for g in grads]

# Ask the optimizer to apply the processed gradients.
opt.apply_gradients(zip(processed_grads, var_list))

例2:

def train_step(model, features, labels):
    with tf.GradientTape() as tape:
        predictions = model(features,training = True)
        loss = loss_func(labels, predictions)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    train_loss.update_state(loss)
    train_metric.update_state(labels, predictions)

4.optimizer.minimize

例:

# Create an optimizer with the desired parameters.
opt = tf.keras.optimizers.SGD(learning_rate=0.1)
# `loss` is a callable that takes no argument and returns the value
# to minimize.
loss = lambda: 3 * var1 * var1 + 2 * var2 * var2
# 在静态图中
# In graph mode, returns op that minimizes the loss by updating the listed
# variables.
opt_op = opt.minimize(loss, var_list=[var1, var2])
opt_op.run()

如果是动态图可以直接执行:

# In eager mode, simply call minimize to update the list of variables.
opt.minimize(loss, var_list=[var1, var2])

 
 

参考链接:

1.https://tensorflow.google.cn/versions/r2.5/api_docs/python/tf/keras
2.https://jackiexiao.github.io/eat_tensorflow2_in_30_days/chinese/

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值