DNNClassifier的基本格式

初始化:

  • feature_columns作为特征列,但是这里不添加数据,仅仅是使用tf.feature_column添加数据特征;数据特征相当于一个字典的键值,这个键值是真正训练时输入数据的特征列的名称。
  • hidden_units=[10, 10]表示隐含层是10*10的神经网络
  • n_classes=3表示输出层的分类有3个
  • optimizer表示使用的训练函数
tf.estimator.DNNClassifier(
        feature_columns=my_feature_columns,
        hidden_units=[10, 10],
        n_classes=3,
        optimizer=tf.train.AdamOptimizer(
            learning_rate=0.01
        )
    )

训练

训练的时候,需要输入训练数据,并指定训练的步数。这一步需要和tf.data.Dataset结合使用。一般来说,使用tf.data.Dataset进行每一个批次的数据喂取,并使用steps参数指定训练的步数。使用lambda函数来简化表达式。返回的数据必须和上一步初始化的数据列具有相同的格式。

classifier.train(
        input_fn=lambda: iris_data.train_input_fn(train_x, train_y,
                                                  args.batch_size),
        steps=args.train_steps
)

预测

输入需要分类的数据集的特征列,特征列和初始化的要一致。这里使用了自定义的函数,具体请参照下面的源代码。

classifier.predict(
        input_fn=lambda: iris_data.eval_input_fn(predict_x,
                                                 labels=None,
                                                 batch_size=args.batch_size)
)

预测的返回值是一个字典的集合,具体结果如下:

{
'probabilities': array([9.9973017e-01, 2.6193992e-04, 7.9224610e-06], dtype=float32), 
'logits': array([ 5.043977 , -3.2031484, -6.7015615], dtype=float32),
 'classes': array([b'0'],dtype=object), 
 'class_ids': array([0])
}
  • probabilities: 表示属于每个种类的可能性
  • logits:暂时没弄明白,好像一般不用
  • classes:表示属于哪一类
  • class_ids:表示类的下标
    因为实例要进行3个分类,所以是上述的结果。

配合Dataset的数据读取

这篇博客中总结了一下Dataset的基本用法。tensorflow中,一般是先定义好神经网络输入的特征列,然后使用Dataset读取特征列。注意,读取的时候,要把每一个特征列添加上列的名称,然后进行字典化处理。之后,初始化DNNClassifier的特征列,使得两者的特征列的名称相同。之后处理好一次数据的batch_size等。最后进行读取。
类似这种格式:

def train_input_fn(features, labels, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
    dataset = dataset.shuffle(1000).repeat().batch(batch_size)
    return dataset

完整版代码

读取数据的代码:

import pandas as pd
import tensorflow as tf

TRAIN_URL = "http://download.tensorflow.org/data/iris_training.csv"
TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"

CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth',
                    'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']


def maybe_download():
    train_path = tf.keras.utils.get_file(fname=TRAIN_URL.split('/')[-1],
                                         origin=TRAIN_URL, cache_dir='.')
    test_path = tf.keras.utils.get_file(fname=TEST_URL.split('/')[-1],
                                        origin=TEST_URL, cache_dir='.')
    return train_path, test_path


def load_data(y_name='Species'):
    train_path, test_path = maybe_download()
    train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
    train_x, train_y = train, train.pop(y_name)
    test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
    test_x, test_y = test, test.pop(y_name)
    return (train_x, train_y), (test_x, test_y)


def train_input_fn(features, labels, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
    dataset = dataset.shuffle(1000).repeat().batch(batch_size)
    return dataset


def eval_input_fn(features, labels, batch_size):
    features = dict(features)
    if labels is None:
        inputs = features
    else:
        inputs = (features, labels)
    dataset = tf.data.Dataset.from_tensor_slices(inputs)
    assert batch_size is not None, "batch_size must not be None"
    dataset = dataset.batch(batch_size)
    return dataset


CSV_TYPES = [[0.0], [0.0], [0.0], [0.0], [0.0]]


def _parse_line(line):
    fields = tf.decode_csv(line, record_defaults=CSV_TYPES)
    features = dict(zip(CSV_COLUMN_NAMES, fields))
    label = features.pop('Species')
    return features, label


def csv_input_fn(csv_path, batch_size):
    dataset = tf.data.TextLineDataset(csv_path).skip(1)
    dataset = dataset.map(_parse_line)
    dataset = dataset.shuffle(1000).repeat().batch(batch_size)
    return dataset

训练学习的代码:

import argparse
import tensorflow as tf
import read_data

parse = argparse.ArgumentParser()
parse.add_argument('--batch_size', default=100, type=int,
                   help='batch size')
parse.add_argument('--train_steps', default=1000, type=int,
                   help='training steps')


def main(argv):
    args = parse.parse_args(argv[1:])
    (train_x, train_y), (test_x, test_y) = read_data.load_data()
    my_feature_columns = []
    for key in train_x.keys():
        my_feature_columns.append(tf.feature_column.numeric_column(key=key))
    classifier = tf.estimator.DNNClassifier(
        feature_columns=my_feature_columns,
        hidden_units=[10, 10],
        n_classes=3,
        optimizer=tf.train.AdamOptimizer(
            learning_rate=0.01
        )
    )
    classifier.train(
        input_fn=lambda: read_data.train_input_fn(train_x, train_y,
                                                  args.batch_size),
        steps=args.train_steps
    )
    eval_result = classifier.evaluate(
        input_fn=lambda: read_data.eval_input_fn(test_x, test_y,
                                                 args.batch_size)
    )
    print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
    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],
    }
    predictions = classifier.predict(
        input_fn=lambda: read_data.eval_input_fn(predict_x,
                                                 labels=None,
                                                 batch_size=args.batch_size)
    )
    template = ('\nPrediction is "{}" ({:.1f}%), expected "{}"')
    for pre_dict, expec in zip(predictions, expected):
        class_id = pre_dict['class_ids'][0]
        probability = pre_dict['probabilities'][class_id]
        print(template.format(read_data.SPECIES[class_id],
                              100 * probability, expec))


if __name__ == '__main__':
    tf.logging.set_verbosity(tf.logging.INFO)
    tf.app.run(main)
GitHub 加速计划 / te / tensorflow
184.55 K
74.12 K
下载
一个面向所有人的开源机器学习框架
最近提交(Master分支:2 个月前 )
a49e66f2 PiperOrigin-RevId: 663726708 2 个月前
91dac11a This test overrides disabled_backends, dropping the default value in the process. PiperOrigin-RevId: 663711155 2 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐