tensorflow 预创建的 Estimators

Estimator 是 Tensorflow 完整模型的高级表示,它被设计用于轻松扩展和异步训练。

import tensorflow as tf
import pandas as pd
from icecream import ic
#使用 Estimators 解决 Tensorflow 中的鸢尾花(Iris)分类问题。
'''
构建并测试了一个模型,该模型根据花萼和花瓣的大小将鸢尾花分成三种物种。
使用鸢尾花数据集训练模型。该数据集包括四个特征和一个标签。这四个特征确定了单个鸢尾花的以下植物学特征:
    花萼长度    花萼宽度    花瓣长度    花瓣宽度
'''
#定义一些有用的常量来解析数据:
CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']
#使用 Keras 与 Pandas 下载并解析鸢尾花数据集。注意为训练和测试保留不同的数据集。
train_path = tf.keras.utils.get_file(
    "iris_training.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv")
test_path = tf.keras.utils.get_file(
    "iris_test.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv")

train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
#通过检查数据可以发现有四列浮点型特征和一列 int32 型标签。
ic(train.head())

运行结果:

ic| train.head():    SepalLength  SepalWidth  PetalLength  PetalWidth  Species
                  0          6.4         2.8          5.6         2.2        2
                  1          5.0         2.3          3.3         1.0        1
                  2          4.9         2.5          4.5         1.7        2
                  3          4.9         3.1          1.5         0.1        0
                  4          5.7         3.8          1.7         0.3        0
#对于每个数据集都分割出标签(Species),模型将被训练来预测这些标签。
train_y = train.pop('Species')
test_y = test.pop('Species')
# 标签列现已从数据中删除
#ic(train.head())

Estimator 编程概述

现在已经设定好了数据,可以使用 Tensorflow Estimator 定义模型。Estimator 是从 tf.estimator.Estimator 中派生的任何类。Tensorflow提供了一组tf.estimator(例如,LinearRegressor)来实现常见的机器学习算法。此外,可以编写自己的自定义 Estimator

为了编写基于预创建的 Estimator 的 Tensorflow 项目,必须完成以下工作:

  • 创建一个或多个输入函数
  • 定义模型的特征列
  • 实例化一个 Estimator,指定特征列和各种超参数。
  • 在 Estimator 对象上调用一个或多个方法,传递合适的输入函数以作为数据源。

创建输入函数

创建输入函数来提供用于训练、评估和预测的数据。

输入函数是一个返回 tf.data.Dataset 对象的函数,此对象会输出下列含两个元素的元组:

  • features——Python字典,其中:
    • 每个键都是特征名称
    • 每个值都是包含此特征所有值的数组
  • label 包含每个样本的标签的值的数组。
#3 创建输入函数
def input_evaluation_set():
    features = {'SepalLength': np.array([6.4, 5.0]),
                'SepalWidth':  np.array([2.8, 2.3]),
                'PetalLength': np.array([5.6, 3.3]),
                'PetalWidth':  np.array([2.2, 1.0])}
    labels = np.array([2, 1])
    return features, labels
'''
输入函数可以任意的方式生成 features 字典与 label 列表。建议使用 Tensorflow 的 Dataset API,该 API 可以用来解析各种类型的数据。
Dataset API 可以处理很多常见情况。例如,使用 Dataset API,可以轻松地从大量文件中并行读取记录,并将它们合并为单个数据流。
为了简化将使用 pandas 加载数据,并利用此内存数据构建输入管道。
'''
def input_fn(features, labels, training=True, batch_size=256):
    """An input function for training or evaluating"""
    # 将输入转换为数据集。
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))

    # 如果在训练模式下混淆并重复数据。
    if training:
        dataset = dataset.shuffle(1000).repeat()

    return dataset.batch(batch_size)

定义特征列(feature columns)

特征列(feature columns)是一个对象,用于描述模型应该如何使用特征字典中的原始输入数据。当构建一个 Estimator 模型的时候,会向其传递一个特征列的列表,其中包含希望模型使用的每个特征。tf.feature_column 模块提供了许多为模型表示数据的选项。

'''
对于鸢尾花问题,4 个原始特征是数值,因此将构建一个特征列的列表,以告知 Estimator 模型将 4 个特征都表示为 32 位浮点值。
'''
# 特征列描述了如何使用输入。
my_feature_columns = []
for key in train.keys():
    my_feature_columns.append(tf.feature_column.numeric_column(key=key))

实例化 Estimator

鸢尾花为题是一个经典的分类问题。幸运的是,Tensorflow 提供了几个预创建的 Estimator 分类器,其中包括:

#5 实例化 Estimator
#对于鸢尾花问题,tf.estimator.DNNClassifier 似乎是最好的选择。可以这样实例化该 Estimator:
# 构建一个拥有两个隐层,隐藏节点分别为 30 和 10 的深度神经网络。
classifier = tf.estimator.DNNClassifier(
    feature_columns=my_feature_columns,
    # 隐层所含结点数量分别为 30 和 10.
    hidden_units=[30, 10],
    # 模型必须从三个类别中做出选择。
    n_classes=3)

运行结果(一些警告信息)

2021-03-05 20:48:44.194673: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2021-03-05 20:48:44.238896: E tensorflow/stream_executor/cuda/cuda_driver.cc:313] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
2021-03-05 20:48:44.238933: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (wangwensong-XPS-13-9360): /proc/driver/nvidia/version does not exist
2021-03-05 20:48:44.239395: I tensorflow/core/platform/cpu_feature_guard.cc:143] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2021-03-05 20:48:44.247650: I tensorflow/core/platform/profile_utils/cpu_utils.cc:102] CPU Frequency: 2699905000 Hz
2021-03-05 20:48:44.247955: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x556d3effdec0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2021-03-05 20:48:44.247975: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmprz6g2xtz

## 训练、评估和预测

我们已经有一个 Estimator 对象,现在可以调用方法来执行下列操作:

  • 训练模型。
  • 评估经过训练的模型。
  • 使用经过训练的模型进行预测。

训练模型

#通过调用 Estimator 的 Train 方法来训练模型:
# 训练模型。
classifier.train(
    input_fn=lambda: input_fn(train, train_y, training=True),
    steps=5000)

注意将 input_fn 调用封装在 lambda 中以获取参数,同时提供不带参数的输入函数,如 Estimator 所预期的那样。step 参数告知该方法在训练多少步后停止训练。

评估经过训练的模型

#现在模型已经经过训练,可以获取一些关于模型性能的统计信息。代码块将在测试数据上对经过训练的模型的准确率(accuracy)进行评估:
eval_result = classifier.evaluate(
    input_fn=lambda: input_fn(test, test_y, training=False))

print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))

运行结果

Test set accuracy: 0.533

与对 train 方法的调用不同,我们没有传递 steps 参数来进行评估。用于评估的 input_fn 只生成一个 epoch 的数据。

eval_result 字典亦包含 average_loss(每个样本的平均误差),loss(每个 mini-batch 的平均误差)与 Estimator 的 global_step(经历的训练迭代次数)值。

利用经过训练的模型进行预测(推理)

#我们已经有一个经过训练的模型,可以生成准确的评估结果。现在可以使用经过训练的模型,根据一些无标签测量结果预测鸢尾花的品种。
# 与训练和评估一样,我们使用单个函数调用进行预测:
# 由模型生成预测
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
    'SepalLength': [5.1, 5.9, 6.9],
    'SepalWidth': [3.3, 3.0, 3.1],
    'PetalLength': [1.7, 4.2, 5.4],
    'PetalWidth': [0.5, 1.5, 2.1],
}

def input_fn(features, batch_size=256):
    """An input function for prediction."""
    # 将输入转换为无标签数据集。
    return tf.data.Dataset.from_tensor_slices(dict(features)).batch(batch_size)

predictions = classifier.predict(
    input_fn=lambda: input_fn(predict_x))
#predict 方法返回一个 Python 可迭代对象,为每个样本生成一个预测结果字典。以下代码输出了一些预测及其概率:
for pred_dict, expec in zip(predictions, expected):
    class_id = pred_dict['class_ids'][0]
    probability = pred_dict['probabilities'][class_id]

    print('Prediction is "{}" ({:.1f}%), expected "{}"'.format(
        SPECIES[class_id], 100 * probability, expec))

完整代码:

import tensorflow as tf
import pandas as pd
import numpy as np
from icecream import ic
#使用 Estimators 解决 Tensorflow 中的鸢尾花(Iris)分类问题。
'''
构建并测试了一个模型,该模型根据花萼和花瓣的大小将鸢尾花分成三种物种。
使用鸢尾花数据集训练模型。该数据集包括四个特征和一个标签。这四个特征确定了单个鸢尾花的以下植物学特征:
    花萼长度    花萼宽度    花瓣长度    花瓣宽度
'''
#1 定义一些有用的常量来解析数据:
CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']
#2 使用 Keras 与 Pandas 下载并解析鸢尾花数据集。注意为训练和测试保留不同的数据集。
train_path = tf.keras.utils.get_file(
    "iris_training.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv")
test_path = tf.keras.utils.get_file(
    "iris_test.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv")

train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
#通过检查数据可以发现有四列浮点型特征和一列 int32 型标签。
#ic(train.head())
#对于每个数据集都分割出标签(Species),模型将被训练来预测这些标签。
train_y = train.pop('Species')
test_y = test.pop('Species')
# 标签列现已从数据中删除
#ic(train.head())
#3 创建输入函数
def input_evaluation_set():
    features = {'SepalLength': np.array([6.4, 5.0]),
                'SepalWidth':  np.array([2.8, 2.3]),
                'PetalLength': np.array([5.6, 3.3]),
                'PetalWidth':  np.array([2.2, 1.0])}
    labels = np.array([2, 1])
    return features, labels
'''
输入函数可以任意的方式生成 features 字典与 label 列表。建议使用 Tensorflow 的 Dataset API,该 API 可以用来解析各种类型的数据。
Dataset API 可以处理很多常见情况。例如,使用 Dataset API,可以轻松地从大量文件中并行读取记录,并将它们合并为单个数据流。
为了简化将使用 pandas 加载数据,并利用此内存数据构建输入管道。
'''
def input_fn(features, labels, training=True, batch_size=256):
    """An input function for training or evaluating"""
    # 将输入转换为数据集。
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))

    # 如果在训练模式下混淆并重复数据。
    if training:
        dataset = dataset.shuffle(1000).repeat()

    return dataset.batch(batch_size)
#4 定义特征列
'''
对于鸢尾花问题,4 个原始特征是数值,因此将构建一个特征列的列表,以告知 Estimator 模型将 4 个特征都表示为 32 位浮点值。
'''
# 特征列描述了如何使用输入。
my_feature_columns = []
for key in train.keys():
    my_feature_columns.append(tf.feature_column.numeric_column(key=key))

#5 实例化 Estimator
#对于鸢尾花问题,tf.estimator.DNNClassifier 似乎是最好的选择。可以这样实例化该 Estimator:
# 构建一个拥有两个隐层,隐藏节点分别为 30 和 10 的深度神经网络。
classifier = tf.estimator.DNNClassifier(
    feature_columns=my_feature_columns,
    # 隐层所含结点数量分别为 30 和 10.
    hidden_units=[30, 10],
    # 模型必须从三个类别中做出选择。
    n_classes=3)
#5.1 训练模型
#通过调用 Estimator 的 Train 方法来训练模型:
# 训练模型。
classifier.train(
    input_fn=lambda: input_fn(train, train_y, training=True),
    steps=5000)
#5.2 评估经过训练的模型
#现在模型已经经过训练,可以获取一些关于模型性能的统计信息。代码块将在测试数据上对经过训练的模型的准确率(accuracy)进行评估:
eval_result = classifier.evaluate(
    input_fn=lambda: input_fn(test, test_y, training=False))

#print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
#Test set accuracy: 0.533
#5.3 利用经过训练的模型进行预测(推理)

#我们已经有一个经过训练的模型,可以生成准确的评估结果。现在可以使用经过训练的模型,根据一些无标签测量结果预测鸢尾花的品种。
# 与训练和评估一样,我们使用单个函数调用进行预测:
# 由模型生成预测
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
    'SepalLength': [5.1, 5.9, 6.9],
    'SepalWidth': [3.3, 3.0, 3.1],
    'PetalLength': [1.7, 4.2, 5.4],
    'PetalWidth': [0.5, 1.5, 2.1],
}

def input_fn(features, batch_size=256):
    """An input function for prediction."""
    # 将输入转换为无标签数据集。
    return tf.data.Dataset.from_tensor_slices(dict(features)).batch(batch_size)

predictions = classifier.predict(
    input_fn=lambda: input_fn(predict_x))
#predict 方法返回一个 Python 可迭代对象,为每个样本生成一个预测结果字典。以下代码输出了一些预测及其概率:
for pred_dict, expec in zip(predictions, expected):
    class_id = pred_dict['class_ids'][0]
    probability = pred_dict['probabilities'][class_id]

    print('Prediction is "{}" ({:.1f}%), expected "{}"'.format(
        SPECIES[class_id], 100 * probability, expec))

运行结果:

Prediction is "Setosa" (65.8%), expected "Setosa"
Prediction is "Versicolor" (51.2%), expected "Versicolor"
Prediction is "Virginica" (65.3%), expected "Virginica"


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值