if os.path.isfile(os.path.join(output_dir, 'pseudo_data.npy')):
      os.remove(os.path.join(output_dir, 'pseudo_data.npy'))

"""Inference entrance."""
# pylint: disable=redefined-outer-name
# pylint: disable=redefined-builtin
# pylint: disable=unused-variable
import argparse
import collections
import itertools
import numpy as np
import os
import shutil
import cv2
import tqdm
import deepdish as dd
import json

import tensorflow as tf
from tensorflow.python.framework import test_util

import tensorpack.utils.viz as tpviz
from tensorpack.predict import MultiTowerOfflinePredictor, OfflinePredictor, PredictConfig
from tensorpack.tfutils import SmartInit, get_tf_version_tuple
from tensorpack.tfutils.export import ModelExporter
from tensorpack.utils import fs, logger

from dataset import register_coco, register_voc
from config import config as cfg
from config import finalize_configs

from data import get_eval_unlabeled_dataflow

from FasterRCNN.dataset import DatasetRegistry
from FasterRCNN.data import get_eval_dataflow
from FasterRCNN.eval import DetectionResult, multithread_predict_dataflow, predict_image
from FasterRCNN.modeling.generalized_rcnn import ResNetFPNModel, ResNetC4Model
from FasterRCNN.viz import draw_final_outputs, draw_predictions
from FasterRCNN.utils import custom
from FasterRCNN.predict import do_evaluate, do_predict, do_visualize

def predict_unlabeled(model,
                      model_path,
                      nr_visualize=100,
                      output_dir='output_patch_samples'):
  """Predict the pseudo label information of unlabeled data."""

  assert cfg.EVAL.PSEUDO_INFERENCE, 'set cfg.EVAL.PSEUDO_INFERENCE=True'
  df, dataset_size = get_eval_unlabeled_dataflow(
      cfg.DATA.TRAIN, return_size=True)
  df.reset_state()
  predcfg = PredictConfig(
      model=model,
      session_init=SmartInit(model_path),
      input_names=['image'],  # ['image', 'gt_boxes', 'gt_labels'],
      output_names=[
          'generate_{}_proposals/boxes'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'generate_{}_proposals/scores'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'fastrcnn_all_scores',
          'output/boxes',
          'output/scores',  # score of the labels
          'output/labels',
      ])
  pred = OfflinePredictor(predcfg)

  if os.path.isdir(output_dir):

    if not os.path.isdir(os.path.join(output_dir, 'vis')):
      os.makedirs(os.path.join(output_dir, 'vis'))
    else:
      shutil.rmtree(os.path.join(output_dir, 'vis'))
      fs.mkdir_p(output_dir + '/vis')
  else:
    fs.mkdir_p(output_dir)
    fs.mkdir_p(output_dir + '/vis')
  logger.warning('-' * 100)
  logger.warning('Write to {}'.format(output_dir))
  logger.warning('-' * 100)

  with tqdm.tqdm(total=nr_visualize) as pbar:
    for idx, dp in itertools.islice(enumerate(df), nr_visualize):
      img, img_id = dp  # dp['image'], dp['img_id']
      rpn_boxes, rpn_scores, all_scores, \
          final_boxes, final_scores, final_labels = pred(img)
      outs = {
          'proposals_boxes': rpn_boxes,  # (?,4)
          'proposals_scores': rpn_scores,  # (?,)
          'boxes': final_boxes,
          'scores': final_scores,
          'labels': final_labels
      }
      ratios = [10, 10]  # [top 20% as background, bottom 20% as background]
      bg_ind, fg_ind = custom.find_bg_and_fg_proposals(
          all_scores, ratios=ratios)

      bg_viz = draw_predictions(img, rpn_boxes[bg_ind], all_scores[bg_ind])

      fg_viz = draw_predictions(img, rpn_boxes[fg_ind], all_scores[fg_ind])

      results = [
          DetectionResult(*args)
          for args in zip(final_boxes, final_scores, final_labels, [None] *
                          len(final_labels))
      ]
      final_viz = draw_final_outputs(img, results)

      viz = tpviz.stack_patches([bg_viz, fg_viz, final_viz], 2, 2)

      if os.environ.get('DISPLAY', None):
        tpviz.interactive_imshow(viz)
      assert cv2.imwrite('{}/vis/{:03d}.png'.format(output_dir, idx), viz)
      pbar.update()
  logger.info('Write {} samples to {}'.format(nr_visualize, output_dir))

  ## Parallel inference the whole unlabled data
  pseudo_preds = collections.defaultdict(list)

  num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
  graph_funcs = MultiTowerOfflinePredictor(predcfg, list(
      range(num_tower))).get_predictors()
  dataflows = [
      get_eval_unlabeled_dataflow(
          cfg.DATA.TRAIN, shard=k, num_shards=num_tower)
      for k in range(num_tower)
  ]

  all_results = multithread_predict_dataflow(dataflows, graph_funcs)

  for id, result in tqdm.tqdm(enumerate(all_results)):
    img_id = result['image_id']
    outs = {
        'proposals_boxes': result['proposal_box'].astype(np.float16),  # (?,4)
        'proposals_scores': result['proposal_score'].astype(np.float16),  # (?,)
        'boxes': result['bbox'].astype(np.float16),  # (?,4)
        'scores': result['score'].astype(np.float16),  # (?,)
        'labels':
            result['category_id'].astype(np.float16)  # (?,)
    }
    pseudo_preds[img_id] = outs
  logger.warn('Writing to {}'.format(
      os.path.join(output_dir, 'pseudo_data.npy')))
  try:
    dd.io.save(os.path.join(output_dir, 'pseudo_data.npy'), pseudo_preds)
  except RuntimeError:
    logger.error('Save failed. Check reasons manually...')

def do_evaluate_unlabeled(pred_config, output_file, reuse=True):
  """Evaluate unlabled data."""

  for i, dataset in enumerate(cfg.DATA.VAL):
    output = output_file + '-' + dataset
    if not os.path.isfile(output) or not reuse:
      if i == 0:
        num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
        graph_funcs = MultiTowerOfflinePredictor(
            pred_config, list(range(num_tower))).get_predictors()
      logger.info('Evaluating {} ...'.format(dataset))
      dataflows = [
          get_eval_dataflow(dataset, shard=k, num_shards=num_tower)
          for k in range(num_tower)
      ]
      all_results = multithread_predict_dataflow(dataflows, graph_funcs)
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE)
    else:
      all_results = json.load(open(output, 'r'))
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE, metric_only=True)

    with open(output + '_cocometric.json', 'w') as f:
      json.dump(eval_metrics, f)

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--load', help='load a model for evaluation.', required=True)
  parser.add_argument(
      '--visualize', action='store_true', help='visualize intermediate results')
  parser.add_argument(
      '--predict_unlabeled', help='visualize intermediate results')
  parser.add_argument('--eval_unlabeled', help='visualize intermediate results')
  parser.add_argument(
      '--evaluate',
      help='Run evaluation. '
      'This argument is the path to the output json evaluation file')
  parser.add_argument(
      '--predict',
      help='Run prediction on a given image. '
      'This argument is the path to the input image file',
      nargs='+')
  parser.add_argument(
      '--benchmark',
      action='store_true',
      help='Benchmark the speed of the model + postprocessing')
  parser.add_argument(
      '--config',
      help='A list of KEY=VALUE to overwrite those defined in config.py',
      nargs='+')
  parser.add_argument('--output-pb', help='Save a model to .pb')
  parser.add_argument('--output-serving', help='Save a model to serving file')

  args = parser.parse_args()
  if args.config:
    cfg.update_args(args.config)
  try:
    register_voc(cfg.DATA.BASEDIR)  # add VOC datasets to the registry
  except NotImplementedError:
    logger.warning('VOC does not find!')
  register_coco(cfg.DATA.BASEDIR)  # add COCO datasets to the registry
  MODEL = ResNetFPNModel() if cfg.MODE_FPN else ResNetC4Model()

  if not tf.test.is_gpu_available():
    assert get_tf_version_tuple() >= (1, 7) and test_util.IsMklEnabled(), \
        'Inference requires either GPU support or MKL support!'
  assert args.load
  finalize_configs(is_training=False)

  if args.predict or args.visualize:
    cfg.TEST.RESULT_SCORE_THRESH = cfg.TEST.RESULT_SCORE_THRESH_VIS

  # let the output has the same path logic as checkpoint
  if args.predict_unlabeled:
    output_dir = args.predict_unlabeled
    predict_unlabeled(MODEL, args.load, output_dir=output_dir)

  if args.visualize:
    do_visualize(MODEL, args.load, output_dir=output_dir)
  else:
    predcfg = PredictConfig(
        model=MODEL,
        session_init=SmartInit(args.load),
        input_names=MODEL.get_inference_tensor_names()[0],
        output_names=MODEL.get_inference_tensor_names()[1])

    if args.output_pb:
      ModelExporter(predcfg).export_compact(args.output_pb, optimize=False)
    elif args.output_serving:
      ModelExporter(predcfg).export_serving(args.output_serving, optimize=False)

    if args.predict:
      predictor = OfflinePredictor(predcfg)
      for image_file in args.predict:
        do_predict(predictor, image_file)
    elif args.evaluate:
      assert args.evaluate.endswith('.json'), args.evaluate
      do_evaluate(predcfg, args.evaluate)
    elif args.eval_unlabeled:
      assert args.eval_unlabeled.endswith('.json'), args.eval_unlabeled
      do_evaluate_unlabeled(predcfg, args.eval_unlabeled)
    elif args.benchmark:
      df = get_eval_dataflow(cfg.DATA.VAL[0])
      df.reset_state()
      predictor = OfflinePredictor(predcfg)
      for _, img in enumerate(tqdm.tqdm(df, total=len(df), smoothing=0.5)):
        predict_image(img[0], predictor)


for id, result in tqdm.tqdm(enumerate(all_results)):
    img_id = result['image_id']
    outs = {
        'proposals_boxes': result['proposal_box'].astype(np.float16),  # (?,4)
        'proposals_scores': result['proposal_score'].astype(np.float16),  # (?,)
        'boxes': result['bbox'].astype(np.float16),  # (?,4)
        'scores': result['score'].astype(np.float16),  # (?,)
        'labels':
            result['category_id'].astype(np.float16)  # (?,)
    }
    pseudo_preds[img_id] = outs

"""Inference entrance."""
# pylint: disable=redefined-outer-name
# pylint: disable=redefined-builtin
# pylint: disable=unused-variable
import argparse
import collections
import itertools
import numpy as np
import os
import shutil
import cv2
import tqdm
import deepdish as dd
import json

import tensorflow as tf
from tensorflow.python.framework import test_util

import tensorpack.utils.viz as tpviz
from tensorpack.predict import MultiTowerOfflinePredictor, OfflinePredictor, PredictConfig
from tensorpack.tfutils import SmartInit, get_tf_version_tuple
from tensorpack.tfutils.export import ModelExporter
from tensorpack.utils import fs, logger

from dataset import register_coco, register_voc
from config import config as cfg
from config import finalize_configs

from data import get_eval_unlabeled_dataflow

from FasterRCNN.dataset import DatasetRegistry
from FasterRCNN.data import get_eval_dataflow
from FasterRCNN.eval import DetectionResult, multithread_predict_dataflow, predict_image
from FasterRCNN.modeling.generalized_rcnn import ResNetFPNModel, ResNetC4Model
from FasterRCNN.viz import draw_final_outputs, draw_predictions
from FasterRCNN.utils import custom
from FasterRCNN.predict import do_evaluate, do_predict, do_visualize

def predict_unlabeled(model,
                      model_path,
                      nr_visualize=100,
                      output_dir='output_patch_samples'):
  """Predict the pseudo label information of unlabeled data."""

  assert cfg.EVAL.PSEUDO_INFERENCE, 'set cfg.EVAL.PSEUDO_INFERENCE=True'
  df, dataset_size = get_eval_unlabeled_dataflow(
      cfg.DATA.TRAIN, return_size=True)
  df.reset_state()
  predcfg = PredictConfig(
      model=model,
      session_init=SmartInit(model_path),
      input_names=['image'],  # ['image', 'gt_boxes', 'gt_labels'],
      output_names=[
          'generate_{}_proposals/boxes'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'generate_{}_proposals/scores'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'fastrcnn_all_scores',
          'output/boxes',
          'output/scores',  # score of the labels
          'output/labels',
      ])
  pred = OfflinePredictor(predcfg)

  if os.path.isdir(output_dir):
    if os.path.isfile(os.path.join(output_dir, 'pseudo_data.npy')):
      os.remove(os.path.join(output_dir, 'pseudo_data.npy'))
    if not os.path.isdir(os.path.join(output_dir, 'vis')):
      os.makedirs(os.path.join(output_dir, 'vis'))
    else:
      shutil.rmtree(os.path.join(output_dir, 'vis'))
      fs.mkdir_p(output_dir + '/vis')
  else:
    fs.mkdir_p(output_dir)
    fs.mkdir_p(output_dir + '/vis')
  logger.warning('-' * 100)
  logger.warning('Write to {}'.format(output_dir))
  logger.warning('-' * 100)

  with tqdm.tqdm(total=nr_visualize) as pbar:
    for idx, dp in itertools.islice(enumerate(df), nr_visualize):
      img, img_id = dp  # dp['image'], dp['img_id']
      rpn_boxes, rpn_scores, all_scores, \
          final_boxes, final_scores, final_labels = pred(img)
      outs = {
          'proposals_boxes': rpn_boxes,  # (?,4)
          'proposals_scores': rpn_scores,  # (?,)
          'boxes': final_boxes,
          'scores': final_scores,
          'labels': final_labels
      }
      ratios = [10, 10]  # [top 20% as background, bottom 20% as background]
      bg_ind, fg_ind = custom.find_bg_and_fg_proposals(
          all_scores, ratios=ratios)

      bg_viz = draw_predictions(img, rpn_boxes[bg_ind], all_scores[bg_ind])

      fg_viz = draw_predictions(img, rpn_boxes[fg_ind], all_scores[fg_ind])

      results = [
          DetectionResult(*args)
          for args in zip(final_boxes, final_scores, final_labels, [None] *
                          len(final_labels))
      ]
      final_viz = draw_final_outputs(img, results)

      viz = tpviz.stack_patches([bg_viz, fg_viz, final_viz], 2, 2)

      if os.environ.get('DISPLAY', None):
        tpviz.interactive_imshow(viz)
      assert cv2.imwrite('{}/vis/{:03d}.png'.format(output_dir, idx), viz)
      pbar.update()
  logger.info('Write {} samples to {}'.format(nr_visualize, output_dir))

  ## Parallel inference the whole unlabled data
  pseudo_preds = collections.defaultdict(list)

  num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
  graph_funcs = MultiTowerOfflinePredictor(predcfg, list(
      range(num_tower))).get_predictors()
  dataflows = [
      get_eval_unlabeled_dataflow(
          cfg.DATA.TRAIN, shard=k, num_shards=num_tower)
      for k in range(num_tower)
  ]

  all_results = multithread_predict_dataflow(dataflows, graph_funcs)

  logger.warn('Writing to {}'.format(
      os.path.join(output_dir, 'pseudo_data.npy')))
  try:
    dd.io.save(os.path.join(output_dir, 'pseudo_data.npy'), pseudo_preds)
  except RuntimeError:
    logger.error('Save failed. Check reasons manually...')

def do_evaluate_unlabeled(pred_config, output_file, reuse=True):
  """Evaluate unlabled data."""

  for i, dataset in enumerate(cfg.DATA.VAL):
    output = output_file + '-' + dataset
    if not os.path.isfile(output) or not reuse:
      if i == 0:
        num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
        graph_funcs = MultiTowerOfflinePredictor(
            pred_config, list(range(num_tower))).get_predictors()
      logger.info('Evaluating {} ...'.format(dataset))
      dataflows = [
          get_eval_dataflow(dataset, shard=k, num_shards=num_tower)
          for k in range(num_tower)
      ]
      all_results = multithread_predict_dataflow(dataflows, graph_funcs)
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE)
    else:
      all_results = json.load(open(output, 'r'))
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE, metric_only=True)

    with open(output + '_cocometric.json', 'w') as f:
      json.dump(eval_metrics, f)

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--load', help='load a model for evaluation.', required=True)
  parser.add_argument(
      '--visualize', action='store_true', help='visualize intermediate results')
  parser.add_argument(
      '--predict_unlabeled', help='visualize intermediate results')
  parser.add_argument('--eval_unlabeled', help='visualize intermediate results')
  parser.add_argument(
      '--evaluate',
      help='Run evaluation. '
      'This argument is the path to the output json evaluation file')
  parser.add_argument(
      '--predict',
      help='Run prediction on a given image. '
      'This argument is the path to the input image file',
      nargs='+')
  parser.add_argument(
      '--benchmark',
      action='store_true',
      help='Benchmark the speed of the model + postprocessing')
  parser.add_argument(
      '--config',
      help='A list of KEY=VALUE to overwrite those defined in config.py',
      nargs='+')
  parser.add_argument('--output-pb', help='Save a model to .pb')
  parser.add_argument('--output-serving', help='Save a model to serving file')

  args = parser.parse_args()
  if args.config:
    cfg.update_args(args.config)
  try:
    register_voc(cfg.DATA.BASEDIR)  # add VOC datasets to the registry
  except NotImplementedError:
    logger.warning('VOC does not find!')
  register_coco(cfg.DATA.BASEDIR)  # add COCO datasets to the registry
  MODEL = ResNetFPNModel() if cfg.MODE_FPN else ResNetC4Model()

  if not tf.test.is_gpu_available():
    assert get_tf_version_tuple() >= (1, 7) and test_util.IsMklEnabled(), \
        'Inference requires either GPU support or MKL support!'
  assert args.load
  finalize_configs(is_training=False)

  if args.predict or args.visualize:
    cfg.TEST.RESULT_SCORE_THRESH = cfg.TEST.RESULT_SCORE_THRESH_VIS

  # let the output has the same path logic as checkpoint
  if args.predict_unlabeled:
    output_dir = args.predict_unlabeled
    predict_unlabeled(MODEL, args.load, output_dir=output_dir)

  if args.visualize:
    do_visualize(MODEL, args.load, output_dir=output_dir)
  else:
    predcfg = PredictConfig(
        model=MODEL,
        session_init=SmartInit(args.load),
        input_names=MODEL.get_inference_tensor_names()[0],
        output_names=MODEL.get_inference_tensor_names()[1])

    if args.output_pb:
      ModelExporter(predcfg).export_compact(args.output_pb, optimize=False)
    elif args.output_serving:
      ModelExporter(predcfg).export_serving(args.output_serving, optimize=False)

    if args.predict:
      predictor = OfflinePredictor(predcfg)
      for image_file in args.predict:
        do_predict(predictor, image_file)
    elif args.evaluate:
      assert args.evaluate.endswith('.json'), args.evaluate
      do_evaluate(predcfg, args.evaluate)
    elif args.eval_unlabeled:
      assert args.eval_unlabeled.endswith('.json'), args.eval_unlabeled
      do_evaluate_unlabeled(predcfg, args.eval_unlabeled)
    elif args.benchmark:
      df = get_eval_dataflow(cfg.DATA.VAL[0])
      df.reset_state()
      predictor = OfflinePredictor(predcfg)
      for _, img in enumerate(tqdm.tqdm(df, total=len(df), smoothing=0.5)):
        predict_image(img[0], predictor)


try:
    dd.io.save(os.path.join(output_dir, 'pseudo_data.npy'), pseudo_preds)
  except RuntimeError:
    logger.error('Save failed. Check reasons manually...')

"""Inference entrance."""
# pylint: disable=redefined-outer-name
# pylint: disable=redefined-builtin
# pylint: disable=unused-variable
import argparse
import collections
import itertools
import numpy as np
import os
import shutil
import cv2
import tqdm
import deepdish as dd
import json

import tensorflow as tf
from tensorflow.python.framework import test_util

import tensorpack.utils.viz as tpviz
from tensorpack.predict import MultiTowerOfflinePredictor, OfflinePredictor, PredictConfig
from tensorpack.tfutils import SmartInit, get_tf_version_tuple
from tensorpack.tfutils.export import ModelExporter
from tensorpack.utils import fs, logger

from dataset import register_coco, register_voc
from config import config as cfg
from config import finalize_configs

from data import get_eval_unlabeled_dataflow

from FasterRCNN.dataset import DatasetRegistry
from FasterRCNN.data import get_eval_dataflow
from FasterRCNN.eval import DetectionResult, multithread_predict_dataflow, predict_image
from FasterRCNN.modeling.generalized_rcnn import ResNetFPNModel, ResNetC4Model
from FasterRCNN.viz import draw_final_outputs, draw_predictions
from FasterRCNN.utils import custom
from FasterRCNN.predict import do_evaluate, do_predict, do_visualize

def predict_unlabeled(model,
                      model_path,
                      nr_visualize=100,
                      output_dir='output_patch_samples'):
  """Predict the pseudo label information of unlabeled data."""

  assert cfg.EVAL.PSEUDO_INFERENCE, 'set cfg.EVAL.PSEUDO_INFERENCE=True'
  df, dataset_size = get_eval_unlabeled_dataflow(
      cfg.DATA.TRAIN, return_size=True)
  df.reset_state()
  predcfg = PredictConfig(
      model=model,
      session_init=SmartInit(model_path),
      input_names=['image'],  # ['image', 'gt_boxes', 'gt_labels'],
      output_names=[
          'generate_{}_proposals/boxes'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'generate_{}_proposals/scores'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'fastrcnn_all_scores',
          'output/boxes',
          'output/scores',  # score of the labels
          'output/labels',
      ])
  pred = OfflinePredictor(predcfg)

  if os.path.isdir(output_dir):
    if os.path.isfile(os.path.join(output_dir, 'pseudo_data.npy')):
      os.remove(os.path.join(output_dir, 'pseudo_data.npy'))
    if not os.path.isdir(os.path.join(output_dir, 'vis')):
      os.makedirs(os.path.join(output_dir, 'vis'))
    else:
      shutil.rmtree(os.path.join(output_dir, 'vis'))
      fs.mkdir_p(output_dir + '/vis')
  else:
    fs.mkdir_p(output_dir)
    fs.mkdir_p(output_dir + '/vis')
  logger.warning('-' * 100)
  logger.warning('Write to {}'.format(output_dir))
  logger.warning('-' * 100)

  with tqdm.tqdm(total=nr_visualize) as pbar:
    for idx, dp in itertools.islice(enumerate(df), nr_visualize):
      img, img_id = dp  # dp['image'], dp['img_id']
      rpn_boxes, rpn_scores, all_scores, \
          final_boxes, final_scores, final_labels = pred(img)
      outs = {
          'proposals_boxes': rpn_boxes,  # (?,4)
          'proposals_scores': rpn_scores,  # (?,)
          'boxes': final_boxes,
          'scores': final_scores,
          'labels': final_labels
      }
      ratios = [10, 10]  # [top 20% as background, bottom 20% as background]
      bg_ind, fg_ind = custom.find_bg_and_fg_proposals(
          all_scores, ratios=ratios)

      bg_viz = draw_predictions(img, rpn_boxes[bg_ind], all_scores[bg_ind])

      fg_viz = draw_predictions(img, rpn_boxes[fg_ind], all_scores[fg_ind])

      results = [
          DetectionResult(*args)
          for args in zip(final_boxes, final_scores, final_labels, [None] *
                          len(final_labels))
      ]
      final_viz = draw_final_outputs(img, results)

      viz = tpviz.stack_patches([bg_viz, fg_viz, final_viz], 2, 2)

      if os.environ.get('DISPLAY', None):
        tpviz.interactive_imshow(viz)
      assert cv2.imwrite('{}/vis/{:03d}.png'.format(output_dir, idx), viz)
      pbar.update()
  logger.info('Write {} samples to {}'.format(nr_visualize, output_dir))

  ## Parallel inference the whole unlabled data
  pseudo_preds = collections.defaultdict(list)

  num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
  graph_funcs = MultiTowerOfflinePredictor(predcfg, list(
      range(num_tower))).get_predictors()
  dataflows = [
      get_eval_unlabeled_dataflow(
          cfg.DATA.TRAIN, shard=k, num_shards=num_tower)
      for k in range(num_tower)
  ]

  all_results = multithread_predict_dataflow(dataflows, graph_funcs)

  for id, result in tqdm.tqdm(enumerate(all_results)):
    img_id = result['image_id']
    outs = {
        'proposals_boxes': result['proposal_box'].astype(np.float16),  # (?,4)
        'proposals_scores': result['proposal_score'].astype(np.float16),  # (?,)
        'boxes': result['bbox'].astype(np.float16),  # (?,4)
        'scores': result['score'].astype(np.float16),  # (?,)
        'labels':
            result['category_id'].astype(np.float16)  # (?,)
    }
    pseudo_preds[img_id] = outs
  logger.warn('Writing to {}'.format(
      os.path.join(output_dir, 'pseudo_data.npy')))

def do_evaluate_unlabeled(pred_config, output_file, reuse=True):
  """Evaluate unlabled data."""

  for i, dataset in enumerate(cfg.DATA.VAL):
    output = output_file + '-' + dataset
    if not os.path.isfile(output) or not reuse:
      if i == 0:
        num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
        graph_funcs = MultiTowerOfflinePredictor(
            pred_config, list(range(num_tower))).get_predictors()
      logger.info('Evaluating {} ...'.format(dataset))
      dataflows = [
          get_eval_dataflow(dataset, shard=k, num_shards=num_tower)
          for k in range(num_tower)
      ]
      all_results = multithread_predict_dataflow(dataflows, graph_funcs)
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE)
    else:
      all_results = json.load(open(output, 'r'))
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE, metric_only=True)

    with open(output + '_cocometric.json', 'w') as f:
      json.dump(eval_metrics, f)

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--load', help='load a model for evaluation.', required=True)
  parser.add_argument(
      '--visualize', action='store_true', help='visualize intermediate results')
  parser.add_argument(
      '--predict_unlabeled', help='visualize intermediate results')
  parser.add_argument('--eval_unlabeled', help='visualize intermediate results')
  parser.add_argument(
      '--evaluate',
      help='Run evaluation. '
      'This argument is the path to the output json evaluation file')
  parser.add_argument(
      '--predict',
      help='Run prediction on a given image. '
      'This argument is the path to the input image file',
      nargs='+')
  parser.add_argument(
      '--benchmark',
      action='store_true',
      help='Benchmark the speed of the model + postprocessing')
  parser.add_argument(
      '--config',
      help='A list of KEY=VALUE to overwrite those defined in config.py',
      nargs='+')
  parser.add_argument('--output-pb', help='Save a model to .pb')
  parser.add_argument('--output-serving', help='Save a model to serving file')

  args = parser.parse_args()
  if args.config:
    cfg.update_args(args.config)
  try:
    register_voc(cfg.DATA.BASEDIR)  # add VOC datasets to the registry
  except NotImplementedError:
    logger.warning('VOC does not find!')
  register_coco(cfg.DATA.BASEDIR)  # add COCO datasets to the registry
  MODEL = ResNetFPNModel() if cfg.MODE_FPN else ResNetC4Model()

  if not tf.test.is_gpu_available():
    assert get_tf_version_tuple() >= (1, 7) and test_util.IsMklEnabled(), \
        'Inference requires either GPU support or MKL support!'
  assert args.load
  finalize_configs(is_training=False)

  if args.predict or args.visualize:
    cfg.TEST.RESULT_SCORE_THRESH = cfg.TEST.RESULT_SCORE_THRESH_VIS

  # let the output has the same path logic as checkpoint
  if args.predict_unlabeled:
    output_dir = args.predict_unlabeled
    predict_unlabeled(MODEL, args.load, output_dir=output_dir)

  if args.visualize:
    do_visualize(MODEL, args.load, output_dir=output_dir)
  else:
    predcfg = PredictConfig(
        model=MODEL,
        session_init=SmartInit(args.load),
        input_names=MODEL.get_inference_tensor_names()[0],
        output_names=MODEL.get_inference_tensor_names()[1])

    if args.output_pb:
      ModelExporter(predcfg).export_compact(args.output_pb, optimize=False)
    elif args.output_serving:
      ModelExporter(predcfg).export_serving(args.output_serving, optimize=False)

    if args.predict:
      predictor = OfflinePredictor(predcfg)
      for image_file in args.predict:
        do_predict(predictor, image_file)
    elif args.evaluate:
      assert args.evaluate.endswith('.json'), args.evaluate
      do_evaluate(predcfg, args.evaluate)
    elif args.eval_unlabeled:
      assert args.eval_unlabeled.endswith('.json'), args.eval_unlabeled
      do_evaluate_unlabeled(predcfg, args.eval_unlabeled)
    elif args.benchmark:
      df = get_eval_dataflow(cfg.DATA.VAL[0])
      df.reset_state()
      predictor = OfflinePredictor(predcfg)
      for _, img in enumerate(tqdm.tqdm(df, total=len(df), smoothing=0.5)):
        predict_image(img[0], predictor)


"""Inference entrance."""
# pylint: disable=redefined-outer-name
# pylint: disable=redefined-builtin
# pylint: disable=unused-variable
import argparse
import collections
import itertools
import numpy as np
import os
import shutil
import cv2
import tqdm
import deepdish as dd
import json

import tensorflow as tf
from tensorflow.python.framework import test_util

import tensorpack.utils.viz as tpviz
from tensorpack.predict import MultiTowerOfflinePredictor, OfflinePredictor, PredictConfig
from tensorpack.tfutils import SmartInit, get_tf_version_tuple
from tensorpack.tfutils.export import ModelExporter
from tensorpack.utils import fs, logger

from dataset import register_coco, register_voc
from config import config as cfg
from config import finalize_configs

from data import get_eval_unlabeled_dataflow

from FasterRCNN.dataset import DatasetRegistry
from FasterRCNN.data import get_eval_dataflow
from FasterRCNN.eval import DetectionResult, multithread_predict_dataflow, predict_image
from FasterRCNN.modeling.generalized_rcnn import ResNetFPNModel, ResNetC4Model
from FasterRCNN.viz import draw_final_outputs, draw_predictions
from FasterRCNN.utils import custom
from FasterRCNN.predict import do_evaluate, do_predict, do_visualize

def predict_unlabeled(model,
                      model_path,
                      nr_visualize=100,
                      output_dir='output_patch_samp

les'):
  """Predict the pseudo label information of unlabeled data."""

  assert cfg.EVAL.PSEUDO_INFERENCE, 'set cfg.EVAL.PSEUDO_INFERENCE=True'
  df, dataset_size = get_eval_unlabeled_dataflow(
      cfg.DATA.TRAIN, return_size=True)
  df.reset_state()
  predcfg = PredictConfig(
      model=model,
      session_init=SmartInit(model_path),
      input_names=['image'],  # ['image', 'gt_boxes', 'gt_labels'],
      output_names=[
          'generate_{}_proposals/boxes'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'generate_{}_proposals/scores'.format(
              'fpn' if cfg.MODE_FPN else 'rpn'),
          'fastrcnn_all_scores',
          'output/boxes',
          'output/scores',  # score of the labels
          'output/labels',
      ])
  pred = OfflinePredictor(predcfg)

  if os.path.isdir(output_dir):
    if os.path.isfile(os.path.join(output_dir, 'pseudo_data.npy')):
      os.remove(os.path.join(output_dir, 'pseudo_data.npy'))
    if not os.path.isdir(os.path.join(output_dir, 'vis')):
      os.makedirs(os.path.join(output_dir, 'vis'))
    else:
      shutil.rmtree(os.path.join(output_dir, 'vis'))
      fs.mkdir_p(output_dir + '/vis')
  else:
    fs.mkdir_p(output_dir)
    fs.mkdir_p(output_dir + '/vis')
  logger.warning('-' * 100)
  logger.warning('Write to {}'.format(output_dir))
  logger.warning('-' * 100)

  with tqdm.tqdm(total=nr_visualize) as pbar:
    for idx, dp in itertools.islice(enumerate(df), nr_visualize):
      img, img_id = dp  # dp['image'], dp['img_id']
      rpn_boxes, rpn_scores, all_scores, \
          final_boxes, final_scores, final_labels = pred(img)
      outs = {
          'proposals_boxes': rpn_boxes,  # (?,4)
          'proposals_scores': rpn_scores,  # (?,)
          'boxes': final_boxes,
          'scores': final_scores,
          'labels': final_labels
      }
      ratios = [10, 10]  # [top 20% as background, bottom 20% as background]
      bg_ind, fg_ind = custom.find_bg_and_fg_proposals(
          all_scores, ratios=ratios)

      bg_viz = draw_predictions(img, rpn_boxes[bg_ind], all_scores[bg_ind])

      fg_viz = draw_predictions(img, rpn_boxes[fg_ind], all_scores[fg_ind])

      results = [
          DetectionResult(*args)
          for args in zip(final_boxes, final_scores, final_labels, [None] *
                          len(final_labels))
      ]
      final_viz = draw_final_outputs(img, results)

      viz = tpviz.stack_patches([bg_viz, fg_viz, final_viz], 2, 2)

      if os.environ.get('DISPLAY', None):
        tpviz.interactive_imshow(viz)
      assert cv2.imwrite('{}/vis/{:03d}.png'.format(output_dir, idx), viz)
      pbar.update()
  logger.info('Write {} samples to {}'.format(nr_visualize, output_dir))

  ## Parallel inference the whole unlabled data
  pseudo_preds = collections.defaultdict(list)

  num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
  graph_funcs = MultiTowerOfflinePredictor(predcfg, list(
      range(num_tower))).get_predictors()
  dataflows = [
      get_eval_unlabeled_dataflow(
          cfg.DATA.TRAIN, shard=k, num_shards=num_tower)
      for k in range(num_tower)
  ]

  all_results = multithread_predict_dataflow(dataflows, graph_funcs)

  for id, result in tqdm.tqdm(enumerate(all_results)):
    img_id = result['image_id']
    outs = {
        'proposals_boxes': result['proposal_box'].astype(np.float16),  # (?,4)
        'proposals_scores': result['proposal_score'].astype(np.float16),  # (?,)
        'boxes': result['bbox'].astype(np.float16),  # (?,4)
        'scores': result['score'].astype(np.float16),  # (?,)
        'labels':
            result['category_id'].astype(np.float16)  # (?,)
    }
    pseudo_preds[img_id] = outs
  logger.warn('Writing to {}'.format(
      os.path.join(output_dir, 'pseudo_data.npy')))
  try:
    dd.io.save(os.path.join(output_dir, 'pseudo_data.npy'), pseudo_preds)
  except RuntimeError:
    logger.error('Save failed. Check reasons manually...')

def do_evaluate_unlabeled(pred_config, output_file, reuse=True):
  """Evaluate unlabled data."""

  for i, dataset in enumerate(cfg.DATA.VAL):
    output = output_file + '-' + dataset
    if not os.path.isfile(output) or not reuse:
      if i == 0:
        num_tower = max(cfg.TRAIN.NUM_GPUS, 1)
        graph_funcs = MultiTowerOfflinePredictor(
            pred_config, list(range(num_tower))).get_predictors()
      logger.info('Evaluating {} ...'.format(dataset))
      dataflows = [
          get_eval_dataflow(dataset, shard=k, num_shards=num_tower)
          for k in range(num_tower)
      ]
      all_results = multithread_predict_dataflow(dataflows, graph_funcs)
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE)
    else:
      all_results = json.load(open(output, 'r'))
      eval_metrics = DatasetRegistry.get(dataset).eval_inference_results2(
          all_results, output, threshold=cfg.TRAIN.CONFIDENCE, metric_only=True)

    with open(output + '_cocometric.json', 'w') as f:
      json.dump(eval_metrics, f)

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--load', help='load a model for evaluation.', required=True)
  parser.add_argument(
      '--visualize', action='store_true', help='visualize intermediate results')
  parser.add_argument(
      '--predict_unlabeled', help='visualize intermediate results')
  parser.add_argument('--eval_unlabeled', help='visualize intermediate results')
  parser.add_argument(
      '--evaluate',
      help='Run evaluation. '
      'This argument is the path to the output json evaluation file')
  parser.add_argument(
      '--predict',
      help='Run prediction on a given image. '
      'This argument is the path to the input image file',
      nargs='+')
  parser.add_argument(
      '--benchmark',
      action='store_true',
      help='Benchmark the speed of the model + postprocessing')
  parser.add_argument(
      '--config',
      help='A list of KEY=VALUE to overwrite those defined in config.py',
      nargs='+')
  parser.add_argument('--output-pb', help='Save a model to .pb')
  parser.add_argument('--output-serving', help='Save a model to serving file')

  args = parser.parse_args()
  if args.config:
    cfg.update_args(args.config)
  try:
    register_voc(cfg.DATA.BASEDIR)  # add VOC datasets to the registry
  except NotImplementedError:
    logger.warning('VOC does not find!')
  register_coco(cfg.DATA.BASEDIR)  # add COCO datasets to the registry
  MODEL = ResNetFPNModel() if cfg.MODE_FPN else ResNetC4Model()

  if not tf.test.is_gpu_available():
    assert get_tf_version_tuple() >= (1, 7) and test_util.IsMklEnabled(), \
        'Inference requires either GPU support or MKL support!'
  assert args.load
  finalize_configs(is_training=False)

  if args.predict or args.visualize:
    cfg.TEST.RESULT_SCORE_THRESH = cfg.TEST.RESULT_SCORE_THRESH_VIS

  # let the output has the same path logic as checkpoint
  if args.predict_unlabeled:
    output_dir = args.predict_unlabeled
    predict_unlabeled(MODEL, args.load, output_dir=output_dir)

  if args.visualize:
    do_visualize(MODEL, args.load, output_dir=output_dir)
  else:
    predcfg = PredictConfig(
        model=MODEL,
        session_init=SmartInit(args.load),
        input_names=MODEL.get_inference_tensor_names()[0],
        output_names=MODEL.get_inference_tensor_names()[1])

    if args.output_pb:
      ModelExporter(predcfg).export_compact(args.output_pb, optimize=False)
    elif args.output_serving:
      ModelExporter(predcfg).export_serving(args.output_serving, optimize=False)

    if args.predict:
      predictor = OfflinePredictor(predcfg)
      for image_file in args.predict:
        do_predict(predictor, image_file)
    elif args.evaluate:
      assert args.evaluate.endswith('.json'), args.evaluate
      do_evaluate(predcfg, args.evaluate)
    elif args.eval_unlabeled:
      assert args.eval_unlabeled.endswith('.json'), args.eval_unlabeled
      do_evaluate_unlabeled(predcfg, args.eval_unlabeled)
    elif args.benchmark:
      df = get_eval_dataflow(cfg.DATA.VAL[0])
      df.reset_state()
      predictor = OfflinePredictor(predcfg)
      for _, img in enumerate(tqdm.tqdm(df, total=len(df), smoothing=0.5)):
        predict_image(img[0], predictor)


from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_c

    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(
        'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


from ..packages_finder import download_dependencies
from ..utils import add_url_argument
from ..utils import add_verbose_argument
from ..utils import read_package_configuration
from ..utils import setup_build

def find_dependencies(dependencies_configs):
    packages = []

    for dependency_config in dependencies_configs:
        name = dependency_config.name

        if name == 'fiber':
            continue

        version = dependency_config.from_version
        current_version = dependency_config.version
        packages.append((name, version, current_version))

    return packages

def show(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, version, _ in packages:
        if isinstance(version, str):
            version = f'"{version}"'
        else:
            version = f'{{ path = "{version["path"]}" }}'

        print(f'{name} = {version}')

def versions(url):
    config = read_package_configuration()
    setup_build()
    dependencies_configs = download_dependencies(config, url)
    packages = find_dependencies(dependencies_configs)

    for name, _, current_version in packages:
        print(f'{name} = "{current_version}"')

def do_dependencies(_parser, args, _mys_config):
    if args.versions:
        versions(args.url)
    else:
        show(args.url)

def add_subparser(subparsers):
    subparser = subparsers.add_parser(

    'dependencies',
        description='Show dependencies.')
    add_verbose_argument(subparser)
    add_url_argument(subparser)
    subparser.add_argument(
        '--versions',
        action='store_true',
        help='Show all package versions currently used by this package.')
    subparser.set_defaults(func=do_dependencies)


import sys

"""python3"""

import os
import json
import time
import codecs
import random
import argparse

import numpy as np

from tqdm import tqdm
from importlib import import_module

import tensorflow as tf
import keras.backend.tensorflow_backend as KTF

config = tf.ConfigProto()
config.gpu_options.allow_growth=True   #不全部占满显存, 按需分配
sess = tf.Session(config=config)

# 设置session
KTF.set_session(sess)

global args

parse=argparse.ArgumentParser()
    parse.add_argument('--model', '-m',     type=str, required=True, help='model file name in .model/')
    parse.add_argument('--model_param',     type=str, default=None, help='model parameters, in form of str(json)')
    parse.add_argument('--w2v_path',        type=str, help='word2vec file path, google w2v form', default='../data/vectorsw300l20.all')
    parse.add_argument('--train',           type=str, required=True, help='train data path')
    parse.add_argument('--test',            type=str, required=True, help='test data path')

    parse.add_argument('--model_path',      type=str, required=True, help='model files path')
    parse.add_argument('--output_path',      type=str, required=True, help='output files path')
    parse.add_argument('--log_path',        type=str, default=None, help='model files path')

    parse.add_argument('--train_base_func', type=str, default=None, help='train data basic deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_deal_func', type=str, default=None, help='train data deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_pad_func',  type=str, default=None, help='train data pad function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--test_base_func',  type=str, default=None, help='test form, default is the same as train form, basic deal, usually same as train')
    parse.add_argument('--test_deal_func',  type=str, default=None, help='test form, default is the same as train form')
    parse.add_argument('--test_pad_func',   type=str, default=None, help='test form, default is the same as train form')

    parse.add_argument('--need_train',      type=str, default='True', help='need to train')
    parse.add_argument('--need_test',       type=str, default='True', help='need to test')

    parse.add_argument('--recover_func',    type=str, default='recover_kbqa', help='recover function, combine NN results to raw datas, for evaluate and output.')
    parse.add_argument('--gpu_fraction',    type=int, default=1, help='n=gpu_fraction, then the memory will be 1/n of all. dafault=1')
    parse.add_argument('--train_data_size', type=int, default=8000, help='train data size')
    parse.add_argument('--train_batch_size', type=int, default=64, help='train batch size')
    parse.add_argument('--test_batch_size', type=int, default=64, help='test batch size')
    parse.add_argument('--train_epoch_num', type=int, default=25, help='train epoch num')
    parse.add_argument('--start_epoch_num', type=int, default=-1, help='train epoch num')

    args_ret=parse.parse_args()
    print(args_ret)

    return vars(args_ret)
if __name__ == '__main__':
    args = getArgs()

    """   gpu_fraction   """
    if not args['gpu_fraction'] == 1 :
        from keras.backend.tensorflow_backend import set_session
        import tensorflow as tf

        rate_t = .9 / args['gpu_fraction']
        config = tf.ConfigProto()
        config.gpu_options.per_process_gpu_memory_fraction = rate_t
        set_session(tf.Session(config=config))

    """   other parameters   """
    args['train_batch_size'] = args['train_batch_size'] # 64
    args['train_data_size'] = args['train_data_size'] # 8000
    args['test_batch_size'] = args['test_batch_size'] # 64
    args['train_epoch_num'] = args['train_epoch_num'] # 25
    args['need_train'] = args['need_train'].lower() in ['true', 't', 'truth']
    args['need_test'] = args['need_test'].lower() in ['true', 't', 'truth']

    """   model and log files path   """
    if not os.path.exists(args['model_path']) :
        os.makedirs(args['model_path'])
    if args['log_path'] is None :
        for i in range(10000) :
            log_name = os.path.join(args['model_path'], 'log_%d'%(i))
            if os.path.exists(log_name) :
                continue
            break
        args['log_path'] = log_name
    args['log'] = codecs.open(args['log_path'], 'w', 'utf-8')

    """   output files path   """
    if not os.path.exists(args['output_path']) :
        os.makedirs(args['output_path'])

    global get_model, preprocess
    """   import get_model function   """
    sys.path.append('model')
    model_file = import_module(args['model'])
    if args['model_param'] is None :
        get_model = model_file.get_model
    else :
        args['model_param'] = json.loads(args['model_param'])
        get_model = lambda x : model_file.get_model(x, args['model_param'])

    """   import recover function   """
    import recover_datas
    recover = eval('recover_datas.%s'%(args['recover_func']))

    """   deal preprocess object   """
    from preprocess import CPreprocess
    from data_delegate import CData

    preprocess = CPreprocess(w2v_path = args['w2v_path'])
    args['train_base_func'] = getattr(preprocess, args['train_base_func']) if not args['train_base_func'] is None else lambda x : x
    args['train_deal_func'] = getattr(preprocess, args['train_deal_func']) if not args['train_deal_func'] is None else lambda x : x
    args['train_pad_func']  = getattr(preprocess, args['train_pad_func']) if not args['train_pad_func'] is None else lambda x : x
    args['test_base_func']  = getattr(preprocess, args['test_base_func']) if not args['test_base_func'] is None else args['train_base_func']
    args['test_deal_func']  = getattr(preprocess, args['test_deal_func']) if not args['test_deal_func'] is None else args['train_deal_func']
    args['test_pad_func']   = getattr(preprocess, args['test_pad_func']) if not args['test_pad_func'] is None else args['train_pad_func']

    print(args)

if __name__ == '__main__':
    """   定义数据   """
    data_train = CData(args['train'], default_size=args['train_data_size'])
    data_test  = CData(args['test'])
    to_tests = {
        'data_test'  : data_test,
    }

    """   定义模型和数据预处理模式   """
    model = get_model(preprocess.get_w2v_matrix())
    get_train_data = lambda x : x.get_data_generator(
        args['train_pad_func'], args['train_batch_size'],
        deal_base_func=args['train_base_func'],
        deal_function=args['train_deal_func'],
        verbose=True)
    get_test_data  = lambda x : x.get_data_generator(
        args['test_pad_func'], args['test_batch_size'],
        deal_base_func=args['test_base_func'],
        deal_function=args['test_deal_func'],
        size=False, shuffle=False, verbose=True)

    train_loss = ' '
    test_loss = ' '
    """   epoches 循环   """
    for iters in range(args['train_epoch_num']) :
        if iters < args['start_epoch_num'] :
            continue
        print('epoches : %d'%(iters))
        model_path_t = os.path.join(args['model_path'], 'model_%d'%(iters))

        """   train   """
        if args['need_train'] :
            train_generator = get_train_data(data_train)
            history = model.fit_generator(train_generator, data_train.it_size, epochs=1, shuffle=False)
            train_loss = str(history.history['loss'])
            model.save_weights(model_path_t)
        else :
            model.load_weights(model_path_t)

        """   test & output   """
        if args['need_test'] :
            test_loss = {}
            kv_list = [[k, to_tests[k]] for k in to_tests]
            for name, data in kv_list :
                test_generator = get_test_data(data)

                # simple_evaluate

                # evaluate & log
                test_predicted = model.predict_generator(test_generator, data.it_size, verbose=1)
                data_recovered, scores = recover(data.get_data(), test_predicted.tolist())

                output_path = os.path.join(args['output_path'], '%s_%d.json'%(name, iters))
                json.dump(data_recovered, codecs.open(output_path, 'w', 'utf-8'))

                test_loss[name] = scores
            test_loss = str(test_loss)

        """   write log   """
        args['log'].write('epoches : %d'%(iters)+'\n')
        args['log'].write(train_loss+'\n')
        args['log'].write(test_loss+'\n\n')
        args['log'].flush()
    args['log'].flush()


parse=argparse.ArgumentParser()
    parse.add_argument('--model', '-m',     type=str, required=True, help='model file name in .model/')
    parse.add_argument('--model_param',     type=str, default=None, help='model parameters, in form of str(json)')
    parse.add_argument('--w2v_path',        type=str, help='word2vec file path, google w2v form', default='../data/vectorsw300l20.all')
    parse.add_argument('--train',           type=str, required=True, help='train data path')
    parse.add_argument('--test',            type=str, required=True, help='test data path')

    parse.add_argument('--model_path',      type=str, required=True, help='model files path')
    parse.add_argument('--output_path',      type=str, required=True, help='output files path')
    parse.add_argument('--log_path',        type=str, default=None, help='model files path')

import sys

"""python3"""

import os
import json
import time
import codecs
import random
import argparse

import numpy as np

from tqdm import tqdm
from importlib import import_module

import tensorflow as tf
import keras.backend.tensorflow_backend as KTF

config = tf.ConfigProto()
config.gpu_options.allow_growth=True   #不全部占满显存, 按需分配
sess = tf.Session(config=config)

# 设置session
KTF.set_session(sess)

global args
def getArgs():

    parse.add_argument('--train_base_func', type=str, default=None, help='train data basic deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_deal_func', type=str, default=None, help='train data deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_pad_func',  type=str, default=None, help='train data pad function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--test_base_func',  type=str, default=None, help='test form, default is the same as train form, basic deal, usually same as train')
    parse.add_argument('--test_deal_func',  type=str, default=None, help='test form, default is the same as train form')
    parse.add_argument('--test_pad_func',   type=str, default=None, help='test form, default is the same as train form')

    parse.add_argument('--need_train',      type=str, default='True', help='need to train')
    parse.add_argument('--need_test',       type=str, default='True', help='need to test')

    parse.add_argument('--recover_func',    type=str, default='recover_kbqa', help='recover function, combine NN results to raw datas, for evaluate and output.')
    parse.add_argument('--gpu_fraction',    type=int, default=1, help='n=gpu_fraction, then the memory will be 1/n of all. dafault=1')
    parse.add_argument('--train_data_size', type=int, default=8000, help='train data size')
    parse.add_argument('--train_batch_size', type=int, default=64, help='train batch size')
    parse.add_argument('--test_batch_size', type=int, default=64, help='test batch size')
    parse.add_argument('--train_epoch_num', type=int, default=25, help='train epoch num')
    parse.add_argument('--start_epoch_num', type=int, default=-1, help='train epoch num')

    args_ret=parse.parse_args()
    print(args_ret)

    return vars(args_ret)
if __name__ == '__main__':
    args = getArgs()

    """   gpu_fraction   """
    if not args['gpu_fraction'] == 1 :
        from keras.backend.tensorflow_backend import set_session
        import tensorflow as tf

        rate_t = .9 / args['gpu_fraction']
        config = tf.ConfigProto()
        config.gpu_options.per_process_gpu_memory_fraction = rate_t
        set_session(tf.Session(config=config))

    """   other parameters   """
    args['train_batch_size'] = args['train_batch_size'] # 64
    args['train_data_size'] = args['train_data_size'] # 8000
    args['test_batch_size'] = args['test_batch_size'] # 64
    args['train_epoch_num'] = args['train_epoch_num'] # 25
    args['need_train'] = args['need_train'].lower() in ['true', 't', 'truth']
    args['need_test'] = args['need_test'].lower() in ['true', 't', 'truth']

    """   model and log files path   """
    if not os.path.exists(args['model_path']) :
        os.makedirs(args['model_path'])
    if args['log_path'] is None :
        for i in range(10000) :
            log_name = os.path.join(args['model_path'], 'log_%d'%(i))
            if os.path.exists(log_name) :
                continue
            break
        args['log_path'] = log_name
    args['log'] = codecs.open(args['log_path'], 'w', 'utf-8')

    """   output files path   """
    if not os.path.exists(args['output_path']) :
        os.makedirs(args['output_path'])

    global get_model, preprocess
    """   import get_model function   """
    sys.path.append('model')
    model_file = import_module(args['model'])
    if args['model_param'] is None :
        get_model = model_file.get_model
    else :
        args['model_param'] = json.loads(args['model_param'])
        get_model = lambda x : model_file.get_model(x, args['model_param'])

    """   import recover function   """
    import recover_datas
    recover = eval('recover_datas.%s'%(args['recover_func']))

    """   deal preprocess object   """
    from preprocess import CPreprocess
    from data_delegate import CData

    preprocess = CPreprocess(w2v_path = args['w2v_path'])
    args['train_base_func'] = getattr(preprocess, args['train_base_func']) if not args['train_base_func'] is None else lambda x : x
    args['train_deal_func'] = getattr(preprocess, args['train_deal_func']) if not args['train_deal_func'] is None else lambda x : x
    args['train_pad_func']  = getattr(preprocess, args['train_pad_func']) if not args['train_pad_func'] is None else lambda x : x
    args['test_base_func']  = getattr(preprocess, args['test_base_func']) if not args['test_base_func'] is None else args['train_base_func']
    args['test_deal_func']  = getattr(preprocess, args['test_deal_func']) if not args['test_deal_func'] is None else args['train_deal_func']
    args['test_pad_func']   = getattr(preprocess, args['test_pad_func']) if not args['test_pad_func'] is None else args['train_pad_func']

    print(args)

if __name__ == '__main__':
    """   定义数据   """
    data_train = CData(args['train'], default_size=args['train_data_size'])
    data_test  = CData(args['test'])
    to_tests = {
        'data_test'  : data_test,
    }

    """   定义模型和数据预处理模式   """
    model = get_model(preprocess.get_w2v_matrix())
    get_train_data = lambda x : x.get_data_generator(
        args['train_pad_func'], args['train_batch_size'],
        deal_base_func=args['train_base_func'],
        deal_function=args['train_deal_func'],
        verbose=True)
    get_test_data  = lambda x : x.get_data_generator(
        args['test_pad_func'], args['test_batch_size'],
        deal_base_func=args['test_base_func'],
        deal_function=args['test_deal_func'],
        size=False, shuffle=False, verbose=True)

    train_loss = ' '
    test_loss = ' '
    """   epoches 循环   """
    for iters in range(args['train_epoch_num']) :
        if iters < args['start_epoch_num'] :
            continue
        print('epoches : %d'%(iters))
        model_path_t = os.path.join(args['model_path'], 'model_%d'%(iters))

        """   train   """
        if args['need_train'] :
            train_generator = get_train_data(data_train)
            history = model.fit_generator(train_generator, data_train.it_size, epochs=1, shuffle=False)
            train_loss = str(history.history['loss'])
            model.save_weights(model_path_t)
        else :
            model.load_weights(model_path_t)

        """   test & output   """
        if args['need_test'] :
            test_loss = {}
            kv_list = [[k, to_tests[k]] for k in to_tests]
            for name, data in kv_list :
                test_generator = get_test_data(data)

                # simple_evaluate

                # evaluate & log
                test_predicted = model.predict_generator(test_generator, data.it_size, verbose=1)
                data_recovered, scores = recover(data.get_data(), test_predicted.tolist())

                output_path = os.path.join(args['output_path'], '%s_%d.json'%(name, iters))
                json.dump(data_recovered, codecs.open(output_path, 'w', 'utf-8'))

                test_loss[name] = scores
            test_loss = str(test_loss)

        """   write log   """
        args['log'].write('epoches : %d'%(iters)+'\n')
        args['log'].write(train_loss+'\n')
        args['log'].write(test_loss+'\n\n')
        args['log'].flush()
    args['log'].flush()


parse.add_argument('--train_base_func', type=str, default=None, help='train data basic deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_deal_func', type=str, default=None, help='train data deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_pad_func',  type=str, default=None, help='train data pad function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--test_base_func',  type=str, default=None, help='test form, default is the same as train form, basic deal, usually same as train')
    parse.add_argument('--test_deal_func',  type=str, default=None, help='test form, default is the same as train form')
    parse.add_argument('--test_pad_func',   type=str, default=None, help='test form, default is the same as train form')

    parse.add_argument('--need_train',      type=str, default='True', help='need to train')
    parse.add_argument('--need_test',       type=str, default='True', help='need to test')

    parse.add_argument('--recover_func',    type=str, default='recover_kbqa', help='recover function, combine NN results to raw datas, for evaluate and output.')

import sys

"""python3"""

import os
import json
import time
import codecs
import random
import argparse

import numpy as np

from tqdm import tqdm
from importlib import import_module

import tensorflow as tf
import keras.backend.tensorflow_backend as KTF

config = tf.ConfigProto()
config.gpu_options.allow_growth=True   #不全部占满显存, 按需分配
sess = tf.Session(config=config)

# 设置session
KTF.set_session(sess)

global args
def getArgs():
    parse=argparse.ArgumentParser()
    parse.add_argument('--model', '-m',     type=str, required=True, help='model file name in .model/')
    parse.add_argument('--model_param',     type=str, default=None, help='model parameters, in form of str(json)')
    parse.add_argument('--w2v_path',        type=str, help='word2vec file path, google w2v form', default='../data/vectorsw300l20.all')
    parse.add_argument('--train',           type=str, required=True, help='train data path')
    parse.add_argument('--test',            type=str, required=True, help='test data path')

    parse.add_argument('--model_path',      type=str, required=True, help='model files path')
    parse.add_argument('--output_path',      type=str, required=True, help='output files path')
    parse.add_argument('--log_path',        type=str, default=None, help='model files path')

    parse.add_argument('--gpu_fraction',    type=int, default=1, help='n=gpu_fraction, then the memory will be 1/n of all. dafault=1')
    parse.add_argument('--train_data_size', type=int, default=8000, help='train data size')
    parse.add_argument('--train_batch_size', type=int, default=64, help='train batch size')
    parse.add_argument('--test_batch_size', type=int, default=64, help='test batch size')
    parse.add_argument('--train_epoch_num', type=int, default=25, help='train epoch num')
    parse.add_argument('--start_epoch_num', type=int, default=-1, help='train epoch num')

    args_ret=parse.parse_args()
    print(args_ret)

    return vars(args_ret)
if __name__ == '__main__':
    args = getArgs()

    """   gpu_fraction   """
    if not args['gpu_fraction'] == 1 :
        from keras.backend.tensorflow_backend import set_session
        import tensorflow as tf

        rate_t = .9 / args['gpu_fraction']
        config = tf.ConfigProto()
        config.gpu_options.per_process_gpu_memory_fraction = rate_t
        set_session(tf.Session(config=config))

    """   other parameters   """
    args['train_batch_size'] = args['train_batch_size'] # 64
    args['train_data_size'] = args['train_data_size'] # 8000
    args['test_batch_size'] = args['test_batch_size'] # 64
    args['train_epoch_num'] = args['train_epoch_num'] # 25
    args['need_train'] = args['need_train'].lower() in ['true', 't', 'truth']
    args['need_test'] = args['need_test'].lower() in ['true', 't', 'truth']

    """   model and log files path   """
    if not os.path.exists(args['model_path']) :
        os.makedirs(args['model_path'])
    if args['log_path'] is None :
        for i in range(10000) :
            log_name = os.path.join(args['model_path'], 'log_%d'%(i))
            if os.path.exists(log_name) :
                continue
            break
        args['log_path'] = log_name
    args['log'] = codecs.open(args['log_path'], 'w', 'utf-8')

    """   output files path   """
    if not os.path.exists(args['output_path']) :
        os.makedirs(args['output_path'])

    global get_model, preprocess
    """   import get_model function   """
    sys.path.append('model')
    model_file = import_module(args['model'])
    if args['model_param'] is None :
        get_model = model_file.get_model
    else :
        args['model_param'] = json.loads(args['model_param'])
        get_model = lambda x : model_file.get_model(x, args['model_param'])

    """   import recover function   """
    import recover_datas
    recover = eval('recover_datas.%s'%(args['recover_func']))

    """   deal preprocess object   """
    from preprocess import CPreprocess
    from data_delegate import CData

    preprocess = CPreprocess(w2v_path = args['w2v_path'])
    args['train_base_func'] = getattr(preprocess, args['train_base_func']) if not args['train_base_func'] is None else lambda x : x
    args['train_deal_func'] = getattr(preprocess, args['train_deal_func']) if not args['train_deal_func'] is None else lambda x : x
    args['train_pad_func']  = getattr(preprocess, args['train_pad_func']) if not args['train_pad_func'] is None else lambda x : x
    args['test_base_func']  = getattr(preprocess, args['test_base_func']) if not args['test_base_func'] is None else args['train_base_func']
    args['test_deal_func']  = getattr(preprocess, args['test_deal_func']) if not args['test_deal_func'] is None else args['train_deal_func']
    args['test_pad_func']   = getattr(preprocess, args['test_pad_func']) if not args['test_pad_func'] is None else args['train_pad_func']

    print(args)

if __name__ == '__main__':
    """   定义数据   """
    data_train = CData(args['train'], default_size=args['train_data_size'])
    data_test  = CData(args['test'])
    to_tests = {
        'data_test'  : data_test,
    }

    """   定义模型和数据预处理模式   """
    model = get_model(preprocess.get_w2v_matrix())
    get_train_data = lambda x : x.get_data_generator(
        args['train_pad_func'], args['train_batch_size'],
        deal_base_func=args['train_base_func'],
        deal_function=args['train_deal_func'],
        verbose=True)
    get_test_data  = lambda x : x.get_data_generator(
        args['test_pad_func'], args['test_batch_size'],
        deal_base_func=args['test_base_func'],
        deal_function=args['test_deal_func'],
        size=False, shuffle=False, verbose=True)

    train_loss = ' '
    test_loss = ' '
    """   epoches 循环   """
    for iters in range(args['train_epoch_num']) :
        if iters < args['start_epoch_num'] :
            continue
        print('epoches : %d'%(iters))
        model_path_t = os.path.join(args['model_path'], 'model_%d'%(iters))

        """   train   """
        if args['need_train'] :
            train_generator = get_train_data(data_train)
            history = model.fit_generator(train_generator, data_train.it_size, epochs=1, shuffle=False)
            train_loss = str(history.history['loss'])
            model.save_weights(model_path_t)
        else :
            model.load_weights(model_path_t)

        """   test & output   """
        if args['need_test'] :
            test_loss = {}
            kv_list = [[k, to_tests[k]] for k in to_tests]
            for name, data in kv_list :
                test_generator = get_test_data(data)

                # simple_evaluate

                # evaluate & log
                test_predicted = model.predict_generator(test_generator, data.it_size, verbose=1)
                data_recovered, scores = recover(data.get_data(), test_predicted.tolist())

                output_path = os.path.join(args['output_path'], '%s_%d.json'%(name, iters))
                json.dump(data_recovered, codecs.open(output_path, 'w', 'utf-8'))

                test_loss[name] = scores
            test_loss = str(test_loss)

        """   write log   """
        args['log'].write('epoches : %d'%(iters)+'\n')
        args['log'].write(train_loss+'\n')
        args['log'].write(test_loss+'\n\n')
        args['log'].flush()
    args['log'].flush()


parse.add_argument('--gpu_fraction',    type=int, default=1, help='n=gpu_fraction, then the memory will be 1/n of all. dafault=1')
    parse.add_argument('--train_data_size', type=int, default=8000, help='train data size')
    parse.add_argument('--train_batch_size', type=int, default=64, help='train batch size')
    parse.add_argument('--test_batch_size', type=int, default=64, help='test batch size')
    parse.add_argument('--train_epoch_num', type=int, default=25, help='train epoch num')
    parse.add_argument('--start_epoch_num', type=int, default=-1, help='train epoch num')

    args_ret=parse.parse_args()
    print(args_ret)

    return vars(args_ret)

import sys

"""python3"""

import os
import json
import time
import codecs
import random
import argparse

import numpy as np

from tqdm import tqdm
from importlib import import_module

import tensorflow as tf
import keras.backend.tensorflow_backend as KTF

config = tf.ConfigProto()
config.gpu_options.allow_growth=True   #不全部占满显存, 按需分配
sess = tf.Session(config=config)

# 设置session
KTF.set_session(sess)

global args
def getArgs():
    parse=argparse.ArgumentParser()
    parse.add_argument('--model', '-m',     type=str, required=True, help='model file name in .model/')
    parse.add_argument('--model_param',     type=str, default=None, help='model parameters, in form of str(json)')
    parse.add_argument('--w2v_path',        type=str, help='word2vec file path, google w2v form', default='../data/vectorsw300l20.all')
    parse.add_argument('--train',           type=str, required=True, help='train data path')
    parse.add_argument('--test',            type=str, required=True, help='test data path')

    parse.add_argument('--model_path',      type=str, required=True, help='model files path')
    parse.add_argument('--output_path',      type=str, required=True, help='output files path')
    parse.add_argument('--log_path',        type=str, default=None, help='model files path')

    parse.add_argument('--train_base_func', type=str, default=None, help='train data basic deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_deal_func', type=str, default=None, help='train data deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_pad_func',  type=str, default=None, help='train data pad function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--test_base_func',  type=str, default=None, help='test form, default is the same as train form, basic deal, usually same as train')
    parse.add_argument('--test_deal_func',  type=str, default=None, help='test form, default is the same as train form')
    parse.add_argument('--test_pad_func',   type=str, default=None, help='test form, default is the same as train form')

    parse.add_argument('--need_train',      type=str, default='True', help='need to train')
    parse.add_argument('--need_test',       type=str, default='True', help='need to test')

    parse.add_argument('--recover_func',    type=str, default='recover_kbqa', help='recover function, combine NN results to raw datas, for evaluate and output.')

if __name__ == '__main__':
    args = getArgs()

    """   gpu_fraction   """
    if not args['gpu_fraction'] == 1 :
        from keras.backend.tensorflow_backend import set_session
        import tensorflow as tf

        rate_t = .9 / args['gpu_fraction']
        config = tf.ConfigProto()
        config.gpu_options.per_process_gpu_memory_fraction = rate_t
        set_session(tf.Session(config=config))

    """   other parameters   """
    args['train_batch_size'] = args['train_batch_size'] # 64
    args['train_data_size'] = args['train_data_size'] # 8000
    args['test_batch_size'] = args['test_batch_size'] # 64
    args['train_epoch_num'] = args['train_epoch_num'] # 25
    args['need_train'] = args['need_train'].lower() in ['true', 't', 'truth']
    args['need_test'] = args['need_test'].lower() in ['true', 't', 'truth']

    """   model and log files path   """
    if not os.path.exists(args['model_path']) :
        os.makedirs(args['model_path'])
    if args['log_path'] is None :
        for i in range(10000) :
            log_name = os.path.join(args['model_path'], 'log_%d'%(i))
            if os.path.exists(log_name) :
                continue
            break
        args['log_path'] = log_name
    args['log'] = codecs.open(args['log_path'], 'w', 'utf-8')

    """   output files path   """
    if not os.path.exists(args['output_path']) :
        os.makedirs(args['output_path'])

    global get_model, preprocess
    """   import get_model function   """
    sys.path.append('model')
    model_file = import_module(args['model'])
    if args['model_param'] is None :
        get_model = model_file.get_model
    else :
        args['model_param'] = json.loads(args['model_param'])
        get_model = lambda x : model_file.get_model(x, args['model_param'])

    """   import recover function   """
    import recover_datas
    recover = eval('recover_datas.%s'%(args['recover_func']))

    """   deal preprocess object   """
    from preprocess import CPreprocess
    from data_delegate import CData

    preprocess = CPreprocess(w2v_path = args['w2v_path'])
    args['train_base_func'] = getattr(preprocess, args['train_base_func']) if not args['train_base_func'] is None else lambda x : x
    args['train_deal_func'] = getattr(preprocess, args['train_deal_func']) if not args['train_deal_func'] is None else lambda x : x
    args['train_pad_func']  = getattr(preprocess, args['train_pad_func']) if not args['train_pad_func'] is None else lambda x : x
    args['test_base_func']  = getattr(preprocess, args['test_base_func']) if not args['test_base_func'] is None else args['train_base_func']
    args['test_deal_func']  = getattr(preprocess, args['test_deal_func']) if not args['test_deal_func'] is None else args['train_deal_func']
    args['test_pad_func']   = getattr(preprocess, args['test_pad_func']) if not args['test_pad_func'] is None else args['train_pad_func']

    print(args)

if __name__ == '__main__':
    """   定义数据   """
    data_train = CData(args['train'], default_size=args['train_data_size'])
    data_test  = CData(args['test'])
    to_tests = {
        'data_test'  : data_test,
    }

    """   定义模型和数据预处理模式   """
    model = get_model(preprocess.get_w2v_matrix())
    get_train_data = lambda x : x.get_data_generator(
        args['train_pad_func'], args['train_batch_size'],
        deal_base_func=args['train_base_func'],
        deal_function=args['train_deal_func'],
        verbose=True)
    get_test_data  = lambda x : x.get_data_generator(
        args['test_pad_func'], args['test_batch_size'],
        deal_base_func=args['test_base_func'],
        deal_function=args['test_deal_func'],
        size=False, shuffle=False, verbose=True)

    train_loss = ' '
    test_loss = ' '
    """   epoches 循环   """
    for iters in range(args['train_epoch_num']) :
        if iters < args['start_epoch_num'] :
            continue
        print('epoches : %d'%(iters))
        model_path_t = os.path.join(args['model_path'], 'model_%d'%(iters))

        """   train   """
        if args['need_train'] :
            train_generator = get_train_data(data_train)
            history = model.fit_generator(train_generator, data_train.it_size, epochs=1, shuffle=False)
            train_loss = str(history.history['loss'])
            model.save_weights(model_path_t)
        else :
            model.load_weights(model_path_t)

        """   test & output   """
        if args['need_test'] :
            test_loss = {}
            kv_list = [[k, to_tests[k]] for k in to_tests]
            for name, data in kv_list :
                test_generator = get_test_data(data)

                # simple_evaluate

                # evaluate & log
                test_predicted = model.predict_generator(test_generator, data.it_size, verbose=1)
                data_recovered, scores = recover(data.get_data(), test_predicted.tolist())

                output_path = os.path.join(args['output_path'], '%s_%d.json'%(name, iters))
                json.dump(data_recovered, codecs.open(output_path, 'w', 'utf-8'))

                test_loss[name] = scores
            test_loss = str(test_loss)

        """   write log   """
        args['log'].write('epoches : %d'%(iters)+'\n')
        args['log'].write(train_loss+'\n')
        args['log'].write(test_loss+'\n\n')
        args['log'].flush()
    args['log'].flush()


.add_argument('--w2v_path',        type=str, help='word2vec file path, google w2v form', default='../data/vectorsw300l20.all')

import sys

"""python3"""

import os
import json
import time
import codecs
import random
import argparse

import numpy as np

from tqdm import tqdm
from importlib import import_module

import tensorflow as tf
import keras.backend.tensorflow_backend as KTF

config = tf.ConfigProto()
config.gpu_options.allow_growth=True   #不全部占满显存, 按需分配
sess = tf.Session(config=config)

# 设置session
KTF.set_session(sess)

global args
def getArgs():
    parse=argparse.ArgumentParser()
    parse.add_argument('--model', '-m',     type=str, required=True, help='model file name in .model/')
    parse.add_argument('--model_param',     type=str, default=None, help='model parameters, in form of str(json)')
    parse

    parse.add_argument('--train',           type=str, required=True, help='train data path')
    parse.add_argument('--test',            type=str, required=True, help='test data path')

    parse.add_argument('--model_path',      type=str, required=True, help='model files path')
    parse.add_argument('--output_path',      type=str, required=True, help='output files path')
    parse.add_argument('--log_path',        type=str, default=None, help='model files path')

    parse.add_argument('--train_base_func', type=str, default=None, help='train data basic deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_deal_func', type=str, default=None, help='train data deal function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--train_pad_func',  type=str, default=None, help='train data pad function name, a member of CPreprocess, default is lambda x : x')
    parse.add_argument('--test_base_func',  type=str, default=None, help='test form, default is the same as train form, basic deal, usually same as train')
    parse.add_argument('--test_deal_func',  type=str, default=None, help='test form, default is the same as train form')
    parse.add_argument('--test_pad_func',   type=str, default=None, help='test form, default is the same as train form')

    parse.add_argument('--need_train',      type=str, default='True', help='need to train')
    parse.add_argument('--need_test',       type=str, default='True', help='need to test')

    parse.add_argument('--recover_func',    type=str, default='recover_kbqa', help='recover function, combine NN results to raw datas, for evaluate and output.')
    parse.add_argument('--gpu_fraction',    type=int, default=1, help='n=gpu_fraction, then the memory will be 1/n of all. dafault=1')
    parse.add_argument('--train_data_size', type=int, default=8000, help='train data size')
    parse.add_argument('--train_batch_size', type=int, default=64, help='train batch size')
    parse.add_argument('--test_batch_size', type=int, default=64, help='test batch size')
    parse.add_argument('--train_epoch_num', type=int, default=25, help='train epoch num')
    parse.add_argument('--start_epoch_num', type=int, default=-1, help='train epoch num')

    args_ret=parse.parse_args()
    print(args_ret)

    return vars(args_ret)
if __name__ == '__main__':
    args = getArgs()

    """   gpu_fraction   """
    if not args['gpu_fraction'] == 1 :
        from keras.backend.tensorflow_backend import set_session
        import tensorflow as tf

        rate_t = .9 / args['gpu_fraction']
        config = tf.ConfigProto()
        config.gpu_options.per_process_gpu_memory_fraction = rate_t
        set_session(tf.Session(config=config))

    """   other parameters   """
    args['train_batch_size'] = args['train_batch_size'] # 64
    args['train_data_size'] = args['train_data_size'] # 8000
    args['test_batch_size'] = args['test_batch_size'] # 64
    args['train_epoch_num'] = args['train_epoch_num'] # 25
    args['need_train'] = args['need_train'].lower() in ['true', 't', 'truth']
    args['need_test'] = args['need_test'].lower() in ['true', 't', 'truth']

    """   model and log files path   """
    if not os.path.exists(args['model_path']) :
        os.makedirs(args['model_path'])
    if args['log_path'] is None :
        for i in range(10000) :
            log_name = os.path.join(args['model_path'], 'log_%d'%(i))
            if os.path.exists(log_name) :
                continue
            break
        args['log_path'] = log_name
    args['log'] = codecs.open(args['log_path'], 'w', 'utf-8')

    """   output files path   """
    if not os.path.exists(args['output_path']) :
        os.makedirs(args['output_path'])

    global get_model, preprocess
    """   import get_model function   """
    sys.path.append('model')
    model_file = import_module(args['model'])
    if args['model_param'] is None :
        get_model = model_file.get_model
    else :
        args['model_param'] = json.loads(args['model_param'])
        get_model = lambda x : model_file.get_model(x, args['model_param'])

    """   import recover function   """
    import recover_datas
    recover = eval('recover_datas.%s'%(args['recover_func']))

    """   deal preprocess object   """
    from preprocess import CPreprocess
    from data_delegate import CData

    preprocess = CPreprocess(w2v_path = args['w2v_path'])
    args['train_base_func'] = getattr(preprocess, args['train_base_func']) if not args['train_base_func'] is None else lambda x : x
    args['train_deal_func'] = getattr(preprocess, args['train_deal_func']) if not args['train_deal_func'] is None else lambda x : x
    args['train_pad_func']  = getattr(preprocess, args['train_pad_func']) if not args['train_pad_func'] is None else lambda x : x
    args['test_base_func']  = getattr(preprocess, args['test_base_func']) if not args['test_base_func'] is None else args['train_base_func']
    args['test_deal_func']  = getattr(preprocess, args['test_deal_func']) if not args['test_deal_func'] is None else args['train_deal_func']
    args['test_pad_func']   = getattr(preprocess, args['test_pad_func']) if not args['test_pad_func'] is None else args['train_pad_func']

    print(args)

if __name__ == '__main__':
    """   定义数据   """
    data_train = CData(args['train'], default_size=args['train_data_size'])
    data_test  = CData(args['test'])
    to_tests = {
        'data_test'  : data_test,
    }

    """   定义模型和数据预处理模式   """
    model = get_model(preprocess.get_w2v_matrix())
    get_train_data = lambda x : x.get_data_generator(
        args['train_pad_func'], args['train_batch_size'],
        deal_base_func=args['train_base_func'],
        deal_function=args['train_deal_func'],
        verbose=True)
    get_test_data  = lambda x : x.get_data_generator(
        args['test_pad_func'], args['test_batch_size'],
        deal_base_func=args['test_base_func'],
        deal_function=args['test_deal_func'],
        size=False, shuffle=False, verbose=True)

    train_loss = ' '
    test_loss = ' '
    """   epoches 循环   """
    for iters in range(args['train_epoch_num']) :
        if iters < args['start_epoch_num'] :
            continue
        print('epoches : %d'%(iters))
        model_path_t = os.path.join(args['model_path'], 'model_%d'%(iters))

        """   train   """
        if args['need_train'] :
            train_generator = get_train_data(data_train)
            history = model.fit_generator(train_generator, data_train.it_size, epochs=1, shuffle=False)
            train_loss = str(history.history['loss'])
            model.save_weights(model_path_t)
        else :
            model.load_weights(model_path_t)

        """   test & output   """
        if args['need_test'] :
            test_loss = {}
            kv_list = [[k, to_tests[k]] for k in to_tests]
            for name, data in kv_list :
                test_generator = get_test_data(data)

                # simple_evaluate

                # evaluate & log
                test_predicted = model.predict_generator(test_generator, data.it_size, verbose=1)
                data_recovered, scores = recover(data.get_data(), test_predicted.tolist())

                output_path = os.path.join(args['output_path'], '%s_%d.json'%(name, iters))
                json.dump(data_recovered, codecs.open(output_path, 'w', 'utf-8'))

                test_loss[name] = scores
            test_loss = str(test_loss)

        """   write log   """
        args['log'].write('epoches : %d'%(iters)+'\n')
        args['log'].write(train_loss+'\n')
        args['log'].write(test_loss+'\n\n')
        args['log'].flush()
    args['log'].flush()