Tensorflow:使用估算器在时期之间更改优化程序的learning_rate

时间:2018-03-30 13:15:49

标签: python tensorflow tensorflow-estimator

我想在epochs之间更改优化器的learning_rate。在各个帖子(thisthis)中,可以使用tf.placeholdertf.Variable通过“经典”字样。 sess.run()界面。

但是,我想使用高级估算器API。代码来自 wide_deep 示例,模型为tf.estimator.DNNClassifier tf.train.GradientDescentOptimizer

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import shutil
import sys

import tensorflow as tf

# Number of vairables
_N = 42

_CSV_COLUMNS = [ ('a%s'% _i) for _i in range (_N-1) ]
_CSV_COLUMNS += ['class']

_CSV_COLUMN_DEFAULTS = [ [0.0] for _ in range (_N-1) ]
_CSV_COLUMN_DEFAULTS += [ [0] ] #class

parser = argparse.ArgumentParser()

parser.add_argument(
  '--model_dir', type=str, default='/tmp/biodeg',
  help='Base directory for the model.')

parser.add_argument(
  '--model_type', type=str, default='deep',
  help="Valid model types: {'wide', 'deep', 'wide_deep'}.")

parser.add_argument(
  '--train_epochs', type=int, default=2000, help='Number of training epochs.')

parser.add_argument(
  '--epochs_per_eval', type=int, default=2,
  help='The number of training epochs to run between evaluations.')

parser.add_argument(
  '--batch_size', type=int, default=40, help='Number of examples per batch.')

parser.add_argument(
  '--train_data', type=str, default='biodeg_data.csv',
  help='Path to the training data.')

parser.add_argument(
  '--test_data', type=str, default='biodeg_test.csv',
  help='Path to the test data.')

_NUM_EXAMPLES = {
  'train': 837,
  'validation': 218,
 }


def build_model_columns():
  """Builds a set of wide and deep feature columns."""
  wide_columns = []

  deep_columns = [
    tf.feature_column.numeric_column('a%s'% _i) for _i in range (_N-1)
  ]

  return wide_columns, deep_columns


def build_estimator(model_dir, model_type):
  """Build an estimator appropriate for the given model type."""
  wide_columns, deep_columns = build_model_columns()
  hidden_units = [30, 30]
  optimizer = tf.train.GradientDescentOptimizer(
    learning_rate = 0.0001
  )

  # Create a tf.estimator.RunConfig to ensure the model is run on CPU, which
  # trains faster than GPU for this model.
  run_config = tf.estimator.RunConfig().replace(
    session_config=tf.ConfigProto(device_count={'GPU': 1}))

  if model_type == 'wide':
    return tf.estimator.LinearClassifier(
      model_dir=model_dir,
      feature_columns=wide_columns,
      config=run_config)
  elif model_type == 'deep':
    return tf.estimator.DNNClassifier(
      model_dir=model_dir,
      feature_columns=deep_columns,
      hidden_units=hidden_units,
      optimizer = optimizer,
      config=run_config)
  else:
    return tf.estimator.DNNLinearCombinedClassifier(
      model_dir=model_dir,
      linear_feature_columns=wide_columns,
      dnn_feature_columns=deep_columns,
      dnn_hidden_units=hidden_units,
      config=run_config)


def input_fn(data_file, num_epochs, shuffle, batch_size):
  """Generate an input function for the Estimator."""
  assert tf.gfile.Exists(data_file), (
    '%s not found. Please make sure you have either run data_download.py or '
    'set both arguments --train_data and --test_data.' % data_file)

  def parse_csv(value):
    print('Parsing', data_file)
    columns = tf.decode_csv(value, record_defaults=_CSV_COLUMN_DEFAULTS)
    features = dict(zip(_CSV_COLUMNS, columns))
    labels = features.pop('class')
    return features, tf.equal(labels, 1)

  # Extract lines from input files using the Dataset API.
  dataset = tf.data.TextLineDataset(data_file)

  if shuffle:
    dataset = dataset.shuffle(buffer_size=_NUM_EXAMPLES['train'])

  dataset = dataset.map(parse_csv, num_parallel_calls=5)

  # We call repeat after shuffling, rather than before, to prevent separate
  # epochs from blending together.
  dataset = dataset.repeat(num_epochs)
  dataset = dataset.batch(batch_size)
  return dataset

def main(unused_argv):
# Clean up the model directory if present
shutil.rmtree(FLAGS.model_dir, ignore_errors=True)
model = build_estimator(FLAGS.model_dir, FLAGS.model_type)

# Train and evaluate the model every `FLAGS.epochs_per_eval` epochs.
for n in range(FLAGS.train_epochs // FLAGS.epochs_per_eval):
  model.train(input_fn=lambda: input_fn(
    FLAGS.train_data, FLAGS.epochs_per_eval, True, FLAGS.batch_size))

  results = model.evaluate(input_fn=lambda: input_fn(
    FLAGS.test_data, 1, False, FLAGS.batch_size))

  # Update model.learning_rate here - somehow...
  # ????

  # Display evaluation metrics
  print('Results at epoch', (n + 1) * FLAGS.epochs_per_eval)
  print('-' * 60)

  for key in sorted(results):
    print('%s: %s' % (key, results[key]))

if __name__ == '__main__':
  tf.logging.set_verbosity(tf.logging.INFO)
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

有办法吗?

PS:我知道有优化器可以让你有自适应学习率,或者你可以使用tf.train.exponential_decay。我需要更好地控制优化器的参数。

0 个答案:

没有答案