text: #!/usr/bin/env python
  
  # Copyright 2017 Google Inc. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #      http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import tensorflow as tf
  import numpy as np
  
  tf.logging.set_verbosity(tf.logging.INFO)
  
  CSV_COLUMNS = 'fare_amount,dayofweek,hourofday,pickuplon,pickuplat,dropofflon,dropofflat,passengers,key'.split(',')
  LABEL_COLUMN = 'fare_amount'
  KEY_FEATURE_COLUMN = 'key'
  DEFAULTS = [[0.0], ['Sun'], [0], [-74.0], [40.0], [-74.0], [40.7], [1.0], ['nokey']]
  
  # These are the raw input columns, and will be provided for prediction also
  INPUT_COLUMNS = [
      # TODO: Define feature columns for dayofweek, hourofday, pickuplon, pickuplat, dropofflat, dropofflon, passengers
  
      # TODO: Add any engineered columns here
      
  ]
  
  # Build the estimator
  def build_estimator(model_dir, nbuckets, hidden_units):
      """
       TODO: Build an estimator starting from INPUT COLUMNS.
       These include feature transformations and synthetic features.
       The model is a wide-and-deep model, i.e. [wide_cols] & [deep_cols].
      """
  
      return None # TODO: Add estimator definition here
  
  
  def add_engineered(features):
      # TODO: Add any engineered features to the dict
      
      return features   
  
  def serving_input_fn():
      feature_placeholders = {
          # TODO: What features will user provide? What will their types be?
          
      }
  
      # TODO: Add any extra placeholders for inputs you'll generate
  
      features = {
          key: tf.expand_dims(tensor, -1)
          for key, tensor in feature_placeholders.items()
      }
      return tf.estimator.export.ServingInputReceiver(
        features, # TODO: Wrap this with a call to add_engineered
        feature_placeholders
      )
  
  # Create input function to load data into datasets
  def read_dataset(filename, mode, batch_size = 512):
      def _input_fn():
          def decode_csv(value_column):
              columns = tf.decode_csv(value_column, record_defaults = DEFAULTS)
              features = dict(zip(CSV_COLUMNS, columns))
              label = features.pop(LABEL_COLUMN)
              return features, label # TODO: Wrap this with a call to add_engineered
          
          # Create list of files that match pattern
          file_list = tf.gfile.Glob(filename)
  
          # Create dataset from file list
          dataset = tf.data.TextLineDataset(file_list).map(decode_csv)
  
          if mode == tf.estimator.ModeKeys.TRAIN:
              num_epochs = None # indefinitely
              dataset = dataset.shuffle(buffer_size = 10 * batch_size)
          else:
              num_epochs = 1 # end-of-input after this
  
          dataset = dataset.repeat(num_epochs).batch(batch_size)
          batch_features, batch_labels = dataset.make_one_shot_iterator().get_next()
          return batch_features, batch_labels
      return _input_fn
  
  # Create estimator train and evaluate function
  def train_and_evaluate(args):
      tf.summary.FileWriterCache.clear() # ensure filewriter cache is clear for TensorBoard events file
      estimator = build_estimator(args['output_dir'], args['nbuckets'], args['hidden_units'])
      train_spec = tf.estimator.TrainSpec(
          input_fn = read_dataset(
              filename = args['train_data_paths'],
              mode = tf.estimator.ModeKeys.TRAIN,
              batch_size = args['train_batch_size']),
          max_steps = args['train_steps'])
      exporter = tf.estimator.LatestExporter('exporter', serving_input_fn)
      eval_spec = tf.estimator.EvalSpec(
          input_fn = read_dataset(
              filename = args['eval_data_paths'],
              mode = tf.estimator.ModeKeys.EVAL,
              batch_size = args['eval_batch_size']),
          steps = None,
          exporters = exporter)
      tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
  