//  [python]
def validate_mvsnet(mvs_list):
    """ validate mvsnet """
    print ('Validation sample number: ', len(mvs_list))

    # Training and validation generators
    mvs_generator = iter(MVSGenerator(mvs_list, FLAGS.view_num))
    generator_data_type = (tf.float32, tf.float32, tf.float32)
    # Datasets from generators
    mvs_set = tf.data.Dataset.from_generator(lambda: mvs_generator, generator_data_type)
    mvs_set = mvs_set.batch(FLAGS.batch_size)
    mvs_set = mvs_set.prefetch(buffer_size=1)
    # iterators
    mvs_iterator = mvs_set.make_initializable_iterator()
    # data
    images, cams, depth_image = mvs_iterator.get_next()

    # consolidate inputs
    images.set_shape(tf.TensorShape([None, FLAGS.view_num, None, None, 3]))
    cams.set_shape(tf.TensorShape([None, FLAGS.view_num, 2, 4, 4]))
    depth_image.set_shape(tf.TensorShape([None, None, None, 1]))
    depth_start = tf.reshape(tf.slice(cams, [0, 0, 1, 3, 0], [FLAGS.batch_size, 1, 1, 1, 1]), 
                             [FLAGS.batch_size])
    depth_interval = tf.reshape(tf.slice(cams, [0, 0, 1, 3, 1], [FLAGS.batch_size, 1, 1, 1, 1]), 
                                [FLAGS.batch_size])
    depth_num = tf.to_int32(tf.reshape(tf.slice(cams, [0, 0, 1, 3, 2], [1, 1, 1, 1, 1]), []))
    if FLAGS.inverse_depth:
        depth_end = tf.reshape(
            tf.slice(cams, [0, 0, 1, 3, 3], [FLAGS.batch_size, 1, 1, 1, 1]), [FLAGS.batch_size])
    else:
        depth_end = depth_start + (tf.to_float(depth_num) - 1) * depth_interval

    # image normalization
    normalized_images = []
    for view in range(0, FLAGS.view_num):
        image = tf.squeeze(tf.slice(images, [0, view, 0, 0, 0], [-1, 1, -1, -1, 3]), axis=1)
        image = tf.image.per_image_standardization(image)
        normalized_images.append(image)
    images = tf.stack(normalized_images, axis=1)

    # depth map inference
    if FLAGS.regularization == '3DCNNs':
        depth_map, prob_map = inference(
            images, cams, FLAGS.max_d, depth_start, depth_interval)
    elif FLAGS.regularization == 'GRU':
        depth_map, prob_map = inference_winner_take_all(images, cams, 
            depth_num, depth_start, depth_end, reg_type='GRU', inverse_depth=FLAGS.inverse_depth)

    if FLAGS.inverse_depth:
        interval = tf.ones_like(depth_interval)
        loss, less_one_accuracy, less_three_accuracy = mvsnet_regression_loss(
            depth_map, depth_image, interval)
    else:
        loss, less_one_accuracy, less_three_accuracy = mvsnet_regression_loss(
            depth_map, depth_image, depth_interval)

    # init option
    init_op = tf.global_variables_initializer()
    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True

    ave_loss = 0
    ave_per1 = 0
    ave_per3 = 0
    model_folder = os.path.split(FLAGS.pretrained_model_ckpt_path)[0]
    with tf.Session(config=config) as sess:     
        # initialization
        sess.run(init_op)

        total_step = 0
        # load model
        if FLAGS.pretrained_model_ckpt_path is not None:
            restorer = tf.train.Saver(tf.global_variables())
            restorer.restore(
                sess, '-'.join([FLAGS.pretrained_model_ckpt_path, str(FLAGS.ckpt_step)]))
            print(Notify.INFO, 'Pre-trained model restored from %s' %
                  ('-'.join([FLAGS.pretrained_model_ckpt_path, str(FLAGS.ckpt_step)])), Notify.ENDC)
            total_step = FLAGS.ckpt_step
    
        # training of one epoch
        sess.run(mvs_iterator.initializer)
        for step in range(len(mvs_list)):

            # run one batch
            start_time = time.time()
            try:
                out_loss, out_less_one, out_less_three, out_depth_map = sess.run([
                    loss, less_one_accuracy, less_three_accuracy, depth_map])
            except tf.errors.OutOfRangeError:
                print("all dense finished")  # ==> "End of dataset"
                break
            duration = time.time() - start_time
            print(Notify.INFO, 'depth map validation for %d, loss=%.3f, < 1 = %.3f, < 3 = %.3f. (%.3f sec/step)' 
                  % (step, out_loss, out_less_one, out_less_three, duration), 
                  Notify.ENDC)

            # save output
            ave_loss += out_loss
            ave_per1 += out_less_one
            ave_per3 += out_less_three
            total_step += 1

        ave_loss /= len(mvs_list)
        ave_per1 /= len(mvs_list)
        ave_per3 /= len(mvs_list)
        print ('ave_loss', ave_loss)
        print ('ave_per1', ave_per1)
        print ('ave_per3', ave_per3)
        with open(FLAGS.validation_result_path, 'a') as log_file:
            log_file.write('Model check point %d, L1 loss = %f, < 1 = %f, < 3 = %f \n' 
                           % (int(FLAGS.ckpt_step), float(ave_loss), float(ave_per1), float(ave_per3)))