text: #   Copyright (c) 2018 PaddlePaddle Authors. 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.
  """VGG16 benchmark in Fluid"""
  from __future__ import print_function
  
  import sys
  import time
  import numpy as np
  import paddle.v2 as paddle
  import paddle.fluid as fluid
  import paddle.fluid.core as core
  import argparse
  import functools
  
  parser = argparse.ArgumentParser(description=__doc__)
  parser.add_argument(
      '--batch_size', type=int, default=128, help="Batch size for training.")
  parser.add_argument(
      '--skip_batch_num',
      type=int,
      default=5,
      help='The first num of minibatch num to skip, for better performance test')
  parser.add_argument(
      '--iterations', type=int, default=80, help='The number of minibatches.')
  parser.add_argument(
      '--learning_rate',
      type=float,
      default=1e-3,
      help="Learning rate for training.")
  parser.add_argument('--pass_num', type=int, default=50, help="No. of passes.")
  parser.add_argument(
      '--device',
      type=str,
      default='GPU',
      choices=['CPU', 'GPU'],
      help="The device type.")
  parser.add_argument(
      '--data_format',
      type=str,
      default='NCHW',
      choices=['NCHW', 'NHWC'],
      help='The data order, now only support NCHW.')
  parser.add_argument(
      '--data_set',
      type=str,
      default='cifar10',
      choices=['cifar10', 'flowers'],
      help='Optional dataset for benchmark.')
  parser.add_argument(
      '--with_test',
      action='store_true',
      help='If set, test the testset during training.')
  args = parser.parse_args()
  
  
  def vgg16_bn_drop(input):
      def conv_block(input, num_filter, groups, dropouts):
          return fluid.nets.img_conv_group(
              input=input,
              pool_size=2,
              pool_stride=2,
              conv_num_filter=[num_filter] * groups,
              conv_filter_size=3,
              conv_act='relu',
              conv_with_batchnorm=True,
              conv_batchnorm_drop_rate=dropouts,
              pool_type='max')
  
      conv1 = conv_block(input, 64, 2, [0.3, 0])
      conv2 = conv_block(conv1, 128, 2, [0.4, 0])
      conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
      conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
      conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
  
      drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
      fc1 = fluid.layers.fc(input=drop, size=512, act=None)
      bn = fluid.layers.batch_norm(input=fc1, act='relu')
      drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
      fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
      return fc2
  
  
  def main():
      if args.data_set == "cifar10":
          classdim = 10
          if args.data_format == 'NCHW':
              data_shape = [3, 32, 32]
          else:
              data_shape = [32, 32, 3]
      else:
          classdim = 102
          if args.data_format == 'NCHW':
              data_shape = [3, 224, 224]
          else:
              data_shape = [224, 224, 3]
  
      # Input data
      images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
      label = fluid.layers.data(name='label', shape=[1], dtype='int64')
  
      # Train program
      net = vgg16_bn_drop(images)
      predict = fluid.layers.fc(input=net, size=classdim, act='softmax')
      cost = fluid.layers.cross_entropy(input=predict, label=label)
      avg_cost = fluid.layers.mean(x=cost)
  
      # Evaluator
      batch_size_tensor = fluid.layers.create_tensor(dtype='int64')
      batch_acc = fluid.layers.accuracy(
          input=predict, label=label, total=batch_size_tensor)
  
      # inference program
      inference_program = fluid.default_main_program().clone()
      with fluid.program_guard(inference_program):
          inference_program = fluid.io.get_inference_program(
              target_vars=[batch_acc, batch_size_tensor])
  
      # Optimization
      optimizer = fluid.optimizer.Adam(learning_rate=args.learning_rate)
      opts = optimizer.minimize(avg_cost)
  
      fluid.memory_optimize(fluid.default_main_program())
  
      # Initialize executor
      place = core.CPUPlace() if args.device == 'CPU' else core.CUDAPlace(0)
      exe = fluid.Executor(place)
  
      # Parameter initialization
      exe.run(fluid.default_startup_program())
  
      # data reader
      train_reader = paddle.batch(
          paddle.reader.shuffle(
              paddle.dataset.cifar.train10()
              if args.data_set == 'cifar10' else paddle.dataset.flowers.train(),
              buf_size=5120),
          batch_size=args.batch_size)
      test_reader = paddle.batch(
          paddle.dataset.cifar.test10()
          if args.data_set == 'cifar10' else paddle.dataset.flowers.test(),
          batch_size=args.batch_size)
  
      # test
      def test(exe):
          test_accuracy = fluid.average.WeightedAverage()
          for batch_id, data in enumerate(test_reader()):
              img_data = np.array(map(lambda x: x[0].reshape(data_shape),
                                      data)).astype("float32")
              y_data = np.array(map(lambda x: x[1], data)).astype("int64")
              y_data = y_data.reshape([-1, 1])
  
              acc, weight = exe.run(inference_program,
                                    feed={"pixel": img_data,
                                          "label": y_data},
                                    fetch_list=[batch_acc, batch_size_tensor])
              test_accuracy.add(value=acc, weight=weight)
          return test_accuracy.eval()
  
      iters, num_samples, start_time = 0, 0, time.time()
      accuracy = fluid.average.WeightedAverage()
      for pass_id in range(args.pass_num):
          accuracy.reset()
          train_accs = []
          train_losses = []
          for batch_id, data in enumerate(train_reader()):
              if iters == args.skip_batch_num:
                  start_time = time.time()
                  num_samples = 0
              if iters == args.iterations:
                  break
              img_data = np.array(map(lambda x: x[0].reshape(data_shape),
                                      data)).astype("float32")
              y_data = np.array(map(lambda x: x[1], data)).astype("int64")
              y_data = y_data.reshape([-1, 1])
  
              loss, acc, weight = exe.run(
                  fluid.default_main_program(),
                  feed={"pixel": img_data,
                        "label": y_data},
                  fetch_list=[avg_cost, batch_acc, batch_size_tensor])
              accuracy.add(value=acc, weight=weight)
              iters += 1
              num_samples += len(data)
              print(
                  "Pass = %d, Iter = %d, Loss = %f, Accuracy = %f" %
                  (pass_id, iters, loss, acc)
              )  # The accuracy is the accumulation of batches, but not the current batch.
  
          pass_train_acc = accuracy.eval()
          train_losses.append(loss)
          train_accs.append(acc)
          # evaluation
          if args.with_test:
              pass_test_acc = test(exe)
          train_elapsed = time.time() - start_time
          print("Pass: %d, Loss: %f, Train Accuray: %f\n" %
                (pass_id, np.mean(train_losses), np.mean(train_accs)))
  
  
  def print_arguments():
      print('-----------  Configuration Arguments -----------')
      for arg, value in sorted(vars(args).iteritems()):
          print('%s: %s' % (arg, value))
      print('------------------------------------------------')
  
  
  if __name__ == "__main__":
      print_arguments()
      main()
  