tensorflow1.X tf.estimator.Estimator详解以及代码详细举例

简介

Estimator 类,用来训练和验证 TensorFlow 模型。

Estimator 对象包含了一个模型 model_fn,这个模型给定输入和参数,会返回训练、验证或者预测等所需要的操作节点。
所有的输出(检查点、事件文件等)会写入到 model_dir,或者其子文件夹中。如果 model_dir 为空,则默认为临时目录。
config 参数为 tf.estimator.RunConfig 对象,包含了执行环境的信息。如果没有传递 config,则它会被 Estimator 实例化,使用的是默认配置。
params 包含了超参数。Estimator 只传递超参数,不会检查超参数,因此 params 的结构完全取决于开发者。
Estimator 的所有方法都不能被子类覆盖(它的构造方法强制决定的)。子类应该使用 model_fn 来配置母类,或者增添方法来实现特殊的功能。
Estimator 不支持 Eager Execution(eager execution能够使用Python 的debug工具、数据结构与控制流。并且无需使用placeholder、session,计算结果能够立即得出)。

类方法

1.  def __init__(self,
               model_fn,
               model_dir=None,
               config=None,
               params=None,
               warm_start_from=None):

参数:

model_fn: 模型函数。函数的格式如下:

参数:
1、features: 这是 input_fn 返回的第一项(input_fn 是 train, evaluate 和 predict 的参数)。类型应该是单一的 Tensor 或者 dict。
2、labels: 这是 input_fn 返回的第二项。类型应该是单一的 Tensor 或者 dict。如果 mode 为 ModeKeys.PREDICT,则会默认为 labels=None。如果 model_fn 不接受 mode,model_fn 应该仍然可以处理  labels=None。
3、mode: 可选。指定是训练、验证还是测试。参见 ModeKeys。
4、params: 可选,超参数的 dict。 可以从超参数调整中配置 Estimators。
5、config: 可选,配置。如果没有传则为默认值。可以根据 num_ps_replicas 或 model_dir 等配置更新 model_fn。
返回:
EstimatorSpec

model_dir: 保存模型参数、图等的地址,也可以用来将路径中的检查点加载至 estimator 中来继续训练之前保存的模型。如果是 PathLike, 那么路径就固定为它了。如果是 None,那么 config 中的 model_dir 会被使用(如果设置了的话),如果两个都设置了,那么必须相同;如果两个都是 None,则会使用临时目录。
config: 配置类。
params: 超参数的dict,会被传递到 model_fn。keys 是参数的名称,values 是基本 python 类型。
warm_start_from: 可选,字符串,检查点的文件路径,用来指示从哪里开始热启动。或者是 tf.estimator.WarmStartSettings 类来全部配置热启动。如果是字符串路径,则所有的变量都是热启动,并且需要 Tensor 和词汇的名字都没有变。

  2. def train(self,
            input_fn,
            hooks=None,
            steps=None,
            max_steps=None,
            saving_listeners=None):

参数:

input_fn:一个函数,提供由小 batches 组成的数据, 供训练使用。必须返回以下之一:
1、一个 'tf.data.Dataset’对象:Dataset的输出必须是一个元组 (features, labels),元组要求如下。
2、一个元组 (features, labels):features 是一个 Tensor 或者一个字典(特征名为 Tensor),labels 是一个 Tensor 或者一个字典(特征名为 Tensor)。features 和 labels 都被 model_fn 所使用,应该符合 model_fn 输入的要求。

hooks:SessionRunHook 子类实例的列表。用于在训练循环内部执行。

steps:模型训练的步数。如果是 None, 则一直训练,直到input_fn 抛出了超过界限的异常。steps 是递进式进行的。如果执行了两次训练(steps=10),则总共训练了 20 次。如果中途抛出了越界异常,则训练在 20 次之前就会停止。如果你不想递进式进行,请换为设置 max_steps。如果设置了 steps,则 max_steps 必须是 None。

max_steps:模型训练的最大步数。如果为 None,则一直训练,直到input_fn 抛出了超过界限的异常。如果设置了 max_steps, 则 steps 必须是 None。如果中途抛出了越界异常,则训练在 max_steps 次之前就会停止。执行两次 train(steps=100) 意味着 200 次训练;但是,执行两次 train(max_steps=100) 意味着第二次执行不会进行任何训练,因为第一次执行已经做完了所有的 100 次。

saving_listeners:CheckpointSaverListener 对象的列表。用于在保存检查点之前或之后立即执行的回调函数。

3.   def evaluate(self,
               input_fn,
               steps=None,
               hooks=None,
               checkpoint_path=None,
               name=None):

根据所给数据 input_fn, 对模型进行验证。对于每一步,执行 input_fn(返回数据的一个 batch)。一直进行验证,直到:steps 个 batches 进行完毕,或者input_fn 抛出了越界异常(OutOfRangeError 或 StopIteration)

参数:
input_fn:一个函数,构造了验证所需的输入数据,必须返回以下之一:
1、一个 'tf.data.Dataset’对象:Dataset的输出必须是一个元组 (features, labels),元组要求如下。
2、一个元组 (features, labels):features 是一个 Tensor 或者一个字典(特征名为 Tensor),labels 是一个 Tensor 或者一个字典(特征名为 Tensor)。features 和 labels 都被 model_fn 所使用,应该符合 model_fn 输入的要求。
steps:模型验证的步数。如果是 None, 则一直验证,直到input_fn 抛出了超过界限的异常。
hooks:SessionRunHook 子类实例的列表。用于在验证内部执行。
checkpoint_path: 用于验证的检查点路径。如果是 None, 则使用 model_dir 中最新的检查点。
name:验证的名字。使用者可以针对不同的数据集运行多个验证操作,比如训练集 vs 测试集。不同验证的结果被保存在不同的文件夹中,且分别出现在 tensorboard 中。

返回
返回一个字典,包括 model_fn 中指定的评价指标、global_step(包含验证进行的全局步数)
异常
ValueError:如果 step 小于等于0
ValueError:如果 model_dir 指定的模型没有被训练,或者指定的 checkpoint_path 为空。

  4. def predict(self,
              input_fn,
              predict_keys=None,
              hooks=None,
              checkpoint_path=None,
              yield_single_examples=True):

对给出的特征进行预测

参数:
input_fn:一个函数,构造特征。预测一直进行下去,直到 input_fn 抛出了越界异常(OutOfRangeError 或 StopIteration)。函数必须返回以下之一:
1、一个 'tf.data.Dataset’对象:Dataset的输出和以下的限制相同。
2、features:一个 Tensor 或者一个字典(特征名为 Tensor)。features 被 model_fn 所使用,应该符合 model_fn 输入的要求。
3、一个元组,其中第一项为 features。
predict_keys:字符串列表,要预测的键值。当 EstimatorSpec.predictions 是一个 dict 时使用。如果使用了 predict_keys, 那么剩下的预测值会从字典中过滤掉。如果是 None,则返回全部。
hooks:SessionRunHook 子类实例的列表。用于在预测内部回调。
checkpoint_path: 用于预测的检查点路径。如果是 None, 则使用 model_dir 中最新的检查点。
yield_single_examples:If False, yield the whole batch as returned by the model_fn instead of decomposing the batch into individual elements. This is useful if model_fn returns some tensors whose first dimension is not equal to the batch size.

返回
predictions tensors 的值
异常
ValueError:model_dir 中找不到训练好的模型。
ValueError:预测值的 batch 长度不同,且 yield_single_examples 为 True。
ValueError:predict_keys 和 predictions 之间有冲突。例如,predict_keys 不是 None,但是 EstimatorSpec.predictions 不是一个 dict。

代码示例

1.不使用Estimator训练

import tensorflow as tf
import numpy as np


def mnist_dataset():
    """获取训练集"""
    (train_images,train_labels),(test_images,test_labels)= tf.keras.datasets.fashion_mnist.load_data()


    """我们想要将这些图像的像素值从0到255之间的数字转换为0到1之间的数字,并将数据集转换为[B,H,W,C]格式(B是图像数量,
    H和W是高度和宽度,C是我们数据集的通道数量,灰度图的情况下为1):"""
    train_images = np.asarray(train_images, dtype=np.float32)/255
    train_images = np.expand_dims(train_images, axis=3)

    test_images = np.asarray(test_images, dtype=np.float32)/255
    test_images = np.expand_dims(test_images, axis=3)
    """然后,我们希望将标签从整数id(如2或Pullover)转换为独热编码 (如0,0,1,0,0,0,0,0,0,0)。我们使用tf.one_hot函数来做这点"""
    train_labels = tf.one_hot(train_labels, depth=10).numpy()
    test_labels = tf.one_hot(test_labels, depth=10).numpy()
    return (train_images,train_labels),(test_images,test_labels)

"""建立模型"""
class Mymodel(tf.keras.Model):
    def __init__(self):
        super(Mymodel, self).__init__()

        self.conv2d_1 = tf.keras.layers.Conv2D(filters=64, kernel_size=3, activation=tf.nn.relu)
        self.maxpooling2d = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=2)
        self.conv2d_2 = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu)
        self.flatten = tf.keras.layers.Flatten()
        self.dense_1 = tf.keras.layers.Dense(64, activation=tf.nn.relu)
        self.dense_2 = tf.keras.layers.Dense(10, activation=tf.nn.softmax)

    def call(self, x):
        print("x: ", x.shape)
        x = self.conv2d_1(x)
        x = self.maxpooling2d(x)
        x = self.conv2d_2(x)
        x = self.maxpooling2d(x)
        x = self.conv2d_2(x)
        x = self.flatten(x)
        x = self.dense_1(x)
        out = self.dense_2(x)
        return out

if __name__ == '__main__':
    (train_images, train_labels), (test_images, test_labels) = mnist_dataset()

    model = Mymodel()
    model.compile(optimizer=optimizers.Adam(1e-3),  # 优化函数
                  loss=tf.losses.CategoricalCrossentropy(from_logits=True),  # s损失函数
                  metrics=['accuracy'])
    model.build(input_shape = (None, 28,28,1))
    model.fit(train_images, train_labels, batch_size = 10, epochs=10, steps_per_epoch=5, verbose=1,
              validation_data=(test_images, test_labels))

    scores = model.evaluate(test_images, test_labels, 10, verbose=1)
    print("Final test loss and accuracy :", scores)

2. 使用Estimator训练

import tensorflow as tf
import time
import os
import numpy as np


def mnist_dataset():
    """获取训练集"""
    (train_images,train_labels),(test_images,test_labels)= tf.keras.datasets.fashion_mnist.load_data()


    """我们想要将这些图像的像素值从0到255之间的数字转换为0到1之间的数字,并将数据集转换为[B,H,W,C]格式(B是图像数量,
    H和W是高度和宽度,C是我们数据集的通道数量,灰度图的情况下为1):"""
    train_images = np.asarray(train_images, dtype=np.float32)/255
    train_images = np.expand_dims(train_images, axis=3)

    test_images = np.asarray(test_images, dtype=np.float32)/255
    test_images = np.expand_dims(test_images, axis=3)
    """然后,我们希望将标签从整数id(如2或Pullover)转换为独热编码 (如0,0,1,0,0,0,0,0,0,0)。我们使用tf.one_hot函数来做这点"""
    train_labels = tf.one_hot(train_labels, depth=10).numpy()
    test_labels = tf.one_hot(test_labels, depth=10).numpy()
    return (train_images,train_labels),(test_images,test_labels)


def input_fn(images, labels, epochs, batch_size):
    ds = tf.data.Dataset.from_tensor_slices((images, labels))
    ds = ds.shuffle(5000).repeat(epochs).batch(batch_size)
    ds = ds.prefetch(2)
    return ds


class TimeHistory(tf.compat.v1.train.SessionRunHook):
    def begin(self):
        self.time = []
    def before_run(self, run_context):
        self.iter_time_start = time.time()
    def after_run(self,run_context,run_values):
        self.time.append(time.time() - self.iter_time_start)

if __name__ == '__main__':
    (train_images, train_labels), (test_images, test_labels) = mnist_dataset()

    inputs = tf.keras.Input(shape=(28,28,1))
    x = tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation=tf.nn.relu)(inputs)
    x = tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=2)(x)
    x = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu)(x)
    x = tf.keras.layers.Flatten()(x)
    x = tf.keras.layers.Dense(64, activation=tf.nn.relu)(x)
    pred = tf.keras.layers.Dense(10, activation=tf.nn.softmax)(x)

    model = tf.keras.Model(inputs=inputs, outputs=pred)
    model.compile(optimizer=optimizers.Adam(1e-3),  # 优化函数
                  loss=tf.losses.CategoricalCrossentropy(from_logits=True),  # s损失函数
                  metrics=['accuracy'])
    """创建Estimator"""

    estimator = tf.keras.estimator.model_to_estimator(model)

    time_hist = TimeHistory()
    BATCH_SIZE = 10
    EPOCHS = 5
    estimator.train(lambda:input_fn(train_images,train_labels,epochs= EPOCHS, batch_size= BATCH_SIZE),hooks=[time_hist])

    eval = estimator.evaluate(lambda:input_fn(test_images,test_labels,epochs= 1, batch_size= 10))
    print("evaluate:", eval)

    dic = estimator.predict(lambda:input_fn(test_images,test_labels,epochs= 1, batch_size= 5))
    print("dic:", dic)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值