1. 模型构建Model和Layer

使用了 Keras 的 Subclassing API 建立模型,即对 tf.keras.Model类进行扩展以定义自己的新模型,同时手工编写了训练和评估模型的流程。这种方式灵活度高,且与其他流行的深度学习框架(如 PyTorch、Chainer)共通,是本手册所推荐的方法。

1.1 模型构建

class MyModel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        # 此处添加初始化代码(包含 call 方法中会用到的层),例如
        # layer1 = tf.keras.layers.BuiltInLayer(...)
        # layer2 = MyCustomLayer(...)

    def call(self, input):
        # 此处添加模型调用的代码(处理输入并返回输出),例如
        # x = layer1(input)
        # output = layer2(x)
        return output

通过 model = Model()实例化后,通过model.variables获得模型中的所有变量

model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for i in range(100):
    with tf.GradientTape() as tape:
        y_pred = model(X)
        loss = tf.reduce_mean(tf.square(y_pred - y))
    # 使用 model.variables 这一属性直接获得模型中的所有变量
    grads = tape.gradient(loss, model.variables)
    optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
print(model.variables)

1.2 Model的属性

model.layers:

获得模型结构列表

model.inputs:

获得模型输入张量列表

model.ouputs:

模型输出张量列表

model.summary:

打印模型的摘要信息

1.3 模型训练

见1.1

1.4 模型评估

y_pred = model.predict(data_loader.test_data)

定义评估函数

sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
# 定义测试数据集一共批次的大小
sparse_categorical_accuracy.update_state(y_true=data_loader.test_label, y_pred=y_pred)
print("测试准确率: %f" % sparse_categorical_accuracy.result())

2. TF 搭建CNN网络

2.1 迁移学习

model = tf.keras.applications.MobileNetV2(weights=None, classes=5)

实例化时所需要的参数:
input_shape :输入张量的形状(不含第一维的 Batch),大多默认为 224 × 224 × 3 。一般而言,模型对输入张量的大小有下限,长和宽至少为 32 × 32 或 75 × 75 ;
include_top :在网络的最后是否包含全连接层,默认为 True ;

weights :预训练权值,默认为 ‘imagenet’ ,即为当前模型载入在 ImageNet 数据集上预训练的权值。如需随机初始化变量可设为 None ;

classes :分类数,默认为 1000。修改该参数需要 include_top 参数为 True 且 weights 参数为 None 。

当执行以上代码时,TensorFlow 会自动从网络上下载 MobileNetV2 网络结构,因此在第一次执行代码时需要具备网络连接。

3 keras pipline 与自定义模型

使用了 Keras 的 Subclassing API 建立模型,即对 tf.keras.Model类进行扩展以定义自己的新模型,同时手工编写了训练和评估模型的流程。这种方式灵活度高,且与其他流行的深度学习框架(如 PyTorch、Chainer)共通,是本手册所推荐的方法。
不过在很多时候,我们只需要建立一个结构相对简单和典型的神经网络(比如上文中的 MLP 和 CNN),并使用常规的手段进行训练。Keras 也给我们提供了另一套更为简单高效的内置方法来建立、训练和评估模型。

3.1 sequential创建模型

1、tf.keras.models.Sequential() 提供一个层的列表,就能快速地建立一个 tf.keras.Model 模型并返回:

model = tf.keras.models.Sequential([
            tf.keras.layers.Flatten(),
            tf.keras.layers.Dense(100, activation=tf.nn.relu),
            tf.keras.layers.Dense(10),
            tf.keras.layers.Softmax()
        ])

2、为此,Keras 提供了 Functional API,帮助我们建立更为复杂的模型,比如说需要多输入 / 输出或存在参数共享的模型。其使用方法是将层作为可调用的对象并返回张量,并将输入向量和输出向量提供给 tf.keras.Model 的 inputs 和 outputs 参数,如

inputs = tf.keras.Input(shape=(28, 28, 1))
x = tf.keras.layers.Flatten()(inputs)
x = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)(x)
x = tf.keras.layers.Dense(units=10)(x)
outputs = tf.keras.layers.Softmax()(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

3.1 使用keras model的compile、fit、evaluate方法训练和评估模型

  1. 通过调用model的 compile 方法配置模型所需要的训练参数以及评估方法
    model.compile(optimizer,loss=None,metrics=None, 准确率衡):配置训练相关参数
    optimizer:梯度下降优化器(在keras.optimizers)
from keras.optimizers import Adadelta
	from keras.optimizers import Adagrad
	from keras.optimizers import Adam
	from keras.optimizers import Adamax
	from keras.optimizers import Nadam
	from keras.optimizers import Optimizer
	from keras.optimizers import RMSprop
	from keras.optimizers import SGD
	from keras.optimizers import deserialize
	from keras.optimizers import get
	from keras.optimizers import serialize
	from keras.optimizers import AdamOptimizer()

loss=None:损失类型,类型可以是字符串或者该function名字参考:

from keras.losses import MAE as mae
from keras.losses import MAE as mean_absolute_error
from keras.losses import MAPE
from keras.losses import binary_crossentropy
from keras.losses import categorical_crossentropy
from keras.losses import serialize

metrics=None, [‘accuracy’]

model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
1、sparse_categorical_crossentropy:对于目标值是整型的进行交叉熵损失计算
 
 2、categorical_crossentropy:对于两个output tensor and a target tensor进行交叉熵损失计算
  1. model.fit():进行训练
model.fit(data_loader.train_data, data_loader.train_label, 
			epochs=num_epochs, batch_size=batch_size)

x:特征值:

1、Numpy array (or array-like), or a list of arrays
2、A TensorFlow tensor, or a list of tensors
3、tf.data dataset or a dataset iterator. Should return a tuple of either (inputs, targets) or (inputs, targets, sample_weights).
4、A generator or keras.utils.Sequence returning (inputs, targets) or (inputs, targets, sample weights).
y:目标值

batch_size=None:批次大小
 
 epochs=1:训练迭代次数
 
 validation_data :验证数据,可用于在训练过程中监控模型的性能。
 
 callbacks=None:添加回调列表(用于如tensorboard显示等)
  1. model.evaluate(test_images, test_labels)
model.evaluate(test, test_label)

预测model.predict(test):

其它方法:

model.save_weights(filepath) 将模型的权重保存为HDF5文件或者ckpt文件
model.load_weights(filepath, by_name=False)从HDF5文件(由其创建save_weights)加载模型的权重。默认情况下,架构预计不会更改。要将权重加载到不同的体系结构(具有一些共同的层),请使用by_name=True仅加载具有相同名称的那些层。

3.2 模型保存与加载

3.2.1 保存模型权重

只包含若干 Variables 对象序列化后的数据,不包含图结构,所以只给 checkpoint 模型不提供代码是无法重新构建计算图的

# 保存权重
model.save_weights('./checkpoints/my_checkpoint')

# 创建模型实例
model = create_model()

# 加载权重
model.load_weights('./checkpoints/my_checkpoint')

# 评估模型
loss,acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

3.2.2 保存整个模型

模型和优化器可以保存到包含其状态(权重和变量)和模型参数的文件中。这可以导出模型,以便在不访问原始 python 代码的情况下使用它。而且您可以通过恢复优化器状态的方式,从中断的位置恢复训练。
保存完整模型会非常有用,可以在 TensorFlow.js (HDF5, Saved Model) 加载他们,然后在 web 浏览器中训练和运行它们,或者使用 TensorFlow Lite 将它们转换为在移动设备上运行(HDF5, Saved Model)
将模型保存为HDF5文件
SingleNN.model.save_weights("./ckpt/SingleNN.h5")

def predict(self):

# 直接使用训练过后的权重测试
if os.path.exists("./ckpt/SingleNN.h5"):

    SingleNN.model.load_weights("./ckpt/SingleNN.h5")

predictions = SingleNN.model.predict(self.test)

print(np.argmax(predictions, 1))

return

3.3 自定义层、损失函数和评估指标

3.3.1 自定义层

自定义层需要继承 tf.keras.layers.Layer 类,并重写 init 、 build 和 call 三个方法,如下所示:

class MyLayer(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()
        # 初始化代码

    def build(self, input_shape):     # input_shape 是一个 TensorShape 类型对象,提供输入的形状
        # 在第一次使用该层的时候调用该部分代码,在这里创建变量可以使得变量的形状自适应输入的形状
        # 而不需要使用者额外指定变量形状。
        # 如果已经可以完全确定变量的形状,也可以在__init__部分创建变量
        self.variable_0 = self.add_weight(...)
        self.variable_1 = self.add_weight(...)

    def call(self, inputs):
        # 模型调用的代码(处理输入并返回输出)
        return output

例如,如果我们要自己实现一个全连接层( tf.keras.layers.Dense),可以按如下方式编写。此代码在 build方法中创建两个变量,并在 call方法中使用创建的变量进行运算:

class LinearLayer(tf.keras.layers.Layer):
    def __init__(self, units):
        super().__init__()
        self.units = units

    def build(self, input_shape):     # 这里 input_shape 是第一次运行call()时参数inputs的形状
        self.w = self.add_variable(name='w',
            shape=[input_shape[-1], self.units], initializer=tf.zeros_initializer())
        self.b = self.add_variable(name='b',
            shape=[self.units], initializer=tf.zeros_initializer())

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

在定义模型的时候,我们便可以如同 Keras 中的其他层一样,调用我们自定义的层 LinearLayer

class LinearModel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.layer = LinearLayer(units=1)

    def call(self, inputs):
        output = self.layer(inputs)
        return output

3.3.2 自定义损失函数和评估指标

自定义损失函数需要继承 tf.keras.losses.Loss 类,重写 call 方法即可,输入真实值 y_true 和模型预测值 y_pred ,输出模型预测值和真实值之间通过自定义的损失函数计算出的损失值。下面的示例为均方差损失函数:

class MeanSquaredError(tf.keras.losses.Loss):
    def call(self, y_true, y_pred):
        return tf.reduce_mean(tf.square(y_pred - y_true))

自定义评估指标需要继承 tf.keras.metrics.Metric 类,并重写 init 、 update_state 和 result 三个方法。下面的示例对前面用到的 SparseCategoricalAccuracy 评估指标类做了一个简单的重实现:

class SparseCategoricalAccuracy(tf.keras.metrics.Metric):
    def __init__(self):
        super().__init__()
        self.total = self.add_weight(name='total', dtype=tf.int32, initializer=tf.zeros_initializer())
        self.count = self.add_weight(name='count', dtype=tf.int32, initializer=tf.zeros_initializer())

    def update_state(self, y_true, y_pred, sample_weight=None):
        values = tf.cast(tf.equal(y_true, tf.argmax(y_pred, axis=-1, output_type=tf.int32)), tf.int32)
        self.total.assign_add(tf.shape(y_true)[0])
        self.count.assign_add(tf.reduce_sum(values))

    def result(self):
        return self.count / self.total

4. TF 常用功能模块

4.1 callbacks

回调是在训练过程的给定阶段应用的一组函数。可以使用回调来获取培训期间内部状态和模型统计信息的视图。您可以将回调列表(作为关键字参数callbacks)传递给或类的fit()方法。然后将在训练的每个阶段调用回调的相关方法。

定制化保存模型
保存events文件

ModelCheckpoint
from tensorflow.python.keras.callbacks import ModelCheckpoint

keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', save_best_only=False, save_weights_only=False, 
	mode='auto', period=1)
	Save the model after every epoch:每隔多少次迭代保存模型
	filepath: 保存模型字符串
	如果设置 weights.{epoch:02d}-{val_loss:.2f}.hdf5格式,将会每隔epoch number数量并且将验证集的损失保存在该位置
	如果设置weights.{epoch:02d}-{val_acc:.2f}.hdf5,将会按照val_acc的值进行保存模型
	monitor: quantity to monitor.设置为'val_acc'或者'val_loss'
	save_best_only: if save_best_only=True, 只保留比上次模型更好的结果
	save_weights_only: if True, 只保存去那种(model.save_weights(filepath)), else the full model is saved (model.save(filepath)).
	mode: one of {auto, min, max}. 如果save_best_only=True, 对于val_acc, 要设置max, 对于val_loss要设置min
	period: 迭代保存checkpoints的间隔
check = ModelCheckpoint('./ckpt/singlenn_{epoch:02d}-{val_acc:.2f}.h5',
                                monitor='val_acc',
                                save_best_only=True,
                                save_weights_only=True,
                                mode='auto',
                                period=1)

SingleNN.model.fit(self.train, self.train_label, epochs=5, callbacks=[check], validation_data=(x, y))

tensorboard

怎么把网络模型放到gpu上 生成网络模型_自定义

4.2 tf.data:数据集的构建和预处理

  • tf.data 的核心是 tf.data.Dataset 类,提供了对数据集的高层封装。
  • tf.data.Dataset 由一系列的可迭代访问的元素(element)组成,每个元素包含一个或多个张量。比如说,对于一个由图像组成的数据集,每个元素可以是一个形状为 长×宽×通道数 的图片张量,也可以是由图片张量和图片标签张量组成的元组(Tuple)。
  1. tf.data.Dataset.from_tensor_slices()
    最基础的建立 tf.data.Dataset 的方法是使用 tf.data.Dataset.from_tensor_slices() ,适用于数据量较小(能够整个装进内存)的情况。
  • tf.data.Dataset 类为我们提供了多种数据集预处理方法。最常用的如:
    1、Dataset.map(f) :
    对数据集中的每个元素应用函数 f ,得到一个新的数据集(这部分往往结合 tf.io 进行读写和解码文件, tf.image 进行图像处理);
    2、Dataset.shuffle(buffer_size) :
    将数据集打乱(设定一个固定大小的缓冲区(Buffer),取出前 buffer_size 个元素放入,并从缓冲区中随机采样,采样后的数据用后续数据替换);
    3、Dataset.batch(batch_size) :
    将数据集分成批次,即对每 batch_size 个元素,使用 tf.stack() 在第 0 维合并,成为一个元素。
    4、Dataset.prefetch() :
    预取出数据集中的若干个元素
    5、除此以外,还有 Dataset.repeat() (重复数据集的元素)、 Dataset.reduce() (与 Map 相对的聚合操作)、 Dataset.take ()等,可参考 API 文档 进一步了解。