def Func(arg_0='data'):
    """Load Matt Mahoney's dataset.

    Download a text file from Matt Mahoney's website
    if not present, and make sure it's the right size.
    Extract the first file enclosed in a zip file as a list of words.
    This dataset can be used for Word Embedding.

    Parameters
    ----------
    path : str
        The path that the data is downloaded to, defaults is ``data/mm_test8/``.

    Returns
    --------
    list of str
        The raw text data e.g. [.... 'their', 'families', 'who', 'were', 'expelled', 'from', 'jerusalem', ...]

    Examples
    --------
    >>> words = tl.files.Func()
    >>> print('Data size', len(words))

    """
    arg_0 = os.path.join(arg_0, 'mm_test8')
    logging.info("Load or Download matt_mahoney_text8 Dataset> {}".format(arg_0))

    arg_1 = 'text8.zip'
    arg_2 = 'http://mattmahoney.net/dc/'
    maybe_download_and_extract(arg_1, arg_0, arg_2, expected_bytes=31344016)

    with zipfile.ZipFile(os.path.join(arg_0, arg_1)) as f:
        arg_3 = f.read(f.namelist()[0]).split()
        for arg_4, arg_5 in enumerate(arg_3):
            arg_3[arg_4] = arg_3[arg_4].decode()
    return arg_3


def Func(
        arg_0='data', arg_1=None, arg_2=0, arg_3=None, arg_4=0.2, arg_5=113, arg_6=1, arg_7=2,
        arg_8=3
):
    """Load IMDB dataset.

    Parameters
    ----------
    path : str
        The path that the data is downloaded to, defaults is ``data/imdb/``.
    nb_words : int
        Number of words to get.
    skip_top : int
        Top most frequent words to ignore (they will appear as oov_char value in the sequence data).
    maxlen : int
        Maximum sequence length. Any longer sequence will be truncated.
    seed : int
        Seed for reproducible data shuffling.
    start_char : int
        The start of a sequence will be marked with this character. Set to 1 because 0 is usually the padding character.
    oov_char : int
        Words that were cut out because of the num_words or skip_top limit will be replaced with this character.
    index_from : int
        Index actual words with this index and higher.

    Examples
    --------
    >>> X_train, y_train, X_test, y_test = tl.files.Func(
    ...                                 nb_words=20000, test_split=0.2)
    >>> print('X_train.shape', X_train.shape)
    (20000,)  [[1, 62, 74, ... 1033, 507, 27],[1, 60, 33, ... 13, 1053, 7]..]
    >>> print('y_train.shape', y_train.shape)
    (20000,)  [1 0 0 ..., 1 0 1]

    References
    -----------
    - `Modified from keras. <https://github.com/fchollet/keras/blob/master/keras/datasets/imdb.py>`__

    """
    arg_0 = os.path.join(arg_0, 'imdb')

    arg_9 = "imdb.pkl"
    arg_10 = 'https://s3.amazonaws.com/text-datasets/'
    maybe_download_and_extract(arg_9, arg_0, arg_10)

    if arg_9.endswith(".gz"):
        arg_11 = gzip.open(os.path.join(arg_0, arg_9), 'rb')
    else:
        arg_11 = open(os.path.join(arg_0, arg_9), 'rb')

    arg_12, arg_13 = cPickle.load(arg_11)
    arg_11.close()

    np.random.seed(arg_5)
    np.random.shuffle(arg_12)
    np.random.seed(arg_5)
    np.random.shuffle(arg_13)

    if arg_6 is not None:
        arg_12 = [[arg_6] + [arg_20 + arg_8 for arg_20 in arg_16] for arg_16 in arg_12]
    elif arg_8:
        arg_12 = [[arg_20 + arg_8 for arg_20 in arg_16] for arg_16 in arg_12]

    if arg_3:
        arg_14 = []
        arg_15 = []
        for arg_16, arg_17 in zip(arg_12, arg_13):
            if len(arg_16) < arg_3:
                arg_14.append(arg_16)
                arg_15.append(arg_17)
        arg_12 = arg_14
        arg_13 = arg_15
    if not arg_12:
        raise Exception(
            'After filtering for sequences shorter than maxlen=' + str(arg_3) + ', no sequence was kept. '
            'Increase maxlen.'
        )
    if not arg_1:
        arg_1 = max([max(arg_16) for arg_16 in arg_12])

    # by convention, use 2 as OOV word
    # reserve 'index_from' (=3 by default) characters: 0 (padding), 1 (start), 2 (OOV)
    if arg_7 is not None:
        arg_12 = [[arg_7 if (arg_20 >= arg_1 or arg_20 < arg_2) else arg_20 for arg_20 in arg_16] for arg_16 in arg_12]
    else:
        arg_18 = []
        for arg_16 in arg_12:
            arg_19 = []
            for arg_20 in arg_16:
                if (arg_20 >= arg_1 or arg_20 < arg_2):
                    arg_19.append(arg_20)
            arg_18.append(arg_19)
        arg_12 = arg_18

    arg_21 = np.array(arg_12[:int(len(arg_12) * (1 - arg_4))])
    arg_22 = np.array(arg_13[:int(len(arg_12) * (1 - arg_4))])

    arg_23 = np.array(arg_12[int(len(arg_12) * (1 - arg_4)):])
    arg_24 = np.array(arg_13[int(len(arg_12) * (1 - arg_4)):])

    return arg_21, arg_22, arg_23, arg_24


def Func(arg_0='data'):
    """Load Nietzsche dataset.

    Parameters
    ----------
    path : str
        The path that the data is downloaded to, defaults is ``data/nietzsche/``.

    Returns
    --------
    str
        The content.

    Examples
    --------
    >>> see tutorial_generate_text.py
    >>> words = tl.files.Func()
    >>> words = basic_clean_str(words)
    >>> words = words.split()

    """
    logging.info("Load or Download nietzsche dataset > {}".format(arg_0))
    arg_0 = os.path.join(arg_0, 'nietzsche')

    arg_1 = "nietzsche.txt"
    arg_2 = 'https://s3.amazonaws.com/text-datasets/'
    arg_3 = maybe_download_and_extract(arg_1, arg_0, arg_2)

    with open(arg_3, "r") as f:
        arg_4 = f.read()
        return arg_4


def Func(arg_0='data'):
    """Load WMT'15 English-to-French translation dataset.

    It will download the data from the WMT'15 Website (10^9-French-English corpus), and the 2013 news test from the same site as development set.
    Returns the directories of training data and test data.

    Parameters
    ----------
    path : str
        The path that the data is downloaded to, defaults is ``data/wmt_en_fr/``.

    References
    ----------
    - Code modified from /tensorflow/models/rnn/translation/data_utils.py

    Notes
    -----
    Usually, it will take a long time to download this dataset.

    """
    arg_0 = os.path.join(arg_0, 'wmt_en_fr')
    # URLs for WMT data.
    arg_1 = "http://www.statmt.org/wmt10/"
    arg_2 = "http://www.statmt.org/wmt15/"

    def gunzip_file(arg_3, arg_4):
        """Unzips from gz_path into new_path."""
        logging.info("Unpacking %s to %s" % (arg_3, arg_4))
        with gzip.open(arg_3, "rb") as gz_file:
            with open(arg_4, "wb") as new_file:
                for arg_5 in gz_file:
                    new_file.write(arg_5)

    def get_wmt_enfr_train_set(arg_0):
        """Download the WMT en-fr training corpus to directory unless it's there."""
        arg_6 = "training-giga-fren.tar"
        maybe_download_and_extract(arg_6, arg_0, arg_1, extract=True)
        arg_7 = os.path.join(arg_0, "giga-fren.release2.fixed")
        gunzip_file(arg_7 + ".fr.gz", arg_7 + ".fr")
        gunzip_file(arg_7 + ".en.gz", arg_7 + ".en")
        return arg_7

    def get_wmt_enfr_dev_set(arg_0):
        """Download the WMT en-fr training corpus to directory unless it's there."""
        arg_6 = "dev-v2.tgz"
        arg_8 = maybe_download_and_extract(arg_6, arg_0, arg_2, extract=False)
        arg_9 = "newstest2013"
        arg_10 = os.path.join(arg_0, "newstest2013")
        if not (gfile.Exists(arg_10 + ".fr") and gfile.Exists(arg_10 + ".en")):
            logging.info("Extracting tgz file %s" % arg_8)
            with tarfile.open(arg_8, "r:gz") as dev_tar:
                arg_11 = dev_tar.getmember("dev/" + arg_9 + ".fr")
                arg_12 = dev_tar.getmember("dev/" + arg_9 + ".en")
                arg_11.name = arg_9 + ".fr"  # Extract without "dev/" prefix.
                arg_12.name = arg_9 + ".en"
                dev_tar.extract(arg_11, arg_0)
                dev_tar.extract(arg_12, arg_0)
        return arg_10

    logging.info("Load or Download WMT English-to-French translation > {}".format(arg_0))

    arg_7 = get_wmt_enfr_train_set(arg_0)
    arg_10 = get_wmt_enfr_dev_set(arg_0)

    return arg_7, arg_10


def Func(arg_0, arg_1):
    """Download file from Google Drive.

    See ``tl.files.load_celebA_dataset`` for example.

    Parameters
    --------------
    ID : str
        The driver ID.
    destination : str
        The destination for save file.

    """

    def save_response_content(arg_2, arg_1, arg_3=32 * 1024):
        arg_4 = int(arg_2.headers.get('content-length', 0))
        with open(arg_1, "wb") as f:
            for arg_5 in tqdm(arg_2.iter_content(arg_3), total=arg_4, unit='B', unit_scale=True,
                              desc=arg_1):
                if arg_5:  # filter out keep-alive new chunks
                    f.write(arg_5)

    def get_confirm_token(arg_2):
        for arg_6, arg_7 in arg_2.cookies.items():
            if arg_6.startswith('download_warning'):
                return arg_7
        return None

    arg_8 = "https://docs.google.com/uc?export=download"
    arg_9 = requests.Session()

    arg_2 = arg_9.get(arg_8, arg_11={'id': arg_0}, stream=True)
    arg_10 = get_confirm_token(arg_2)

    if arg_10:
        arg_11 = {'id': arg_0, 'confirm': arg_10}
        arg_2 = arg_9.get(arg_8, arg_11=arg_11, stream=True)
    save_response_content(arg_2, arg_1)


def Func(arg_0='data'):
    """Load CelebA dataset

    Return a list of image path.

    Parameters
    -----------
    path : str
        The path that the data is downloaded to, defaults is ``data/celebA/``.

    """
    arg_1 = 'celebA'
    arg_2, arg_3 = "img_align_celeba.zip", "0B7EVK8r0v71pZjFTYXZWM3FlRnM"
    arg_4 = os.path.join(arg_0, arg_2)
    arg_5 = os.path.join(arg_0, arg_1)
    if os.path.exists(arg_5):
        logging.info('[*] {} already exists'.format(arg_4))
    else:
        exists_or_mkdir(arg_0)
        download_file_from_google_drive(arg_3, arg_4)
        arg_6 = ''
        with zipfile.ZipFile(arg_4) as zf:
            arg_6 = zf.namelist()[0]
            zf.extractall(arg_0)
        os.remove(arg_4)
        os.rename(os.path.join(arg_0, arg_6), arg_5)

    arg_7 = load_file_list(arg_0=arg_5, regx='\\.jpg', printable=False)
    for arg_8, arg_9 in enumerate(arg_7):
        arg_7[arg_8] = os.path.join(arg_5, arg_7[arg_8])
    return arg_7


def Func(arg_0, arg_1, arg_2):
    """Assign the given parameters to the TensorLayer network.

    Parameters
    ----------
    sess : Session
        TensorFlow Session.
    params : list of array
        A list of parameters (array) in order.
    network : :class:`Layer`
        The network to be assigned.

    Returns
    --------
    list of operations
        A list of tf ops in order that assign params. Support sess.run(ops) manually.

    Examples
    --------
    - See ``tl.files.save_npz``

    References
    ----------
    - `Assign value to a TensorFlow variable <http://stackoverflow.com/questions/34220532/how-to-assign-value-to-a-tensorflow-variable>`__

    """
    arg_3 = []
    for arg_4, arg_5 in enumerate(arg_1):
        arg_3.append(arg_2.all_params[arg_4].assign(arg_5))
    if arg_0 is not None:
        arg_0.run(arg_3)
    return arg_3


def Func(arg_0=None, arg_1=None, arg_2=None):
    """Load model from npz and assign to a network.

    Parameters
    -------------
    sess : Session
        TensorFlow Session.
    name : str
        The name of the `.npz` file.
    network : :class:`Layer`
        The network to be assigned.

    Returns
    --------
    False or network
        Returns False, if the model is not exist.

    Examples
    --------
    - See ``tl.files.save_npz``

    """
    if arg_2 is None:
        raise ValueError("network is None.")
    if arg_0 is None:
        raise ValueError("session is None.")
    if not os.path.exists(arg_1):
        logging.error("file {} doesn't exist.".format(arg_1))
        return False
    else:
        arg_3 = load_npz(arg_1=arg_1)
        assign_params(arg_0, arg_3, arg_2)
        logging.info("[*] Load {} SUCCESS!".format(arg_1))
        return arg_2


def Func(arg_0=None, arg_1='model.npz', arg_2=None):
    """Input parameters and the file name, save parameters as a dictionary into .npz file.

    Use ``tl.files.load_and_assign_npz_dict()`` to restore.

    Parameters
    ----------
    save_list : list of parameters
        A list of parameters (tensor) to be saved.
    name : str
        The name of the `.npz` file.
    sess : Session
        TensorFlow Session.

    """
    if arg_2 is None:
        raise ValueError("session is None.")
    if arg_0 is None:
        arg_0 = []

    arg_3 = [tensor.name for tensor in arg_0]
    arg_4 = arg_2.run(arg_0)
    arg_5 = {arg_3[idx]: val for idx, val in enumerate(arg_4)}
    np.savez(arg_1, **arg_5)
    arg_4 = None
    arg_5 = None
    del arg_4
    del arg_5
    logging.info("[*] Model saved in npz_dict %s" % arg_1)


def Func(arg_0=None, arg_1='model.ckpt', arg_2='checkpoint', arg_3=None, arg_4=True, arg_5=False):
    """Load parameters from `ckpt` file.

    Parameters
    ------------
    sess : Session
        TensorFlow Session.
    mode_name : str
        The name of the model, default is ``model.ckpt``.
    save_dir : str
        The path / file directory to the `ckpt`, default is ``checkpoint``.
    var_list : list of tensor
        The parameters / variables (tensor) to be saved. If empty, save all global variables (default).
    is_latest : boolean
        Whether to load the latest `ckpt`, if False, load the `ckpt` with the name of ```mode_name``.
    printable : boolean
        Whether to print all parameters information.

    Examples
    ----------
    - Save all global parameters.

    >>> tl.files.save_ckpt(sess=sess, mode_name='model.ckpt', save_dir='model', printable=True)

    - Save specific parameters.

    >>> tl.files.save_ckpt(sess=sess, mode_name='model.ckpt', var_list=net.all_params, save_dir='model', printable=True)

    - Load latest ckpt.

    >>> tl.files.Func(sess=sess, var_list=net.all_params, save_dir='model', printable=True)

    - Load specific ckpt.

    >>> tl.files.Func(sess=sess, mode_name='model.ckpt', var_list=net.all_params, save_dir='model', is_latest=False, printable=True)

    """
    if arg_0 is None:
        raise ValueError("session is None.")
    if arg_3 is None:
        arg_3 = []

    if arg_4:
        arg_6 = tf.train.latest_checkpoint(arg_2)
    else:
        arg_6 = os.path.join(arg_2, arg_1)

    if not arg_3:
        arg_3 = tf.global_variables()

    logging.info("[*] load %s n_params: %d" % (arg_6, len(arg_3)))

    if arg_5:
        for arg_7, arg_8 in enumerate(arg_3):
            logging.info("  param {:3}: {:15}   {}".format(arg_7, arg_8.name, str(arg_8.get_shape())))

    try:
        arg_9 = tf.train.Saver(arg_3)
        arg_9.restore(arg_0, arg_6)
    except Exception as e:
        logging.info(e)
        logging.info("[*] load ckpt fail ...")


def Func(arg_0='', arg_1='file.npy'):
    """Load `.npy` file.

    Parameters
    ------------
    path : str
        Path to the file (optional).
    name : str
        File name.

    Examples
    ---------
    - see tl.files.save_any_to_npy()

    """
    arg_2 = os.path.join(arg_0, arg_1)
    try:
        return np.load(arg_2).item()
    except Exception:
        return np.load(arg_2)
    raise Exception("[!] Fail to load %s" % arg_2)


def Func(arg_0, arg_1, arg_2, arg_3=False, arg_4=None):
    """Checks if file exists in working_directory otherwise tries to dowload the file,
    and optionally also tries to extract the file if format is ".zip" or ".tar"

    Parameters
    -----------
    filename : str
        The name of the (to be) dowloaded file.
    working_directory : str
        A folder path to search for the file in and dowload the file to
    url : str
        The URL to download the file from
    extract : boolean
        If True, tries to uncompress the dowloaded file is ".tar.gz/.tar.bz2" or ".zip" file, default is False.
    expected_bytes : int or None
        If set tries to verify that the downloaded file is of the specified size, otherwise raises an Exception, defaults is None which corresponds to no check being performed.

    Returns
    ----------
    str
        File path of the dowloaded (uncompressed) file.

    Examples
    --------
    >>> down_file = tl.files.Func(filename='train-images-idx3-ubyte.gz',
    ...                                            working_directory='data/',
    ...                                            url_source='http://yann.lecun.com/exdb/mnist/')
    >>> tl.files.Func(filename='ADEChallengeData2016.zip',
    ...                                             working_directory='data/',
    ...                                             url_source='http://sceneparsing.csail.mit.edu/data/',
    ...                                             extract=True)

    """

    # We first define a download function, supporting both Python 2 and 3.
    def _download(arg_0, arg_1, arg_2):

        arg_5 = progressbar.ProgressBar()

        def _dlProgress(arg_6, arg_7, arg_8, arg_9=arg_5):
            if (arg_8 != 0):

                if not arg_9.max_value:
                    arg_10 = math.ceil(float(arg_8) / float(arg_7))
                    arg_9.max_value = int(arg_10)

                arg_9.update(arg_6, force=True)

        arg_12 = os.path.join(arg_1, arg_0)

        logging.info('Downloading %s...\n' % arg_0)

        urlretrieve(arg_2 + arg_0, arg_12, reporthook=_dlProgress)

    exists_or_mkdir(arg_1, verbose=False)
    arg_12 = os.path.join(arg_1, arg_0)

    if not os.path.exists(arg_12):

        _download(arg_0, arg_1, arg_2)
        arg_13 = os.stat(arg_12)
        logging.info('Succesfully downloaded %s %s bytes.' % (arg_0, arg_13.st_size))  # , 'bytes.')
        if (not (arg_4 is None) and (arg_4 != arg_13.st_size)):
            raise Exception('Failed to verify ' + arg_0 + '. Can you get to it with a browser?')
        if (arg_3):
            if tarfile.is_tarfile(arg_12):
                logging.info('Trying to extract tar file')
                tarfile.open(arg_12, 'r').extractall(arg_1)
                logging.info('... Success!')
            elif zipfile.is_zipfile(arg_12):
                logging.info('Trying to extract zip file')
                with zipfile.ZipFile(arg_12) as zf:
                    zf.extractall(arg_1)
                logging.info('... Success!')
            else:
                logging.info("Unknown compression_format only .tar.gz/.tar.bz2/.tar and .zip supported")
    return arg_12


def Func(arg_0=None, arg_1=None, arg_2=None, **arg_3):
    """Process a batch of data by given function by threading.

    Usually be used for data augmentation.

    Parameters
    -----------
    data : numpy.array or others
        The data to be processed.
    thread_count : int
        The number of threads to use.
    fn : function
        The function for data processing.
    more args : the args for `fn`
        Ssee Examples below.

    Examples
    --------
    Process images.

    >>> images, _, _, _ = tl.files.load_cifar10_dataset(shape=(-1, 32, 32, 3))
    >>> images = tl.prepro.Func(images[0:32], tl.prepro.zoom, zoom_range=[0.5, 1])

    Customized image preprocessing function.

    >>> def distort_img(x):
    >>>     x = tl.prepro.flip_axis(x, axis=0, is_random=True)
    >>>     x = tl.prepro.flip_axis(x, axis=1, is_random=True)
    >>>     x = tl.prepro.crop(x, 100, 100, is_random=True)
    >>>     return x
    >>> images = tl.prepro.Func(images, distort_img)

    Process images and masks together (Usually be used for image segmentation).

    >>> X, Y --> [batch_size, row, col, 1]
    >>> data = tl.prepro.Func([_ for _ in zip(X, Y)], tl.prepro.zoom_multi, zoom_range=[0.5, 1], is_random=True)
    data --> [batch_size, 2, row, col, 1]
    >>> X_, Y_ = data.transpose((1,0,2,3,4))
    X_, Y_ --> [batch_size, row, col, 1]
    >>> tl.vis.save_image(X_, 'images.png')
    >>> tl.vis.save_image(Y_, 'masks.png')

    Process images and masks together by using ``thread_count``.

    >>> X, Y --> [batch_size, row, col, 1]
    >>> data = tl.prepro.Func(X, tl.prepro.zoom_multi, 8, zoom_range=[0.5, 1], is_random=True)
    data --> [batch_size, 2, row, col, 1]
    >>> X_, Y_ = data.transpose((1,0,2,3,4))
    X_, Y_ --> [batch_size, row, col, 1]
    >>> tl.vis.save_image(X_, 'after.png')
    >>> tl.vis.save_image(Y_, 'before.png')

    Customized function for processing images and masks together.

    >>> def distort_img(data):
    >>>    x, y = data
    >>>    x, y = tl.prepro.flip_axis_multi([x, y], axis=0, is_random=True)
    >>>    x, y = tl.prepro.flip_axis_multi([x, y], axis=1, is_random=True)
    >>>    x, y = tl.prepro.crop_multi([x, y], 100, 100, is_random=True)
    >>>    return x, y

    >>> X, Y --> [batch_size, row, col, channel]
    >>> data = tl.prepro.Func([_ for _ in zip(X, Y)], distort_img)
    >>> X_, Y_ = data.transpose((1,0,2,3,4))

    Returns
    -------
    list or numpyarray
        The processed results.

    References
    ----------
    - `python queue <https://pymotw.com/2/Queue/index.html#module-Queue>`__
    - `run with limited queue <http://effbot.org/librarybook/queue.htm>`__

    """

    def apply_fn(arg_4, arg_5, arg_0, arg_3):
        arg_4[arg_5] = arg_1(arg_0, **arg_3)

    if arg_2 is None:
        arg_4 = [None] * len(arg_0)
        arg_6 = []
        # for i in range(len(data)):
        #     t = threading.Thread(name='threading_and_return', target=apply_fn, args=(results, i, data[i], kwargs))
        for arg_5, arg_7 in enumerate(arg_0):
            arg_8 = threading.Thread(name='threading_and_return', target=apply_fn, args=(arg_4, arg_5, arg_7, arg_3))
            arg_8.start()
            arg_6.append(arg_8)
    else:
        arg_9 = np.linspace(0, len(arg_0), arg_2 + 1)
        arg_9 = np.round(arg_9).astype(int)
        arg_4 = [None] * arg_2
        arg_6 = []
        for arg_5 in range(arg_2):
            arg_8 = threading.Thread(
                name='threading_and_return', target=apply_fn, args=(arg_4, arg_5, arg_0[arg_9[arg_5]:arg_9[arg_5 + 1]], arg_3)
            )
            arg_8.start()
            arg_6.append(arg_8)

    for arg_8 in arg_6:
        arg_8.join()

    if arg_2 is None:
        try:
            return np.asarray(arg_4)
        except Exception:
            return arg_4
    else:
        return np.concatenate(arg_4)


def Func(
        arg_0, arg_1, arg_2, arg_3=None, arg_4=None, arg_5=1, arg_6='constant', arg_7=0.0, arg_8=True,
        arg_9=False
):
    """Projective transform by given coordinates, usually 4 coordinates.

    see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`__.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    src : list or numpy
        The original coordinates, usually 4 coordinates of (width, height).
    dst : list or numpy
        The coordinates after transformation, the number of coordinates is the same with src.
    map_args : dictionary or None
        Keyword arguments passed to inverse map.
    output_shape : tuple of 2 int
        Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
    order : int
        The order of interpolation. The order has to be in the range 0-5:
            - 0 Nearest-neighbor
            - 1 Bi-linear (default)
            - 2 Bi-quadratic
            - 3 Bi-cubic
            - 4 Bi-quartic
            - 5 Bi-quintic
    mode : str
        One of `constant` (default), `edge`, `symmetric`, `reflect` or `wrap`.
        Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
    cval : float
        Used in conjunction with mode `constant`, the value outside the image boundaries.
    clip : boolean
        Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
    preserve_range : boolean
        Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    --------
    Assume X is an image from CIFAR-10, i.e. shape == (32, 32, 3)

    >>> src = [[0,0],[0,32],[32,0],[32,32]]     # [w, h]
    >>> dst = [[10,10],[0,32],[32,0],[32,32]]
    >>> x = tl.prepro.Func(X, src, dst)

    References
    -----------
    - `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`__
    - `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`__

    """
    if arg_3 is None:
        arg_3 = {}
    # if type(src) is list:
    if isinstance(arg_1, list):  # convert to numpy
        arg_1 = np.array(arg_1)
    # if type(dst) is list:
    if isinstance(arg_2, list):
        arg_2 = np.array(arg_2)
    if np.max(arg_0) > 1:  # convert to [0, 1]
        arg_0 = arg_0 / 255

    arg_10 = transform.ProjectiveTransform()
    arg_10.estimate(arg_2, arg_1)
    arg_11 = transform.warp(
        arg_0, arg_10, arg_3=arg_3, arg_4=arg_4, arg_5=arg_5, arg_6=arg_6, arg_7=arg_7, arg_8=arg_8,
        arg_9=arg_9
    )
    return arg_11


def Func(
        arg_0, arg_1=20, arg_2=False, arg_3=0, arg_4=1, arg_5=2, arg_6='nearest', arg_7=0., arg_8=1
):
    """Rotate an image randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    rg : int or float
        Degree to rotate, usually 0 ~ 180.
    is_random : boolean
        If True, randomly rotate. Default is False
    row_index col_index and channel_index : int
        Index of row, col and channel, default (0, 1, 2), for theano (1, 2, 0).
    fill_mode : str
        Method to fill missing pixel, default `nearest`, more options `constant`, `reflect` or `wrap`, see `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__
    cval : float
        Value used for points outside the boundaries of the input if mode=`constant`. Default is 0.0
    order : int
        The order of interpolation. The order has to be in the range 0-5. See ``tl.prepro.affine_transform`` and `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ---------
    >>> x --> [row, col, 1]
    >>> x = tl.prepro.Func(x, rg=40, is_random=False)
    >>> tl.vis.save_image(x, 'im.png')

    """
    if arg_2:
        arg_9 = np.pi / 180 * np.random.uniform(-arg_1, arg_1)
    else:
        arg_9 = np.pi / 180 * arg_1
    arg_10 = np.array([[np.cos(arg_9), -np.sin(arg_9), 0], [np.sin(arg_9), np.cos(arg_9), 0], [0, 0, 1]])

    arg_11, arg_12 = arg_0.shape[arg_3], arg_0.shape[arg_4]
    arg_13 = transform_matrix_offset_center(arg_10, arg_11, arg_12)
    arg_0 = affine_transform(arg_0, arg_13, arg_5, arg_6, arg_7, arg_8)
    return arg_0


def Func(arg_0, arg_1, arg_2, arg_3=False, arg_4=0, arg_5=1):
    """Randomly or centrally Func an image.

    Parameters
    ----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    wrg : int
        Size of width.
    hrg : int
        Size of height.
    is_random : boolean,
        If True, randomly Func, else central Func. Default is False.
    row_index: int
        index of row.
    col_index: int
        index of column.

    Returns
    -------
    numpy.array
        A processed image.

    """
    arg_6, arg_7 = arg_0.shape[arg_4], arg_0.shape[arg_5]

    if (arg_6 < arg_2) or (arg_7 < arg_1):
        raise AssertionError("The size of Funcping should smaller than or equal to the original image")

    if arg_3:
        arg_8 = int(np.random.uniform(0, arg_6 - arg_2))
        arg_9 = int(np.random.uniform(0, arg_7 - arg_1))
        # tl.logging.info(h_offset, w_offset, x[h_offset: hrg+h_offset ,w_offset: wrg+w_offset].shape)
        return arg_0[arg_8:arg_2 + arg_8, arg_9:arg_1 + arg_9]
    else:  # central Func
        arg_8 = int(np.floor((arg_6 - arg_2) / 2.))
        arg_9 = int(np.floor((arg_7 - arg_1) / 2.))
        arg_10 = arg_8 + arg_2
        arg_11 = arg_9 + arg_1
        return arg_0[arg_8:arg_10, arg_9:arg_11]


def Func(arg_0, arg_1, arg_2=False):
    """Flip the axises of multiple images together, such as flip left and right, up and down, randomly or non-randomly,

    Parameters
    -----------
    x : list of numpy.array
        List of images with dimension of [n_images, row, col, channel] (default).
    others : args
        See ``tl.prepro.flip_axis``.

    Returns
    -------
    numpy.array
        A list of processed images.

    """
    if arg_2:
        arg_3 = np.random.uniform(-1, 1)
        if arg_3 > 0:
            # x = np.asarray(x).swapaxes(axis, 0)
            # x = x[::-1, ...]
            # x = x.swapaxes(0, axis)
            # return x
            arg_4 = []
            for arg_5 in arg_0:
                arg_5 = np.asarray(arg_5).swapaxes(arg_1, 0)
                arg_5 = arg_5[::-1, ...]
                arg_5 = arg_5.swapaxes(0, arg_1)
                arg_4.append(arg_5)
            return np.asarray(arg_4)
        else:
            return np.asarray(arg_0)
    else:
        # x = np.asarray(x).swapaxes(axis, 0)
        # x = x[::-1, ...]
        # x = x.swapaxes(0, axis)
        # return x
        arg_4 = []
        for arg_5 in arg_0:
            arg_5 = np.asarray(arg_5).swapaxes(arg_1, 0)
            arg_5 = arg_5[::-1, ...]
            arg_5 = arg_5.swapaxes(0, arg_1)
            arg_4.append(arg_5)
        return np.asarray(arg_4)


def Func(
        arg_0, arg_1=0.1, arg_2=0.1, arg_3=False, arg_4=0, arg_5=1, arg_6=2, arg_7='nearest', arg_8=0.,
        arg_9=1
):
    """Shift an image randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    wrg : float
        Percentage of Func in axis x, usually -0.25 ~ 0.25.
    hrg : float
        Percentage of Func in axis y, usually -0.25 ~ 0.25.
    is_random : boolean
        If True, randomly Func. Default is False.
    row_index col_index and channel_index : int
        Index of row, col and channel, default (0, 1, 2), for theano (1, 2, 0).
    fill_mode : str
        Method to fill missing pixel, default `nearest`, more options `constant`, `reflect` or `wrap`, see `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__
    cval : float
        Value used for points outside the boundaries of the input if mode='constant'. Default is 0.0.
    order : int
        The order of interpolation. The order has to be in the range 0-5. See ``tl.prepro.affine_transform`` and `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__

    Returns
    -------
    numpy.array
        A processed image.

    """
    arg_10, arg_11 = arg_0.shape[arg_4], arg_0.shape[arg_5]
    if arg_3:
        arg_12 = np.random.uniform(-arg_2, arg_2) * arg_10
        arg_13 = np.random.uniform(-arg_1, arg_1) * arg_11
    else:
        arg_12, arg_13 = arg_2 * arg_10, arg_1 * arg_11
    arg_14 = np.array([[1, 0, arg_12], [0, 1, arg_13], [0, 0, 1]])

    arg_15 = arg_14  # no need to do offset
    arg_0 = affine_transform(arg_0, arg_15, arg_6, arg_7, arg_8, arg_9)
    return arg_0


def Func(arg_0, arg_1=1, arg_2=1, arg_3=False):
    """Change the Func of a single image, randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    gamma : float
        Non negative real number. Default value is 1.
            - Small than 1 means brighter.
            - If `is_random` is True, gamma in a range of (1-gamma, 1+gamma).
    gain : float
        The constant multiplier. Default value is 1.
    is_random : boolean
        If True, randomly change Func. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    References
    -----------
    - `skimage.exposure.adjust_gamma <http://scikit-image.org/docs/dev/api/skimage.exposure.html>`__
    - `chinese blog <http://www.cnblogs.com/denny402/p/5124402.html>`__

    """
    if arg_3:
        arg_1 = np.random.uniform(1 - arg_1, 1 + arg_1)
    arg_0 = exposure.adjust_gamma(arg_0, arg_1, arg_2)
    return arg_0


def Func(arg_0, arg_1=1., arg_2=1., arg_3=1., arg_4=False):
    """Perform Func augmentation for a single image, randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    gamma : float
        Change brightness (the same with ``tl.prepro.brightness``)
            - if is_random=False, one float number, small than one means brighter, greater than one means darker.
            - if is_random=True, tuple of two float numbers, (min, max).
    contrast : float
        Change contrast.
            - if is_random=False, one float number, small than one means blur.
            - if is_random=True, tuple of two float numbers, (min, max).
    saturation : float
        Change saturation.
            - if is_random=False, one float number, small than one means unsaturation.
            - if is_random=True, tuple of two float numbers, (min, max).
    is_random : boolean
        If True, randomly change Func. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ---------
    Random

    >>> x = tl.prepro.Func(x, gamma=(0.5, 5.0), contrast=(0.3, 1.0), saturation=(0.7, 1.0), is_random=True)

    Non-random

    >>> x = tl.prepro.Func(x, 0.5, 0.6, 0.8, is_random=False)

    """
    if arg_4:
        if not (len(arg_1) == len(arg_2) == len(arg_3) == 2):
            raise AssertionError("if is_random = True, the arguments are (min, max)")

        ## random change brightness  # small --> brighter
        arg_5 = np.random.randint(0, 3)  # 0-brighter, 1-darker, 2 keep normal

        if arg_5 == 0:  # brighter
            arg_1 = np.random.uniform(arg_1[0], 1.0)  # (.5, 1.0)
        elif arg_5 == 1:  # darker
            arg_1 = np.random.uniform(1.0, arg_1[1])  # (1.0, 5.0)
        else:
            arg_1 = 1
        arg_6 = brightness(arg_0, arg_1=arg_1, gain=1, arg_4=False)

        # tl.logging.info("using contrast and saturation")
        arg_7 = PIL.Image.fromarray(arg_6)  # array -> PIL
        arg_8 = PIL.ImageEnhance.Contrast(arg_7)
        arg_7 = arg_8.enhance(np.random.uniform(arg_2[0], arg_2[1]))  #0.3,0.9))

        arg_9 = PIL.ImageEnhance.Color(arg_7)
        arg_7 = arg_9.enhance(np.random.uniform(arg_3[0], arg_3[1]))  # (0.7,1.0))
        arg_6 = np.array(arg_7)  # PIL -> array
    else:
        arg_6 = brightness(arg_0, arg_1=arg_1, gain=1, arg_4=False)
        arg_7 = PIL.Image.fromarray(arg_6)  # array -> PIL
        arg_8 = PIL.ImageEnhance.Contrast(arg_7)
        arg_7 = arg_8.enhance(arg_2)

        arg_9 = PIL.ImageEnhance.Color(arg_7)
        arg_7 = arg_9.enhance(arg_3)
        arg_6 = np.array(arg_7)  # PIL -> array
    return np.asarray(arg_6)


def Func(arg_0, arg_1=0.66, arg_2=True, arg_3=True, arg_4=False):
    """Adjust hue of an RGB image.

    This is a convenience method that converts an RGB image to float representation, converts it to HSV, add an offset to the hue channel, converts back to RGB and then back to the original data type.
    For TF, see `tf.image.Func <https://www.tensorflow.org/api_docs/python/tf/image/Func>`__.and `tf.image.random_hue <https://www.tensorflow.org/api_docs/python/tf/image/random_hue>`__.

    Parameters
    -----------
    im : numpy.array
        An image with values between 0 and 255.
    hout : float
        The scale value for adjusting hue.
            - If is_offset is False, set all hue values to this value. 0 is red; 0.33 is green; 0.66 is blue.
            - If is_offset is True, add this value as the offset to the hue channel.
    is_offset : boolean
        Whether `hout` is added on HSV as offset or not. Default is True.
    is_clip : boolean
        If HSV value smaller than 0, set to 0. Default is True.
    is_random : boolean
        If True, randomly change hue. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ---------
    Random, add a random value between -0.2 and 0.2 as the offset to every hue values.

    >>> im_hue = tl.prepro.Func(image, hout=0.2, is_offset=True, is_random=False)

    Non-random, make all hue to green.

    >>> im_green = tl.prepro.Func(image, hout=0.66, is_offset=False, is_random=False)

    References
    -----------
    - `tf.image.random_hue <https://www.tensorflow.org/api_docs/python/tf/image/random_hue>`__.
    - `tf.image.Func <https://www.tensorflow.org/api_docs/python/tf/image/Func>`__.
    - `StackOverflow: Changing image hue with python PIL <https://stackoverflow.com/questions/7274221/changing-image-hue-with-python-pil>`__.

    """
    arg_5 = rgb_to_hsv(arg_0)
    if arg_4:
        arg_1 = np.random.uniform(-arg_1, arg_1)

    if arg_2:
        arg_5[..., 0] += arg_1
    else:
        arg_5[..., 0] = arg_1

    if arg_3:
        arg_5[..., 0] = np.clip(arg_5[..., 0], 0, np.inf)  # Hao : can remove green dots

    arg_6 = hsv_to_rgb(arg_5)
    return arg_6


def Func(arg_0, arg_1=None, arg_2='bicubic', arg_3=None):
    """Resize an image by given output size and method.

    Warning, this function will rescale the value to [0, 255].

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    size : list of 2 int or None
        For height and width.
    interp : str
        Interpolation method for re-sizing (`nearest`, `lanczos`, `bilinear`, `bicubic` (default) or `cubic`).
    mode : str
        The PIL image mode (`P`, `L`, etc.) to convert image before resizing.

    Returns
    -------
    numpy.array
        A processed image.

    References
    ------------
    - `scipy.misc.Func <https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.Func.html>`__

    """
    if arg_1 is None:
        arg_1 = [100, 100]

    if arg_0.shape[-1] == 1:
        # greyscale
        arg_0 = scipy.misc.Func(arg_0[:, :, 0], arg_1, arg_2=arg_2, arg_3=arg_3)
        return arg_0[:, :, np.newaxis]
    else:
        # rgb, bgr, rgba
        return scipy.misc.Func(arg_0, arg_1, arg_2=arg_2, arg_3=arg_3)


def Func(arg_0, arg_1=None, arg_2=None, arg_3=1e-7):
    """Normalize every pixels by the same given mean and std, which are usually
    compute from all examples.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    mean : float
        Value for subtraction.
    std : float
        Value for division.
    epsilon : float
        A small position value for dividing standard deviation.

    Returns
    -------
    numpy.array
        A processed image.

    """
    if arg_1:
        arg_0 = arg_0 - arg_1
    if arg_2:
        arg_0 = arg_0 / (arg_2 + arg_3)
    return arg_0


def Func(arg_0, arg_1):
    """Apply ZCA whitening on an image by given principal components matrix.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    principal_components : matrix
        Matrix from ``get_Func_principal_components_img``.

    Returns
    -------
    numpy.array
        A processed image.

    """
    arg_2 = np.reshape(arg_0, (arg_0.size))
    # tl.logging.info(principal_components.shape, x.shape)  # ((28160, 28160), (160, 176, 1))
    # flatx = np.reshape(x, (x.shape))
    # flatx = np.reshape(x, (x.shape[0], ))
    # tl.logging.info(flatx.shape)  # (160, 176, 1)
    arg_3 = np.dot(arg_2, arg_1)
    arg_0 = np.reshape(arg_3, (arg_0.shape[0], arg_0.shape[1], arg_0.shape[2]))
    return arg_0


def Func(arg_0, arg_1=0.5):
    """Randomly set some pixels to zero by a given keeping probability.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] or [row, col].
    keep : float
        The keeping probability (0, 1), the lower more values will be set to zero.

    Returns
    -------
    numpy.array
        A processed image.

    """
    if len(arg_0.shape) == 3:
        if arg_0.shape[-1] == 3:  # color
            arg_2 = arg_0.shape
            arg_3 = np.random.binomial(n=1, p=arg_1, size=arg_0.shape[:-1])
            for arg_4 in range(3):
                arg_0[:, :, arg_4] = np.multiply(arg_0[:, :, arg_4], arg_3)
        elif arg_0.shape[-1] == 1:  # greyscale image
            arg_2 = arg_0.shape
            arg_0 = np.multiply(arg_0, np.random.binomial(n=1, p=arg_1, size=arg_2))
        else:
            raise Exception("Unsupported shape {}".format(arg_0.shape))
    elif len(arg_0.shape) == 2 or 1:  # greyscale matrix (image) or vector
        arg_2 = arg_0.shape
        arg_0 = np.multiply(arg_0, np.random.binomial(n=1, p=arg_1, size=arg_2))
    else:
        raise Exception("Unsupported shape {}".format(arg_0.shape))
    return arg_0


def Func(arg_0=None, arg_1=(100, 100), arg_2=1):
    """Inputs a list of points, return a 2D image.

    Parameters
    --------------
    list_points : list of 2 int
        [[x, y], [x, y]..] for point coordinates.
    size : tuple of 2 int
        (w, h) for output size.
    val : float or int
        For the contour value.

    Returns
    -------
    numpy.array
        An image.

    """
    if arg_0 is None:
        raise Exception("list_points : list of 2 int")
    arg_3 = arg_7.zeros(arg_1)
    if len(arg_0) == 0:
        return arg_3
    for arg_4 in arg_0:
        for arg_5 in arg_4:
            # tl.logging.info(x)
            arg_3[arg_6(arg_7.round(arg_5[0]))][arg_6(arg_7.round(arg_5[1]))] = arg_2
    return arg_3


def Func(arg_0):
    """Parse darknet annotation format into two lists for class and bounding box.

    Input list of [[class, x, y, w, h], ...], return two list of [class ...] and [[x, y, w, h], ...].

    Parameters
    ------------
    annotations : list of list
        A list of class and bounding boxes of images e.g. [[class, x, y, w, h], ...]

    Returns
    -------
    list of int
        List of class labels.

    list of list of 4 numbers
        List of bounding box.

    """
    arg_1 = []
    arg_2 = []
    for arg_3 in arg_0:
        arg_1.append(arg_3[0])
        arg_2.append(arg_3[1:])
    return arg_1, arg_2


def Func(arg_0, arg_1=None, arg_2=None, arg_3='bicubic', arg_4=None, arg_5=False):
    """Resize an image, and compute the new bounding box coordinates.

    Parameters
    -------------
    im : numpy.array
        An image with dimension of [row, col, channel] (default).
    coords : list of list of 4 int/float or None
        Coordinates [[x, y, w, h], [x, y, w, h], ...]
    size interp and mode : args
        See ``tl.prepro.imresize``.
    is_rescale : boolean
        Set to True, if the input coordinates are rescaled to [0, 1], then return the original coordinates. Default is False.

    Returns
    -------
    numpy.array
        A processed image
    list of list of 4 numbers
        A list of new bounding boxes.

    Examples
    --------
    >>> im = np.zeros([80, 100, 3])    # as an image with shape width=100, height=80
    >>> _, coords = Func(im, coords=[[20, 40, 30, 30], [10, 20, 20, 20]], size=[160, 200], is_rescale=False)
    >>> print(coords)
      [[40, 80, 60, 60], [20, 40, 40, 40]]
    >>> _, coords = Func(im, coords=[[20, 40, 30, 30]], size=[40, 100], is_rescale=False)
    >>> print(coords)
      [[20, 20, 30, 15]]
    >>> _, coords = Func(im, coords=[[20, 40, 30, 30]], size=[60, 150], is_rescale=False)
    >>> print(coords)
      [[30, 30, 45, 22]]
    >>> im2, coords = Func(im, coords=[[0.2, 0.4, 0.3, 0.3]], size=[160, 200], is_rescale=True)
    >>> print(coords, im2.shape)
      [[0.2, 0.4, 0.3, 0.3]] (160, 200, 3)

    """
    if arg_1 is None:
        arg_1 = []
    if arg_2 is None:
        arg_2 = [100, 100]

    arg_6, arg_7 = arg_0.shape[0:2]
    arg_6 = arg_6 * 1.0  # * 1.0 for python2 : force division to be float point
    arg_7 = arg_7 * 1.0
    arg_0 = imresize(arg_0, arg_2=arg_2, arg_3=arg_3, arg_4=arg_4)

    if arg_5 is False:
        arg_8 = list()

        for arg_9 in arg_1:

            if len(arg_9) != 4:
                raise AssertionError("coordinate should be 4 values : [x, y, w, h]")

            # x' = x * (imw'/imw)
            arg_10 = int(arg_9[0] * (arg_2[1] / arg_7))
            # y' = y * (imh'/imh)
            # tl.logging.info('>>', coord[1], size[0], imh)
            arg_11 = int(arg_9[1] * (arg_2[0] / arg_6))
            # w' = w * (imw'/imw)
            arg_12 = int(arg_9[2] * (arg_2[1] / arg_7))
            # h' = h * (imh'/imh)
            arg_13 = int(arg_9[3] * (arg_2[0] / arg_6))
            arg_8.append([arg_10, arg_11, arg_12, arg_13])
        return arg_0, arg_8
    else:
        return arg_0, arg_1


def Func(arg_0, arg_1=0):
    """Return mask for sequences.

    Parameters
    -----------
    sequences : list of list of int
        All sequences where each row is a sequence.
    pad_val : int
        The pad value.

    Returns
    ----------
    list of list of int
        The mask.

    Examples
    ---------
    >>> sentences_ids = [[4, 0, 5, 3, 0, 0],
    ...                  [5, 3, 9, 4, 9, 0]]
    >>> mask = Func(sentences_ids, pad_val=0)
    [[1 1 1 1 0 0]
     [1 1 1 1 1 0]]

    """
    arg_2 = np.ones_like(arg_0)
    for arg_3, arg_4 in enumerate(arg_0):
        for arg_5 in reversed(range(len(arg_4))):
            if arg_4[arg_5] == arg_1:
                arg_2[arg_3, arg_5] = 0
            else:
                break  # <-- exit the for loop, prepcess next sequence
    return arg_2


def Func(
        arg_0, arg_1, arg_2=None, arg_3=0.5, arg_4=(0, 1, 5, 6, 7, 2, 3, 4, 11, 12, 13, 8, 9, 10, 15, 14, 17, 16, 18)
):
    """Flip an image and corresponding keypoints.

    Parameters
    -----------
    image : 3 channel image
        The given image for augmentation.
    annos : list of list of floats
        The keypoints annotation of people.
    mask : single channel image or None
        The mask if available.
    prob : float, 0 to 1
        The probability to flip the image, if 1, always flip the image.
    flip_list : tuple of int
        Denotes how the keypoints number be changed after flipping which is required for pose estimation task.
        The left and right body should be maintained rather than switch.
        (Default COCO format).
        Set to an empty tuple if you don't need to maintain left and right information.

    Returns
    ----------
    preprocessed image, annos, mask

    """

    arg_5 = np.random.uniform(0, 1.0)
    if arg_5 < arg_3:
        return arg_0, arg_1, arg_2

    arg_6, arg_7, arg_6 = np.shape(arg_0)
    arg_0 = cv2.flip(arg_0, 1)
    arg_2 = cv2.flip(arg_2, 1)
    arg_8 = []
    for arg_9 in arg_1:  # TODO : speed up with affine transform
        arg_10 = []
        for arg_11 in arg_4:
            arg_12 = arg_9[arg_11]
            if arg_12[0] < 0 or arg_12[1] < 0:
                arg_10.append((-1000, -1000))
                continue
            if arg_12[0] > arg_0.shape[1] - 1 or arg_12[1] > arg_0.shape[0] - 1:
                arg_10.append((-1000, -1000))
                continue
            if (arg_7 - arg_12[0]) > arg_0.shape[1] - 1:
                arg_10.append((-1000, -1000))
                continue
            arg_10.append((arg_7 - arg_12[0], arg_12[1]))
        arg_8.append(arg_10)
    arg_1 = arg_8

    return arg_0, arg_1, arg_2


def Func(arg_0=None, arg_1=0.99, arg_2=0):
    """Take 1D float array of rewards and compute discounted rewards for an
    episode. When encount a non-zero value, consider as the end a of an episode.

    Parameters
    ----------
    rewards : list
        List of rewards
    gamma : float
        Discounted factor
    mode : int
        Mode for computing the discount rewards.
            - If mode == 0, reset the discount process when encount a non-zero reward (Ping-pong game).
            - If mode == 1, would not reset the discount process.

    Returns
    --------
    list of float
        The discounted rewards.

    Examples
    ----------
    >>> rewards = np.asarray([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1])
    >>> gamma = 0.9
    >>> discount_rewards = tl.rein.Func(rewards, gamma)
    >>> print(discount_rewards)
    [ 0.72899997  0.81        0.89999998  1.          0.72899997  0.81
    0.89999998  1.          0.72899997  0.81        0.89999998  1.        ]
    >>> discount_rewards = tl.rein.Func(rewards, gamma, mode=1)
    >>> print(discount_rewards)
    [ 1.52110755  1.69011939  1.87791049  2.08656716  1.20729685  1.34144104
    1.49048996  1.65610003  0.72899997  0.81        0.89999998  1.        ]

    """
    if arg_0 is None:
        raise Exception("rewards should be a list")
    arg_3 = np.zeros_like(arg_0, dtype=np.float32)
    arg_4 = 0
    for arg_5 in reversed(xrange(0, arg_0.size)):
        if arg_2 == 0:
            if arg_0[arg_5] != 0: arg_4 = 0

        arg_4 = arg_4 * arg_1 + arg_0[arg_5]
        arg_3[arg_5] = arg_4
    return arg_3


def Func(arg_0, arg_1, arg_2, arg_3=None):
    """Calculate the loss for Policy Gradient Network.

    Parameters
    ----------
    logits : tensor
        The network outputs without softmax. This function implements softmax inside.
    actions : tensor or placeholder
        The agent actions.
    rewards : tensor or placeholder
        The rewards.

    Returns
    --------
    Tensor
        The TensorFlow loss function.

    Examples
    ----------
    >>> states_batch_pl = tf.placeholder(tf.float32, shape=[None, D])
    >>> network = InputLayer(states_batch_pl, name='input')
    >>> network = DenseLayer(network, n_units=H, act=tf.nn.relu, name='relu1')
    >>> network = DenseLayer(network, n_units=3, name='out')
    >>> probs = network.outputs
    >>> sampling_prob = tf.nn.softmax(probs)
    >>> actions_batch_pl = tf.placeholder(tf.int32, shape=[None])
    >>> discount_rewards_batch_pl = tf.placeholder(tf.float32, shape=[None])
    >>> loss = tl.rein.Func(probs, actions_batch_pl, discount_rewards_batch_pl)
    >>> train_op = tf.train.RMSPropOptimizer(learning_rate, decay_rate).minimize(loss)

    """
    arg_4 = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=arg_1, arg_0=arg_0, arg_3=arg_3)

    return tf.reduce_sum(tf.multiply(arg_4, arg_2))


def Func(arg_0, arg_1, arg_2='Func'):
    """Log weight.

    Parameters
    -----------
    probs : tensor
        If it is a network output, usually we should scale it to [0, 1] via softmax.
    weights : tensor
        The weights.

    Returns
    --------
    Tensor
        The Tensor after appling the log weighted expression.

    """
    with tf.variable_scope(arg_2):
        arg_3 = tf.reduce_mean(tf.log(arg_0) * arg_1)
        return arg_3


def Func(arg_0, arg_1, arg_2=None):
    """Softmax cross-entropy operation, returns the TensorFlow expression of cross-entropy for two distributions,
    it implements softmax internally. See ``tf.nn.sparse_softmax_Func_with_logits``.

    Parameters
    ----------
    output : Tensor
        A batch of distribution with shape: [batch_size, num of classes].
    target : Tensor
        A batch of index with shape: [batch_size, ].
    name : string
        Name of this loss.

    Examples
    --------
    >>> ce = tl.cost.Func(y_logits, y_target_logits, 'my_loss')

    References
    -----------
    - About cross-entropy: `<https://en.wikipedia.org/wiki/Cross_entropy>`__.
    - The code is borrowed from: `<https://en.wikipedia.org/wiki/Cross_entropy>`__.

    """
    if arg_2 is None:
        raise Exception("Please give a unique name to tl.cost.Func for TF1.0+")
    return tf.reduce_mean(tf.nn.sparse_softmax_Func_with_logits(labels=arg_1, logits=arg_0), arg_2=arg_2)


def Func(arg_0, arg_1, arg_2=None):
    """Sigmoid cross-entropy operation, see ``tf.nn.Func_with_logits``.

    Parameters
    ----------
    output : Tensor
        A batch of distribution with shape: [batch_size, num of classes].
    target : Tensor
        A batch of index with shape: [batch_size, ].
    name : string
        Name of this loss.

    """
    return tf.reduce_mean(tf.nn.Func_with_logits(labels=arg_1, logits=arg_0), arg_2=arg_2)


def Func(arg_0, arg_1, arg_2=1e-8, arg_3='bce_loss'):
    """Binary cross entropy operation.

    Parameters
    ----------
    output : Tensor
        Tensor with type of `float32` or `float64`.
    target : Tensor
        The target distribution, format the same with `output`.
    epsilon : float
        A small value to avoid output to be zero.
    name : str
        An optional name to attach to this function.

    References
    -----------
    - `ericjang-DRAW <https://github.com/ericjang/draw/blob/master/draw.py#L73>`__

    """
    #     with ops.op_scope([output, target], name, "bce_loss") as name:
    #         output = ops.convert_to_tensor(output, name="preds")
    #         target = ops.convert_to_tensor(targets, name="target")

    # with tf.name_scope(name):
    return tf.reduce_mean(
        tf.reduce_sum(-(arg_1 * tf.log(arg_0 + arg_2) + (1. - arg_1) * tf.log(1. - arg_0 + arg_2)), axis=1),
        arg_3=arg_3
    )


def Func(arg_0, arg_1, arg_2="normalized_mean_squared_error_loss"):
    """Return the TensorFlow expression of normalized mean-square-error of two distributions.

    Parameters
    ----------
    output : Tensor
        2D, 3D or 4D tensor i.e. [batch_size, n_feature], [batch_size, height, width] or [batch_size, height, width, channel].
    target : Tensor
        The target distribution, format the same with `output`.
    name : str
        An optional name to attach to this function.

    """
    # with tf.name_scope("normalized_mean_squared_error_loss"):
    if arg_0.get_shape().ndims == 2:  # [batch_size, n_feature]
        arg_3 = tf.sqrt(tf.reduce_sum(tf.squared_difference(arg_0, arg_1), axis=1))
        arg_4 = tf.sqrt(tf.reduce_sum(tf.square(arg_1), axis=1))
    elif arg_0.get_shape().ndims == 3:  # [batch_size, w, h]
        arg_3 = tf.sqrt(tf.reduce_sum(tf.squared_difference(arg_0, arg_1), axis=[1, 2]))
        arg_4 = tf.sqrt(tf.reduce_sum(tf.square(arg_1), axis=[1, 2]))
    elif arg_0.get_shape().ndims == 4:  # [batch_size, w, h, c]
        arg_3 = tf.sqrt(tf.reduce_sum(tf.squared_difference(arg_0, arg_1), axis=[1, 2, 3]))
        arg_4 = tf.sqrt(tf.reduce_sum(tf.square(arg_1), axis=[1, 2, 3]))
    arg_5 = tf.reduce_mean(arg_3 / arg_4, arg_2=arg_2)
    return arg_5


def Func(arg_0, arg_1, arg_2, arg_3=False, arg_4=None):
    """Returns the expression of cross-entropy of two sequences, implement
    softmax internally. Normally be used for Dynamic RNN with Synced sequence input and output.

    Parameters
    -----------
    logits : Tensor
        2D tensor with shape of [batch_size * ?, n_classes], `?` means dynamic IDs for each example.
        - Can be get from `DynamicRNNLayer` by setting ``return_seq_2d`` to `True`.
    target_seqs : Tensor
        int of tensor, like word ID. [batch_size, ?], `?` means dynamic IDs for each example.
    input_mask : Tensor
        The mask to compute loss, it has the same size with `target_seqs`, normally 0 or 1.
    return_details : boolean
        Whether to return detailed losses.
            - If False (default), only returns the loss.
            - If True, returns the loss, losses, weights and targets (see source code).

    Examples
    --------
    >>> batch_size = 64
    >>> vocab_size = 10000
    >>> embedding_size = 256
    >>> input_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="input")
    >>> target_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="target")
    >>> input_mask = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="mask")
    >>> net = tl.layers.EmbeddingInputlayer(
    ...         inputs = input_seqs,
    ...         vocabulary_size = vocab_size,
    ...         embedding_size = embedding_size,
    ...         name = 'seq_embedding')
    >>> net = tl.layers.DynamicRNNLayer(net,
    ...         cell_fn = tf.contrib.rnn.BasicLSTMCell,
    ...         n_hidden = embedding_size,
    ...         dropout = (0.7 if is_train else None),
    ...         sequence_length = tl.layers.retrieve_seq_length_op2(input_seqs),
    ...         return_seq_2d = True,
    ...         name = 'dynamicrnn')
    >>> print(net.outputs)
    (?, 256)
    >>> net = tl.layers.DenseLayer(net, n_units=vocab_size, name="output")
    >>> print(net.outputs)
    (?, 10000)
    >>> loss = tl.cost.Func(net.outputs, target_seqs, input_mask)

    """
    arg_5 = tf.reshape(arg_1, [-1])  # to one vector
    arg_6 = tf.to_float(tf.reshape(arg_2, [-1]))  # to one vector like targets
    arg_7 = tf.nn.sparse_softmax_cross_entropy_with_logits(arg_0=arg_0, labels=arg_5, arg_4=arg_4) * arg_6
    # losses = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=targets, name=name)) # for TF1.0 and others

    arg_8 = tf.divide(
        tf.reduce_sum(arg_7),  # loss from mask. reduce_sum before element-wise mul with mask !!
        tf.reduce_sum(arg_6),
        arg_4="seq_loss_with_mask"
    )

    if arg_3:
        return arg_8, arg_7, arg_6, arg_5
    else:
        return arg_8


def Func(arg_0=1.0):
    """Max-norm regularization returns a function that can be used to apply max-norm regularization to weights.

    More about max-norm, see `wiki-max norm <https://en.wikipedia.org/wiki/Matrix_norm#Max_norm>`_.
    The implementation follows `TensorFlow contrib <https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/layers/regularizers.py>`__.

    Parameters
    ----------
    scale : float
        A scalar multiplier `Tensor`. 0.0 disables the regularizer.

    Returns
    ---------
    A function with signature `mn(weights, name=None)` that apply Lo regularization.

    Raises
    --------
    ValueError : If scale is outside of the range [0.0, 1.0] or if scale is not a float.

    """
    if isinstance(arg_0, numbers.Integral):
        raise ValueError('scale cannot be an integer: %s' % arg_0)

    if isinstance(arg_0, numbers.Real):
        if arg_0 < 0.:
            raise ValueError('Setting a scale less than 0 on a regularizer: %g' % arg_0)
        # if scale >= 1.:
        #   raise ValueError('Setting a scale greater than 1 on a regularizer: %g' %
        #                    scale)
        if arg_0 == 0.:
            tl.logging.info('Scale of 0 disables regularizer.')
            return lambda _, arg_1=None: None

    def mn(arg_2, arg_1='max_regularizer'):
        """Applies max-norm regularization to weights."""
        with tf.name_scope(arg_1) as scope:
            arg_3 = ops.convert_to_tensor(arg_0, dtype=arg_2.dtype.base_dtype, arg_1='scale')
            #   if tf.__version__ <= '0.12':
            #       standard_ops_fn = standard_ops.mul
            #   else:
            arg_4 = standard_ops.multiply
            return arg_4(arg_3, standard_ops.reduce_max(standard_ops.abs(arg_2)), arg_1=scope)

    return mn


def Func(arg_0, arg_1=0, arg_2=1, arg_3=None):
    """Ramp activation function.

    Parameters
    ----------
    x : Tensor
        input.
    v_min : float
        cap input to v_min as a lower bound.
    v_max : float
        cap input to v_max as a upper bound.
    name : str
        The function name (optional).

    Returns
    -------
    Tensor
        A ``Tensor`` in the same type as ``x``.

    """
    return tf.clip_by_value(arg_0, clip_value_min=arg_1, clip_value_max=arg_2, arg_3=arg_3)


def Func(arg_0, arg_1='Func'):
    """Return the softmax outputs of images, every pixels have multiple label, the sum of a pixel is 1.

    Usually be used for image segmentation.

    Parameters
    ----------
    x : Tensor
        input.
            - For 2d image, 4D tensor (batch_size, height, weight, channel), where channel >= 2.
            - For 3d image, 5D tensor (batch_size, depth, height, weight, channel), where channel >= 2.
    name : str
        function name (optional)

    Returns
    -------
    Tensor
        A ``Tensor`` in the same type as ``x``.

    Examples
    --------
    >>> outputs = Func(network.outputs)
    >>> dice_loss = 1 - dice_coe(outputs, y_, epsilon=1e-5)

    References
    ----------
    - `tf.reverse <https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html#reverse>`__

    """
    with tf.name_scope(arg_1):
        return tf.nn.softmax(arg_0)


def Func(arg_0, arg_1, arg_2):
        """Tensorflow version of np.repeat for 1D"""
        # https://github.com/tensorflow/tensorflow/issues/8521

        if len(arg_1.get_shape()) != 1:
            raise AssertionError("This is not a 1D Tensor")

        arg_1 = tf.expand_dims(arg_1, -1)
        arg_1 = tf.tile(arg_1, [1, arg_2])
        arg_1 = arg_0.tf_flatten(arg_1)
        return arg_1


def Func(arg_0, arg_1, arg_2):
        """Batch version of tf_map_coordinates

        Only supports 2D feature maps

        Parameters
        ----------
        inputs : ``tf.Tensor``
            shape = (b*c, h, w)
        coords : ``tf.Tensor``
            shape = (b*c, h, w, n, 2)

        Returns
        -------
        ``tf.Tensor``
            A Tensor with the shape as (b*c, h, w, n)

        """
        arg_3 = arg_1.get_shape()
        arg_4 = arg_2.get_shape()
        arg_5 = tf.shape(arg_1)[0]
        arg_6 = int(arg_3[1])
        arg_7 = int(arg_3[2])
        arg_8 = int(arg_4[3])
        arg_9 = arg_6 * arg_7 * arg_8

        arg_10 = tf.cast(tf.floor(arg_2), 'int32')
        arg_11 = tf.cast(tf.ceil(arg_2), 'int32')
        arg_12 = tf.stack([arg_10[:, :, :, :, 0], arg_11[:, :, :, :, 1]], axis=-1)
        arg_13 = tf.stack([arg_11[:, :, :, :, 0], arg_10[:, :, :, :, 1]], axis=-1)

        arg_14 = arg_0._tf_repeat(tf.range(arg_5), arg_9)

        arg_15 = arg_0._get_vals_by_coords(arg_1, arg_10, arg_14, (arg_5, arg_6, arg_7, arg_8))
        arg_16 = arg_0._get_vals_by_coords(arg_1, arg_11, arg_14, (arg_5, arg_6, arg_7, arg_8))
        arg_17 = arg_0._get_vals_by_coords(arg_1, arg_12, arg_14, (arg_5, arg_6, arg_7, arg_8))
        arg_18 = arg_0._get_vals_by_coords(arg_1, arg_13, arg_14, (arg_5, arg_6, arg_7, arg_8))

        arg_19 = arg_2 - tf.cast(arg_10, 'float32')

        arg_20 = arg_15 + (arg_18 - arg_15) * arg_19[:, :, :, :, 0]
        arg_21 = arg_17 + (arg_16 - arg_17) * arg_19[:, :, :, :, 0]
        arg_22 = arg_20 + (arg_21 - arg_20) * arg_19[:, :, :, :, 1]

        return arg_22


def Func(arg_0, arg_1, arg_2, arg_3):
        """Batch map offsets into input

        Parameters
        ------------
        inputs : ``tf.Tensor``
            shape = (b, h, w, c)
        offsets: ``tf.Tensor``
            shape = (b, h, w, 2*n)
        grid_offset: `tf.Tensor``
            Offset grids shape = (h, w, n, 2)

        Returns
        -------
        ``tf.Tensor``
            A Tensor with the shape as (b, h, w, c)

        """
        arg_4 = arg_1.get_shape()
        arg_5 = tf.shape(arg_1)[0]
        arg_6 = int(int(arg_2.get_shape()[3]) / 2)
        arg_7 = arg_4[1]
        arg_8 = arg_4[2]
        arg_9 = arg_4[3]

        # inputs (b, h, w, c) --> (b*c, h, w)
        arg_1 = arg_0._to_bc_h_w(arg_1, arg_4)

        # offsets (b, h, w, 2*n) --> (b, h, w, n, 2)
        arg_2 = tf.reshape(arg_2, (arg_5, arg_7, arg_8, arg_6, 2))
        # offsets (b, h, w, n, 2) --> (b*c, h, w, n, 2)
        # offsets = tf.tile(offsets, [channel, 1, 1, 1, 1])

        arg_10 = tf.expand_dims(arg_3, 0)  # grid_offset --> (1, h, w, n, 2)
        arg_10 = tf.tile(arg_10, [arg_5, 1, 1, 1, 1]) + arg_2  # grid_offset --> (b, h, w, n, 2)

        # clip out of bound
        arg_10 = tf.stack(
            [
                tf.clip_by_value(arg_10[:, :, :, :, 0], 0.0, tf.cast(arg_7 - 1, 'float32')),
                tf.clip_by_value(arg_10[:, :, :, :, 1], 0.0, tf.cast(arg_8 - 1, 'float32'))
            ], axis=-1
        )
        arg_10 = tf.tile(arg_10, [arg_9, 1, 1, 1, 1])

        arg_11 = arg_0._tf_batch_map_coordinates(arg_1, arg_10)
        # (b*c, h, w, n) --> (b, h, w, n, c)
        arg_11 = arg_0._to_b_h_w_n_c(arg_11, [arg_5, arg_7, arg_8, arg_6, arg_9])

        return arg_11


def Func(arg_0=None, arg_1=None, arg_2=None, arg_3=False, arg_4=False):
    """Generate a generator that input a group of example in numpy.array and
    their labels, return the examples and labels by the given batch size.

    Parameters
    ----------
    inputs : numpy.array
        The input features, every row is a example.
    targets : numpy.array
        The labels of inputs, every row is a example.
    batch_size : int
        The batch size.
    allow_dynamic_batch_size: boolean
        Allow the use of the last data batch in case the number of examples is not a multiple of batch_size, this may result in unexpected behaviour if other functions expect a fixed-sized batch-size.
    shuffle : boolean
        Indicating whether to use a shuffling queue, shuffle the dataset before return.

    Examples
    --------
    >>> X = np.asarray([['a','a'], ['b','b'], ['c','c'], ['d','d'], ['e','e'], ['f','f']])
    >>> y = np.asarray([0,1,2,3,4,5])
    >>> for batch in tl.iterate.Func(inputs=X, targets=y, batch_size=2, shuffle=False):
    >>>     print(batch)
    (array([['a', 'a'], ['b', 'b']], dtype='<U1'), array([0, 1]))
    (array([['c', 'c'], ['d', 'd']], dtype='<U1'), array([2, 3]))
    (array([['e', 'e'], ['f', 'f']], dtype='<U1'), array([4, 5]))

    Notes
    -----
    If you have two inputs and one label and want to shuffle them together, e.g. X1 (1000, 100), X2 (1000, 80) and Y (1000, 1), you can stack them together (`np.hstack((X1, X2))`)
    into (1000, 180) and feed to ``inputs``. After getting a batch, you can split it back into X1 and X2.

    """
    if len(arg_0) != len(arg_1):
        raise AssertionError("The length of inputs and targets should be equal")

    if arg_4:
        arg_5 = np.arange(len(arg_0))
        np.random.shuffle(arg_5)

    # for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):
    # chulei: handling the case where the number of samples is not a multiple of batch_size, avoiding wasting samples
    for arg_6 in range(0, len(arg_0), arg_2):
        arg_7 = arg_6 + arg_2
        if arg_7 > len(arg_0):
            if arg_3:
                arg_7 = len(arg_0)
            else:
                break
        if arg_4:
            arg_8 = arg_5[arg_6:arg_7]
        else:
            arg_8 = slice(arg_6, arg_7)
        if (isinstance(arg_0, list) or isinstance(arg_1, list)) and (arg_4 ==True):
            # zsdonghao: for list indexing when shuffle==True
            yield [arg_0[arg_9] for arg_9 in arg_8], [arg_1[arg_9] for arg_9 in arg_8]
        else:
            yield arg_0[arg_8], arg_1[arg_8]


def Func(arg_0, arg_1=None, arg_2='model', **arg_3):
        """Save model architecture and parameters into database, timestamp will be added automatically.

        Parameters
        ----------
        network : TensorLayer layer
            TensorLayer layer instance.
        model_name : str
            The name/key of model.
        kwargs : other events
            Other events, such as name, accuracy, loss, step number and etc (optinal).

        Examples
        ---------
        Save model architecture and parameters into database.
        >>> db.Func(net, accuracy=0.8, loss=2.3, name='second_model')

        Load one model with parameters from database (run this in other script)
        >>> net = db.find_top_model(sess=sess, accuracy=0.8, loss=2.3)

        Find and load the latest model.
        >>> net = db.find_top_model(sess=sess, sort=[("time", pymongo.DESCENDING)])
        >>> net = db.find_top_model(sess=sess, sort=[("time", -1)])

        Find and load the oldest model.
        >>> net = db.find_top_model(sess=sess, sort=[("time", pymongo.ASCENDING)])
        >>> net = db.find_top_model(sess=sess, sort=[("time", 1)])

        Get model information
        >>> net._accuracy
        ... 0.8

        Returns
        ---------
        boolean : True for success, False for fail.
        """
        arg_3.update({'model_name': arg_2})
        arg_0._fill_project_info(arg_3)  # put project_name into kwargs

        arg_4 = arg_1.get_all_params()

        arg_5 = time.time()

        arg_3.update({'architecture': arg_1.all_graphs, 'time': datetime.utcnow()})

        try:
            arg_6 = arg_0.model_fs.put(arg_0._serialization(arg_4))
            arg_3.update({'params_id': arg_6, 'time': datetime.utcnow()})
            arg_0.db.Model.insert_one(arg_3)
            print("[Database] Save model: SUCCESS, took: {}s".format(round(time.time() - arg_5, 2)))
            return True
        except Exception as e:
            arg_7, arg_8, arg_9 = sys.exc_info()
            arg_10 = os.path.split(arg_9.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(arg_7, arg_8, arg_10, arg_9.tb_lineno, e))
            print("[Database] Save model: FAIL")
            return False


def Func(arg_0, arg_1=None, arg_2=None, **arg_3):
        """Saves one dataset into database, timestamp will be added automatically.

        Parameters
        ----------
        dataset : any type
            The dataset you want to store.
        dataset_name : str
            The name of dataset.
        kwargs : other events
            Other events, such as description, author and etc (optinal).

        Examples
        ----------
        Save dataset
        >>> db.Func([X_train, y_train, X_test, y_test], 'mnist', description='this is a tutorial')

        Get dataset
        >>> dataset = db.find_top_dataset('mnist')

        Returns
        ---------
        boolean : Return True if save success, otherwise, return False.
        """
        arg_0._fill_project_info(arg_3)
        if arg_2 is None:
            raise Exception("dataset_name is None, please give a dataset name")
        arg_3.update({'dataset_name': arg_2})

        arg_4 = time.time()
        try:
            arg_5 = arg_0.dataset_fs.put(arg_0._serialization(arg_1))
            arg_3.update({'dataset_id': arg_5, 'time': datetime.utcnow()})
            arg_0.db.Dataset.insert_one(arg_3)
            # print("[Database] Save params: {} SUCCESS, took: {}s".format(file_name, round(time.time()-s, 2)))
            print("[Database] Save dataset: SUCCESS, took: {}s".format(round(time.time() - arg_4, 2)))
            return True
        except Exception as e:
            arg_6, arg_7, arg_8 = sys.exc_info()
            arg_9 = os.path.split(arg_8.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(arg_6, arg_7, arg_9, arg_8.tb_lineno, e))
            print("[Database] Save dataset: FAIL")
            return False


def Func(arg_0, arg_1=None, arg_2=None, **arg_3):
        """Finds and returns a dataset from the database which matches the requirement.

        Parameters
        ----------
        dataset_name : str
            The name of dataset.
        sort : List of tuple
            PyMongo sort comment, search "PyMongo find one sorting" and `collection level operations <http://api.mongodb.com/python/current/api/pymongo/collection.html>`__ for more details.
        kwargs : other events
            Other events, such as description, author and etc (optinal).

        Examples
        ---------
        Save dataset
        >>> db.save_dataset([X_train, y_train, X_test, y_test], 'mnist', description='this is a tutorial')

        Get dataset
        >>> dataset = db.Func('mnist')
        >>> datasets = db.find_datasets('mnist')

        Returns
        --------
        dataset : the dataset or False
            Return False if nothing found.

        """

        arg_0._fill_project_info(arg_3)
        if arg_1 is None:
            raise Exception("dataset_name is None, please give a dataset name")
        arg_3.update({'dataset_name': arg_1})

        arg_4 = time.time()

        arg_5 = arg_0.db.Dataset.find_one(filter=arg_3, arg_2=arg_2)

        if arg_5 is not None:
            arg_6 = arg_5['dataset_id']
        else:
            print("[Database] FAIL! Cannot find dataset: {}".format(arg_3))
            return False
        try:
            arg_7 = arg_0._deserialization(arg_0.dataset_fs.get(arg_6).read())
            arg_8 = arg_0.db.Dataset.find(arg_3)
            print("[Database] Find one dataset SUCCESS, {} took: {}s".format(arg_3, round(time.time() - arg_4, 2)))

            # check whether more datasets match the requirement
            arg_9 = arg_8.distinct('dataset_id')
            arg_10 = len(arg_9)
            if arg_10 != 1:
                print("     Note that there are {} datasets match the requirement".format(arg_10))
            return arg_7
        except Exception as e:
            arg_11, arg_12, arg_13 = sys.exc_info()
            arg_14 = os.path.split(arg_13.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(arg_11, arg_12, arg_14, arg_13.tb_lineno, e))
            return False


def Func(arg_0, arg_1=None, **arg_2):
        """Finds and returns all datasets from the database which matches the requirement.
        In some case, the data in a dataset can be stored separately for better management.

        Parameters
        ----------
        dataset_name : str
            The name/key of dataset.
        kwargs : other events
            Other events, such as description, author and etc (optional).

        Returns
        --------
        params : the parameters, return False if nothing found.

        """

        arg_0._fill_project_info(arg_2)
        if arg_1 is None:
            raise Exception("dataset_name is None, please give a dataset name")
        arg_2.update({'dataset_name': arg_1})

        arg_3 = time.time()
        arg_4 = arg_0.db.Dataset.find(arg_2)

        if arg_4 is not None:
            arg_5 = arg_4.distinct('dataset_id')
            arg_6 = []
            for arg_7 in arg_5:  # you may have multiple Buckets files
                arg_8 = arg_0.dataset_fs.get(arg_7).read()
                arg_6.append(arg_0._deserialization(arg_8))
        else:
            print("[Database] FAIL! Cannot find any dataset: {}".format(arg_2))
            return False

        print("[Database] Find {} datasets SUCCESS, took: {}s".format(len(arg_6), round(time.time() - arg_3, 2)))
        return arg_6


def Func(arg_0, **arg_1):
        """Delete datasets.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        """

        arg_0._fill_project_info(arg_1)
        arg_0.db.Dataset.delete_many(arg_1)
        logging.info("[Database] Delete Dataset SUCCESS")


def Func(arg_0, **arg_1):
        """Saves the validation log, timestamp will be added automatically.

        Parameters
        -----------
        kwargs : logging information
            Events, such as accuracy, loss, step number and etc.

        Examples
        ---------
        >>> db.Func(accuracy=0.33, loss=0.98)

        """

        arg_0._fill_project_info(arg_1)
        arg_1.update({'time': datetime.utcnow()})
        arg_2 = arg_0.db.ValidLog.insert_one(arg_1)
        arg_3 = arg_0._print_dict(arg_1)
        logging.info("[Database] valid log: " + arg_3)


def Func(arg_0, **arg_1):
        """Deletes training log.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        Examples
        ---------
        Save training log
        >>> db.save_training_log(accuracy=0.33)
        >>> db.save_training_log(accuracy=0.44)

        Delete logs that match the requirement
        >>> db.Func(accuracy=0.33)

        Delete all logs
        >>> db.Func()
        """
        arg_0._fill_project_info(arg_1)
        arg_0.db.TrainLog.delete_many(arg_1)
        logging.info("[Database] Delete TrainLog SUCCESS")


def Func(arg_0, arg_1=None, arg_2=None, arg_3=None, arg_4=None, **arg_5):
        """Uploads a task to the database, timestamp will be added automatically.

        Parameters
        -----------
        task_name : str
            The task name.
        script : str
            File name of the python script.
        hyper_parameters : dictionary
            The hyper parameters pass into the script.
        saved_result_keys : list of str
            The keys of the task results to keep in the database when the task finishes.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        -----------
        Uploads a task
        >>> db.Func(task_name='mnist', script='example/tutorial_mnist_simple.py', description='simple tutorial')

        Finds and runs the latest task
        >>> db.run_top_task(sess=sess, sort=[("time", pymongo.DESCENDING)])
        >>> db.run_top_task(sess=sess, sort=[("time", -1)])

        Finds and runs the oldest task
        >>> db.run_top_task(sess=sess, sort=[("time", pymongo.ASCENDING)])
        >>> db.run_top_task(sess=sess, sort=[("time", 1)])

        """
        if not isinstance(arg_1, str):  # is None:
            raise Exception("task_name should be string")
        if not isinstance(arg_2, str):  # is None:
            raise Exception("script should be string")
        if arg_3 is None:
            arg_3 = {}
        if arg_4 is None:
            arg_4 = []

        arg_0._fill_project_info(arg_5)
        arg_5.update({'time': datetime.utcnow()})
        arg_5.update({'hyper_parameters': arg_3})
        arg_5.update({'saved_result_keys': arg_4})

        arg_6 = open(arg_2, 'rb').read()

        arg_5.update({'status': 'pending', 'script': arg_6, 'result': {}})
        arg_0.db.Task.insert_one(arg_5)
        logging.info("[Database] Saved Task - task_name: {} script: {}".format(arg_1, arg_2))


def Func(arg_0, arg_1=None, arg_2=None, **arg_3):
        """Finds and runs a pending task that in the first of the sorting list.

        Parameters
        -----------
        task_name : str
            The task name.
        sort : List of tuple
            PyMongo sort comment, search "PyMongo find one sorting" and `collection level operations <http://api.mongodb.com/python/current/api/pymongo/collection.html>`__ for more details.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        ---------
        Monitors the database and pull tasks to run
        >>> while True:
        >>>     print("waiting task from distributor")
        >>>     db.Func(task_name='mnist', sort=[("time", -1)])
        >>>     time.sleep(1)

        Returns
        --------
        boolean : True for success, False for fail.
        """
        if not isinstance(arg_1, str):  # is None:
            raise Exception("task_name should be string")
        arg_0._fill_project_info(arg_3)
        arg_3.update({'status': 'pending'})

        # find task and set status to running
        arg_4 = arg_0.db.Task.find_one_and_update(arg_3, {'$set': {'status': 'running'}}, arg_2=arg_2)

        try:
            # get task info e.g. hyper parameters, python script
            if arg_4 is None:
                logging.info("[Database] Find Task FAIL: key: {} sort: {}".format(arg_1, arg_2))
                return False
            else:
                logging.info("[Database] Find Task SUCCESS: key: {} sort: {}".format(arg_1, arg_2))
            arg_5 = arg_4['time']
            arg_6 = arg_4['script']
            arg_7 = arg_4['_id']
            arg_8 = arg_4['hyper_parameters']
            arg_9 = arg_4['saved_result_keys']
            logging.info("  hyper parameters:")
            for arg_10 in arg_8:
                arg_11()[arg_10] = arg_8[arg_10]
                logging.info("    {}: {}".format(arg_10, arg_8[arg_10]))
            # run task
            arg_12 = time.time()
            logging.info("[Database] Start Task: key: {} sort: {} push time: {}".format(arg_1, arg_2, arg_5))
            arg_6 = arg_6.decode('utf-8')
            with tf.Graph().as_default():  # as graph: # clear all TF graphs
                exec(arg_6, arg_11())

            # set status to finished
            arg_13 = arg_0.db.Task.find_one_and_update({'_id': arg_7}, {'$set': {'status': 'finished'}})

            # return results
            arg_14 = {}
            for arg_15 in arg_9:
                logging.info("  result: {}={} {}".format(arg_15, arg_11()[arg_15], type(arg_11()[arg_15])))
                arg_14.update({"%s" % arg_15: arg_11()[arg_15]})
            arg_13 = arg_0.db.Task.find_one_and_update(
                {
                    '_id': arg_7
                }, {'$set': {
                    'result': arg_14
                }}, return_document=pymongo.ReturnDocument.AFTER
            )
            logging.info(
                "[Database] Finished Task: task_name - {} sort: {} push time: {} took: {}s".
                format(arg_1, arg_2, arg_5,
                       time.time() - arg_12)
            )
            return True
        except Exception as e:
            arg_16, arg_17, arg_18 = sys.exc_info()
            arg_19 = os.path.split(arg_18.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(arg_16, arg_17, arg_19, arg_18.tb_lineno, e))
            logging.info("[Database] Fail to run task")
            # if fail, set status back to pending
            arg_13 = arg_0.db.Task.find_one_and_update({'_id': arg_7}, {'$set': {'status': 'pending'}})
            return False


def Func(arg_0, **arg_1):
        """Delete tasks.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        Examples
        ---------
        >>> db.Func()

        """

        arg_0._fill_project_info(arg_1)
        arg_0.db.Task.delete_many(arg_1)
        logging.info("[Database] Delete Task SUCCESS")


def Func(arg_0, arg_1=None, **arg_2):
        """Finds and runs a pending task.

        Parameters
        -----------
        task_name : str
            The task name.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        ---------
        Wait until all tasks finish in user's local console

        >>> while not db.Func():
        >>>     time.sleep(1)
        >>> print("all tasks finished")
        >>> sess = tf.InteractiveSession()
        >>> net = db.find_top_model(sess=sess, sort=[("test_accuracy", -1)])
        >>> print("the best accuracy {} is from model {}".format(net._test_accuracy, net._name))

        Returns
        --------
        boolean : True for success, False for fail.

        """

        if not isinstance(arg_1, str):  # is None:
            raise Exception("task_name should be string")
        arg_0._fill_project_info(arg_2)

        arg_2.update({'$or': [{'status': 'pending'}, {'status': 'running'}]})

        # ## find task
        # task = self.db.Task.find_one(kwargs)
        arg_3 = arg_0.db.Task.find(arg_2)

        arg_4 = arg_3.distinct('_id')
        arg_5 = len(arg_4)

        if arg_5 == 0:
            logging.info("[Database] No unfinished task - task_name: {}".format(arg_1))
            return False
        else:

            logging.info("[Database] Find {} unfinished task - task_name: {}".format(arg_5, arg_1))
            return True


def Func(arg_0, arg_1, arg_2, arg_3=2):
    """Augment unigram features with hashed n-gram features."""

    def get_ngrams(arg_3):
        return list(zip(*[arg_0[arg_4:] for arg_4 in range(arg_3)]))

    def hash_ngram(arg_5):
        arg_6 = array.array('L', arg_5).tobytes()
        arg_7 = int(hashlib.sha256(arg_6).hexdigest(), 16)
        return arg_1 + arg_7 % arg_2

    return arg_0 + [hash_ngram(arg_5) for arg_4 in range(2, arg_3 + 1) for arg_5 in get_ngrams(arg_4)]


def Func(arg_0=None):
    """Load IMDb data and augment with hashed n-gram features."""
    arg_1, arg_2, arg_3, arg_4 = tl.files.load_imdb_dataset(nb_words=VOCAB_SIZE)

    if arg_0 is not None:
        arg_1 = np.array([augment_with_ngrams(x, VOCAB_SIZE, N_BUCKETS, n=arg_0) for x in arg_1])
        arg_3 = np.array([augment_with_ngrams(x, VOCAB_SIZE, N_BUCKETS, n=arg_0) for x in arg_3])

    return arg_1, arg_2, arg_3, arg_4


def Func(arg_0, arg_1=''):
    """Read one image.

    Parameters
    -----------
    image : str
        The image file name.
    path : str
        The image folder path.

    Returns
    -------
    numpy.array
        The image.

    """
    return imageio.imread(os.path.join(arg_1, arg_0))


def Func(arg_0, arg_1='', arg_2=10, arg_3=True):
    """Returns all images in list by given path and name of each image file.

    Parameters
    -------------
    img_list : list of str
        The image file names.
    path : str
        The image folder path.
    n_threads : int
        The number of threads to read image.
    printable : boolean
        Whether to print information when reading images.

    Returns
    -------
    list of numpy.array
        The images.

    """
    arg_4 = []
    for arg_5 in range(0, len(arg_0), arg_2):
        arg_6 = arg_0[arg_5:arg_5 + arg_2]
        arg_7 = tl.prepro.threading_data(arg_6, fn=read_image, arg_1=arg_1)
        # tl.logging.info(b_imgs.shape)
        arg_4.extend(arg_7)
        if arg_3:
            tl.logging.info('read %d from %s' % (len(arg_4), arg_1))
    return arg_4


def Func(arg_0, arg_1='_temp.png'):
    """Save a image.

    Parameters
    -----------
    image : numpy array
        [w, h, c]
    image_path : str
        path

    """
    try:  # RGB
        imageio.imwrite(arg_1, arg_0)
    except Exception:  # Greyscale
        imageio.imwrite(arg_1, arg_0[:, :, 0])


def Func(arg_0, arg_1, arg_2='_temp.png'):
    """Save multiple images into one single image.

    Parameters
    -----------
    images : numpy array
        (batch, w, h, c)
    size : list of 2 ints
        row and column number.
        number of images should be equal or less than size[0] * size[1]
    image_path : str
        save path

    Examples
    ---------
    >>> import numpy as np
    >>> import tensorlayer as tl
    >>> images = np.random.rand(64, 100, 100, 3)
    >>> tl.visualize.Func(images, [8, 8], 'temp.png')

    """
    if len(arg_0.shape) == 3:  # Greyscale [batch, h, w] --> [batch, h, w, 1]
        arg_0 = arg_0[:, :, :, np.newaxis]

    def merge(arg_0, arg_1):
        arg_3, arg_4 = arg_0.shape[1], arg_0.shape[2]
        arg_5 = np.zeros((arg_3 * arg_1[0], arg_4 * arg_1[1], 3), dtype=arg_0.dtype)
        for arg_6, arg_7 in enumerate(arg_0):
            arg_8 = arg_6 % arg_1[1]
            arg_9 = arg_6 // arg_1[1]
            arg_5[arg_9 * arg_3:arg_9 * arg_3 + arg_3, arg_8 * arg_4:arg_8 * arg_4 + arg_4, :] = arg_7
        return arg_5

    def imsave(arg_0, arg_1, arg_10):
        if np.max(arg_0) <= 1 and (-1 <= np.min(arg_0) < 0):
            arg_0 = ((arg_0 + 1) * 127.5).astype(np.uint8)
        elif np.max(arg_0) <= 1 and np.min(arg_0) >= 0:
            arg_0 = (arg_0 * 255).astype(np.uint8)

        return imageio.imwrite(arg_10, merge(arg_0, arg_1))

    if len(arg_0) > arg_1[0] * arg_1[1]:
        raise AssertionError("number of images should be equal or less than size[0] * size[1] {}".format(len(arg_0)))

    return imsave(arg_0, arg_1, arg_2)


def Func(
        arg_0, arg_1, arg_2, arg_3, arg_4, arg_5=True, arg_6=True, arg_7=None
):
    """Draw bboxes and class labels on image. Return or save the image with bboxes, example in the docs of ``tl.prepro``.

    Parameters
    -----------
    image : numpy.array
        The RGB image [height, width, channel].
    classes : list of int
        A list of class ID (int).
    coords : list of int
        A list of list for coordinates.
            - Should be [x, y, x2, y2] (up-left and botton-right format)
            - If [x_center, y_center, w, h] (set is_center to True).
    scores : list of float
        A list of score (float). (Optional)
    classes_list : list of str
        for converting ID to string on image.
    is_center : boolean
        Whether the coordinates is [x_center, y_center, w, h]
            - If coordinates are [x_center, y_center, w, h], set it to True for converting it to [x, y, x2, y2] (up-left and botton-right) internally.
            - If coordinates are [x1, x2, y1, y2], set it to False.
    is_rescale : boolean
        Whether to rescale the coordinates from pixel-unit format to ratio format.
            - If True, the input coordinates are the portion of width and high, this API will scale the coordinates to pixel unit internally.
            - If False, feed the coordinates with pixel unit format.
    save_name : None or str
        The name of image file (i.e. image.png), if None, not to save image.

    Returns
    -------
    numpy.array
        The saved image.

    References
    -----------
    - OpenCV rectangle and putText.
    - `scikit-image <http://scikit-image.org/docs/dev/api/skimage.draw.html#skimage.draw.rectangle>`__.

    """
    if len(arg_2) != len(arg_1):
        raise AssertionError("number of coordinates and classes are equal")

    if len(arg_3) > 0 and len(arg_3) != len(arg_1):
        raise AssertionError("number of scores and classes are equal")

    # don't change the original image, and avoid error https://stackoverflow.com/questions/30249053/python-opencv-drawing-errors-after-manipulating-array-with-numpy
    arg_0 = arg_0.copy()

    arg_8, arg_9 = arg_0.shape[0:2]
    arg_10 = int((arg_8 + arg_9) // 430)

    for arg_11, arg_12 in enumerate(arg_2):
        if arg_5:
            arg_13, arg_14, arg_15, arg_16 = tl.prepro.obj_box_coord_centroid_to_upleft_butright(arg_2[arg_11])
        else:
            arg_13, arg_14, arg_15, arg_16 = arg_2[arg_11]

        if arg_6:  # scale back to pixel unit if the coords are the portion of width and high
            arg_13, arg_14, arg_15, arg_16 = tl.prepro.obj_box_coord_scale_to_pixelunit([arg_13, arg_14, arg_15, arg_16], (arg_8, arg_9))

        cv2.rectangle(
            arg_0,
            (int(arg_13), int(arg_14)),
            (int(arg_15), int(arg_16)),  # up-left and botton-right
            [0, 255, 0],
            arg_10
        )

        cv2.putText(
            arg_0,
            arg_4[arg_1[arg_11]] + ((" %.2f" % (arg_3[arg_11])) if (len(arg_3) != 0) else " "),
            (int(arg_13), int(arg_14)),  # button left
            0,
            1.5e-3 * arg_8,  # bigger = larger font
            [0, 0, 256],  # self.meta['colors'][max_indx],
            int(arg_10 / 2) + 1
        )  # bold

    if arg_7 is not None:
        # cv2.imwrite('_my.png', image)
        save_image(arg_0, arg_7)
    # if len(coords) == 0:
    #     tl.logging.info("Func: no bboxes exist, cannot draw !")
    return arg_0


def Func(arg_0=None, arg_1=10, arg_2=True, arg_3='cnn', arg_4=3119362):
    """Display a group of RGB or Greyscale CNN masks.

    Parameters
    ----------
    CNN : numpy.array
        The image. e.g: 64 5x5 RGB images can be (5, 5, 3, 64).
    second : int
        The display second(s) for the image(s), if saveable is False.
    saveable : boolean
        Save or plot the figure.
    name : str
        A name to save the image, if saveable is True.
    fig_idx : int
        The matplotlib figure index.

    Examples
    --------
    >>> tl.visualize.Func(network.all_params[0].eval(), second=10, saveable=True, name='cnn1_mnist', fig_idx=2012)

    """
    import matplotlib.pyplot as plt
    # tl.logging.info(CNN.shape)    # (5, 5, 3, 64)
    # exit()
    arg_5 = arg_0.shape[3]
    arg_6 = arg_0.shape[0]
    arg_7 = arg_0.shape[1]
    arg_8 = arg_0.shape[2]
    arg_9 = int(np.sqrt(arg_5))
    arg_10 = int(np.ceil(arg_5 / arg_9))
    plt.ion()  # active mode
    arg_11 = plt.figure(arg_4)
    arg_12 = 1
    for arg_13 in range(1, arg_9 + 1):
        for arg_14 in range(1, arg_10 + 1):
            if arg_12 > arg_5:
                break
            arg_11.add_subplot(arg_10, arg_9, arg_12)
            # tl.logging.info(CNN[:,:,:,count-1].shape, n_row, n_col)   # (5, 1, 32) 5 5
            # exit()
            # plt.imshow(
            #         np.reshape(CNN[count-1,:,:,:], (n_row, n_col)),
            #         cmap='gray', interpolation="nearest")     # theano
            if arg_8 == 1:
                plt.imshow(np.reshape(arg_0[:, :, :, arg_12 - 1], (arg_6, arg_7)), cmap='gray', interpolation="nearest")
            elif arg_8 == 3:
                plt.imshow(
                    np.reshape(arg_0[:, :, :, arg_12 - 1], (arg_6, arg_7, arg_8)), cmap='gray', interpolation="nearest"
                )
            else:
                raise Exception("Unknown n_color")
            plt.gca().xaxis.set_major_locator(plt.NullLocator())  # distable tick
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            arg_12 = arg_12 + 1
    if arg_2:
        plt.savefig(arg_3 + '.pdf', format='pdf')
    else:
        plt.draw()
        plt.pause(arg_1)


def Func(arg_0, arg_1, arg_2=500, arg_3=5, arg_4=False, arg_5='tsne', arg_6=9862):
    """Visualize the embeddings by using t-SNE.

    Parameters
    ----------
    embeddings : numpy.array
        The embedding matrix.
    reverse_dictionary : dictionary
        id_to_word, mapping id to unique word.
    plot_only : int
        The number of examples to plot, choice the most common words.
    second : int
        The display second(s) for the image(s), if saveable is False.
    saveable : boolean
        Save or plot the figure.
    name : str
        A name to save the image, if saveable is True.
    fig_idx : int
        matplotlib figure index.

    Examples
    --------
    >>> see 'tutorial_word2vec_basic.py'
    >>> final_embeddings = normalized_embeddings.eval()
    >>> tl.visualize.Func(final_embeddings, labels, reverse_dictionary,
    ...                   plot_only=500, second=5, saveable=False, name='tsne')

    """
    import matplotlib.pyplot as plt

    def plot_with_labels(arg_7, arg_8, arg_9=(18, 18), arg_3=5, arg_4=True, arg_5='tsne', arg_6=9862):

        if arg_7.shape[0] < len(arg_8):
            raise AssertionError("More labels than embeddings")

        if arg_4 is False:
            plt.ion()
            plt.figure(arg_6)

        plt.figure(arg_9=arg_9)  # in inches

        for arg_10, arg_11 in enumerate(arg_8):
            arg_12, arg_13 = arg_7[arg_10, :]
            plt.scatter(arg_12, arg_13)
            plt.annotate(arg_11, xy=(arg_12, arg_13), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')

        if arg_4:
            plt.savefig(arg_5 + '.pdf', format='pdf')
        else:
            plt.draw()
            plt.pause(arg_3)

    try:
        from sklearn.manifold import TSNE
        from six.moves import xrange

        arg_14 = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000)
        # plot_only = 500
        arg_7 = arg_14.fit_transform(arg_0[:arg_2, :])
        arg_8 = [arg_1[arg_10] for arg_10 in xrange(arg_2)]
        plot_with_labels(arg_7, arg_8, arg_3=arg_3, arg_4=arg_4, arg_5=arg_5, arg_6=arg_6)

    except ImportError:
        arg_15 = "Please install sklearn and matplotlib to visualize embeddings."
        tl.logging.error(arg_15)
        raise ImportError(arg_15)


def Func(arg_0=None, arg_1=10, arg_2=True, arg_3=None, arg_4='mnist', arg_5=2396512):
    """Visualize every columns of the weight matrix to a group of Greyscale img.

    Parameters
    ----------
    W : numpy.array
        The weight matrix
    second : int
        The display second(s) for the image(s), if saveable is False.
    saveable : boolean
        Save or plot the figure.
    shape : a list with 2 int or None
        The shape of feature image, MNIST is [28, 80].
    name : a string
        A name to save the image, if saveable is True.
    fig_idx : int
        matplotlib figure index.

    Examples
    --------
    >>> tl.visualize.Func(network.all_params[0].eval(), second=10, saveable=True, name='weight_of_1st_layer', fig_idx=2012)

    """
    if arg_3 is None:
        arg_3 = [28, 28]

    import matplotlib.pyplot as plt
    if arg_2 is False:
        plt.ion()
    arg_6 = plt.figure(arg_5)  # show all feature images
    arg_7 = arg_0.shape[1]

    arg_8 = int(np.sqrt(arg_7))  # 每行显示的个数   若25个hidden unit -> 每行显示5个
    arg_9 = int(np.ceil(arg_7 / arg_8))
    arg_10 = int(1)
    for arg_11 in range(1, arg_8 + 1):
        for arg_12 in range(1, arg_9 + 1):
            if arg_10 > arg_7:
                break
            arg_6.add_subplot(arg_8, arg_9, arg_10)
            # ------------------------------------------------------------
            # plt.imshow(np.reshape(W[:,count-1],(28,28)), cmap='gray')
            # ------------------------------------------------------------
            arg_13 = arg_0[:, arg_10 - 1] / np.sqrt((arg_0[:, arg_10 - 1]**2).sum())
            # feature[feature<0.0001] = 0   # value threshold
            # if count == 1 or count == 2:
            #     print(np.mean(feature))
            # if np.std(feature) < 0.03:      # condition threshold
            #     feature = np.zeros_like(feature)
            # if np.mean(feature) < -0.015:      # condition threshold
            #     feature = np.zeros_like(feature)
            plt.imshow(
                np.reshape(arg_13, (arg_3[0], arg_3[1])), cmap='gray', interpolation="nearest"
            )  # , vmin=np.min(feature), vmax=np.max(feature))
            # plt.title(name)
            # ------------------------------------------------------------
            # plt.imshow(np.reshape(W[:,count-1] ,(np.sqrt(size),np.sqrt(size))), cmap='gray', interpolation="nearest")
            plt.gca().xaxis.set_major_locator(plt.NullLocator())  # distable tick
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            arg_10 = arg_10 + 1
    if arg_2:
        plt.savefig(arg_4 + '.pdf', format='pdf')
    else:
        plt.draw()
        plt.pause(arg_1)