目录
一、数据集加载
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_true
和 y_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/