<h3 dir="auto">System information</h3>
<ul dir="auto">
<li><strong>Have I written custom code (as opposed to using a stock example script provided in TensorFlow)</strong>:</li>
<li><strong>OS Platform and Distribution (e.g., Linux Ubuntu 16.04)</strong>:</li>
<li><strong>TensorFlow installed from (source or binary)</strong>: python wheel</li>
<li><strong>TensorFlow version (use command below)</strong>: 1.4 and 1.3</li>
<li><strong>Python version</strong>: 3.6.1</li>
<li><strong>Bazel version (if compiling from source)</strong>:</li>
<li><strong>GCC/Compiler version (if compiling from source)</strong>:</li>
<li><strong>CUDA/cuDNN version</strong>: None</li>
<li><strong>GPU model and memory</strong>: None</li>
<li><strong>Exact command to reproduce</strong>:</li>
</ul>
<p dir="auto">when I run tensorflow1.4 script using estimator, the script is 8 times slower than tensorflow 1.3</p>
<h3 dir="auto">Source code / logs</h3>
<p dir="auto"><code class="notranslate">main</code> script</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#!/usr/bin/env python
__author__ = 'zj'

import argparse
import os
import sys
import numpy as np
import time
try:
    import better_exceptions
except ImportError:
    pass
import tensorflow as tf
from src.model_ori import crnn_fn
from src.data_handler import data_loader
from src.config import Params, Alphabet
from src.input_utils import input_fn


def main(unused_argv):
    models_path = FLAGS.input_model_dir
    if not os.path.exists(models_path):
        assert FileNotFoundError

    models_list = [os.path.join(models_path, x[:-5]) for x in os.listdir(models_path) if x.endswith('.meta')]

    if not os.path.exists(FLAGS.output_model_dir):
        os.makedirs(FLAGS.output_model_dir)

    parameters = Params(eval_batch_size=128,
                        input_shape=(32, 304),
                        digits_only=False,
                        alphabet=Alphabet.CHINESECHAR_LETTERS_DIGITS_EXTENDED,
                        alphabet_decoding='same',
                        image_channels=1,
                        csv_delimiter=' ',
                        csv_files_eval=FLAGS.csv_files_eval,
                        output_model_dir=FLAGS.output_model_dir,
                        gpu=FLAGS.gpu
                        )

    model_params = {
        'Params': parameters,
    }

    os.environ['CUDA_VISIBLE_DEVICES'] = parameters.gpu
    config_sess = tf.ConfigProto()
    config_sess.gpu_options.per_process_gpu_memory_fraction = 0.6

    # Config estimator
    est_config = tf.estimator.RunConfig()
    est_config = est_config.replace(session_config=config_sess,
                                    save_summary_steps=100,
                                    model_dir=parameters.output_model_dir)

    estimator = tf.estimator.Estimator(model_fn=crnn_fn,
                                       params=model_params,
                                       config=est_config,
                                       model_dir=parameters.output_model_dir,
                                       )
    try:
        with open(FLAGS.output_file, encoding='utf-8', mode='w') as save_file:
            for model in models_list:
                start = time.time()
                
                eval_results = estimator.evaluate(input_fn=data_loader(csv_filename=parameters.csv_files_eval,
                                                                       params=parameters,
                                                                       batch_size=parameters.eval_batch_size,
                                                                       num_epochs=1),
                                                  steps=3,
                                                  checkpoint_path=model)
                print('time:',time.time() - start)
                print('model: %s Evaluation results: %s' % (model, str(eval_results)))
                save_file.write(model + ' ' + str(eval_results) + '\n')

    except KeyboardInterrupt:
        print('Interrupted')


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-fe', '--csv_files_eval', required=False, type=str, help='CSV filename for evaluation',
                        nargs='*', default=['E:/val1.csv'])
    parser.add_argument('-o', '--output_model_dir', required=False, type=str,
                        help='Directory for output', default='models_vgg_100K_no_eval')
    parser.add_argument('-m', '--input_model_dir', required=False, type=str,
                        help='Directory for output', default='model_test')
    parser.add_argument('-g', '--gpu', type=str, help=&quot;GPU 0,1 or '' &quot;, default='0')
    parser.add_argument('-of', '--output_file', required=False, type=str, default='123.txt', help=&quot;the log output file&quot;)

    tf.logging.set_verbosity(tf.logging.DEBUG)
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
"><pre class="notranslate"><span class="pl-c">#!/usr/bin/env python</span>
<span class="pl-s1">__author__</span> <span class="pl-c1">=</span> <span class="pl-s">'zj'</span>

<span class="pl-k">import</span> <span class="pl-s1">argparse</span>
<span class="pl-k">import</span> <span class="pl-s1">os</span>
<span class="pl-k">import</span> <span class="pl-s1">sys</span>
<span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">time</span>
<span class="pl-k">try</span>:
    <span class="pl-k">import</span> <span class="pl-s1">better_exceptions</span>
<span class="pl-k">except</span> <span class="pl-v">ImportError</span>:
    <span class="pl-k">pass</span>
<span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>
<span class="pl-k">from</span> <span class="pl-s1">src</span>.<span class="pl-s1">model_ori</span> <span class="pl-k">import</span> <span class="pl-s1">crnn_fn</span>
<span class="pl-k">from</span> <span class="pl-s1">src</span>.<span class="pl-s1">data_handler</span> <span class="pl-k">import</span> <span class="pl-s1">data_loader</span>
<span class="pl-k">from</span> <span class="pl-s1">src</span>.<span class="pl-s1">config</span> <span class="pl-k">import</span> <span class="pl-v">Params</span>, <span class="pl-v">Alphabet</span>
<span class="pl-k">from</span> <span class="pl-s1">src</span>.<span class="pl-s1">input_utils</span> <span class="pl-k">import</span> <span class="pl-s1">input_fn</span>


<span class="pl-k">def</span> <span class="pl-en">main</span>(<span class="pl-s1">unused_argv</span>):
    <span class="pl-s1">models_path</span> <span class="pl-c1">=</span> <span class="pl-v">FLAGS</span>.<span class="pl-s1">input_model_dir</span>
    <span class="pl-k">if</span> <span class="pl-c1">not</span> <span class="pl-s1">os</span>.<span class="pl-s1">path</span>.<span class="pl-en">exists</span>(<span class="pl-s1">models_path</span>):
        <span class="pl-k">assert</span> <span class="pl-v">FileNotFoundError</span>

    <span class="pl-s1">models_list</span> <span class="pl-c1">=</span> [<span class="pl-s1">os</span>.<span class="pl-s1">path</span>.<span class="pl-en">join</span>(<span class="pl-s1">models_path</span>, <span class="pl-s1">x</span>[:<span class="pl-c1">-</span><span class="pl-c1">5</span>]) <span class="pl-k">for</span> <span class="pl-s1">x</span> <span class="pl-c1">in</span> <span class="pl-s1">os</span>.<span class="pl-en">listdir</span>(<span class="pl-s1">models_path</span>) <span class="pl-k">if</span> <span class="pl-s1">x</span>.<span class="pl-en">endswith</span>(<span class="pl-s">'.meta'</span>)]

    <span class="pl-k">if</span> <span class="pl-c1">not</span> <span class="pl-s1">os</span>.<span class="pl-s1">path</span>.<span class="pl-en">exists</span>(<span class="pl-v">FLAGS</span>.<span class="pl-s1">output_model_dir</span>):
        <span class="pl-s1">os</span>.<span class="pl-en">makedirs</span>(<span class="pl-v">FLAGS</span>.<span class="pl-s1">output_model_dir</span>)

    <span class="pl-s1">parameters</span> <span class="pl-c1">=</span> <span class="pl-v">Params</span>(<span class="pl-s1">eval_batch_size</span><span class="pl-c1">=</span><span class="pl-c1">128</span>,
                        <span class="pl-s1">input_shape</span><span class="pl-c1">=</span>(<span class="pl-c1">32</span>, <span class="pl-c1">304</span>),
                        <span class="pl-s1">digits_only</span><span class="pl-c1">=</span><span class="pl-c1">False</span>,
                        <span class="pl-s1">alphabet</span><span class="pl-c1">=</span><span class="pl-v">Alphabet</span>.<span class="pl-v">CHINESECHAR_LETTERS_DIGITS_EXTENDED</span>,
                        <span class="pl-s1">alphabet_decoding</span><span class="pl-c1">=</span><span class="pl-s">'same'</span>,
                        <span class="pl-s1">image_channels</span><span class="pl-c1">=</span><span class="pl-c1">1</span>,
                        <span class="pl-s1">csv_delimiter</span><span class="pl-c1">=</span><span class="pl-s">' '</span>,
                        <span class="pl-s1">csv_files_eval</span><span class="pl-c1">=</span><span class="pl-v">FLAGS</span>.<span class="pl-s1">csv_files_eval</span>,
                        <span class="pl-s1">output_model_dir</span><span class="pl-c1">=</span><span class="pl-v">FLAGS</span>.<span class="pl-s1">output_model_dir</span>,
                        <span class="pl-s1">gpu</span><span class="pl-c1">=</span><span class="pl-v">FLAGS</span>.<span class="pl-s1">gpu</span>
                        )

    <span class="pl-s1">model_params</span> <span class="pl-c1">=</span> {
        <span class="pl-s">'Params'</span>: <span class="pl-s1">parameters</span>,
    }

    <span class="pl-s1">os</span>.<span class="pl-s1">environ</span>[<span class="pl-s">'CUDA_VISIBLE_DEVICES'</span>] <span class="pl-c1">=</span> <span class="pl-s1">parameters</span>.<span class="pl-s1">gpu</span>
    <span class="pl-s1">config_sess</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-v">ConfigProto</span>()
    <span class="pl-s1">config_sess</span>.<span class="pl-s1">gpu_options</span>.<span class="pl-s1">per_process_gpu_memory_fraction</span> <span class="pl-c1">=</span> <span class="pl-c1">0.6</span>

    <span class="pl-c"># Config estimator</span>
    <span class="pl-s1">est_config</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">estimator</span>.<span class="pl-v">RunConfig</span>()
    <span class="pl-s1">est_config</span> <span class="pl-c1">=</span> <span class="pl-s1">est_config</span>.<span class="pl-en">replace</span>(<span class="pl-s1">session_config</span><span class="pl-c1">=</span><span class="pl-s1">config_sess</span>,
                                    <span class="pl-s1">save_summary_steps</span><span class="pl-c1">=</span><span class="pl-c1">100</span>,
                                    <span class="pl-s1">model_dir</span><span class="pl-c1">=</span><span class="pl-s1">parameters</span>.<span class="pl-s1">output_model_dir</span>)

    <span class="pl-s1">estimator</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">estimator</span>.<span class="pl-v">Estimator</span>(<span class="pl-s1">model_fn</span><span class="pl-c1">=</span><span class="pl-s1">crnn_fn</span>,
                                       <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">model_params</span>,
                                       <span class="pl-s1">config</span><span class="pl-c1">=</span><span class="pl-s1">est_config</span>,
                                       <span class="pl-s1">model_dir</span><span class="pl-c1">=</span><span class="pl-s1">parameters</span>.<span class="pl-s1">output_model_dir</span>,
                                       )
    <span class="pl-k">try</span>:
        <span class="pl-k">with</span> <span class="pl-en">open</span>(<span class="pl-v">FLAGS</span>.<span class="pl-s1">output_file</span>, <span class="pl-s1">encoding</span><span class="pl-c1">=</span><span class="pl-s">'utf-8'</span>, <span class="pl-s1">mode</span><span class="pl-c1">=</span><span class="pl-s">'w'</span>) <span class="pl-k">as</span> <span class="pl-s1">save_file</span>:
            <span class="pl-k">for</span> <span class="pl-s1">model</span> <span class="pl-c1">in</span> <span class="pl-s1">models_list</span>:
                <span class="pl-s1">start</span> <span class="pl-c1">=</span> <span class="pl-s1">time</span>.<span class="pl-en">time</span>()
                
                <span class="pl-s1">eval_results</span> <span class="pl-c1">=</span> <span class="pl-s1">estimator</span>.<span class="pl-en">evaluate</span>(<span class="pl-s1">input_fn</span><span class="pl-c1">=</span><span class="pl-en">data_loader</span>(<span class="pl-s1">csv_filename</span><span class="pl-c1">=</span><span class="pl-s1">parameters</span>.<span class="pl-s1">csv_files_eval</span>,
                                                                       <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">parameters</span>,
                                                                       <span class="pl-s1">batch_size</span><span class="pl-c1">=</span><span class="pl-s1">parameters</span>.<span class="pl-s1">eval_batch_size</span>,
                                                                       <span class="pl-s1">num_epochs</span><span class="pl-c1">=</span><span class="pl-c1">1</span>),
                                                  <span class="pl-s1">steps</span><span class="pl-c1">=</span><span class="pl-c1">3</span>,
                                                  <span class="pl-s1">checkpoint_path</span><span class="pl-c1">=</span><span class="pl-s1">model</span>)
                <span class="pl-en">print</span>(<span class="pl-s">'time:'</span>,<span class="pl-s1">time</span>.<span class="pl-en">time</span>() <span class="pl-c1">-</span> <span class="pl-s1">start</span>)
                <span class="pl-en">print</span>(<span class="pl-s">'model: %s Evaluation results: %s'</span> <span class="pl-c1">%</span> (<span class="pl-s1">model</span>, <span class="pl-en">str</span>(<span class="pl-s1">eval_results</span>)))
                <span class="pl-s1">save_file</span>.<span class="pl-en">write</span>(<span class="pl-s1">model</span> <span class="pl-c1">+</span> <span class="pl-s">' '</span> <span class="pl-c1">+</span> <span class="pl-en">str</span>(<span class="pl-s1">eval_results</span>) <span class="pl-c1">+</span> <span class="pl-s">'<span class="pl-cce">\n</span>'</span>)

    <span class="pl-k">except</span> <span class="pl-v">KeyboardInterrupt</span>:
        <span class="pl-en">print</span>(<span class="pl-s">'Interrupted'</span>)


<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">'__main__'</span>:
    <span class="pl-s1">parser</span> <span class="pl-c1">=</span> <span class="pl-s1">argparse</span>.<span class="pl-v">ArgumentParser</span>()
    <span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">'-fe'</span>, <span class="pl-s">'--csv_files_eval'</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>, <span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">'CSV filename for evaluation'</span>,
                        <span class="pl-s1">nargs</span><span class="pl-c1">=</span><span class="pl-s">'*'</span>, <span class="pl-s1">default</span><span class="pl-c1">=</span>[<span class="pl-s">'E:/val1.csv'</span>])
    <span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">'-o'</span>, <span class="pl-s">'--output_model_dir'</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>,
                        <span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">'Directory for output'</span>, <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s">'models_vgg_100K_no_eval'</span>)
    <span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">'-m'</span>, <span class="pl-s">'--input_model_dir'</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>,
                        <span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">'Directory for output'</span>, <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s">'model_test'</span>)
    <span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">'-g'</span>, <span class="pl-s">'--gpu'</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>, <span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">"GPU 0,1 or '' "</span>, <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s">'0'</span>)
    <span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">'-of'</span>, <span class="pl-s">'--output_file'</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>, <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s">'123.txt'</span>, <span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">"the log output file"</span>)

    <span class="pl-s1">tf</span>.<span class="pl-s1">logging</span>.<span class="pl-en">set_verbosity</span>(<span class="pl-s1">tf</span>.<span class="pl-s1">logging</span>.<span class="pl-v">DEBUG</span>)
    <span class="pl-v">FLAGS</span>, <span class="pl-s1">unparsed</span> <span class="pl-c1">=</span> <span class="pl-s1">parser</span>.<span class="pl-en">parse_known_args</span>()
    <span class="pl-s1">tf</span>.<span class="pl-s1">app</span>.<span class="pl-en">run</span>(<span class="pl-s1">main</span><span class="pl-c1">=</span><span class="pl-s1">main</span>, <span class="pl-s1">argv</span><span class="pl-c1">=</span>[<span class="pl-s1">sys</span>.<span class="pl-s1">argv</span>[<span class="pl-c1">0</span>]] <span class="pl-c1">+</span> <span class="pl-s1">unparsed</span>)</pre></div>
<p dir="auto"><code class="notranslate">data_loader</code> script</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#!/usr/bin/env python
import tensorflow as tf
import numpy as np
from .config import Params, CONST
from typing import Tuple


def data_loader(csv_filename: str, params: Params, batch_size: int = 128, data_augmentation: bool = False,
                num_epochs: int = None, image_summaries: bool = False):
    def input_fn():
        # Choose case one csv file or list of csv files
        if not isinstance(csv_filename, list):
            filename_queue = tf.train.string_input_producer([csv_filename], num_epochs=num_epochs,
                                                            name='filename_queue')
        elif isinstance(csv_filename, list):
            filename_queue = tf.train.string_input_producer(csv_filename, num_epochs=num_epochs, name='filename_queue')

        # Skip lines that have already been processed
        reader = tf.TextLineReader(name='CSV_Reader', skip_header_lines=0)
        key, value = reader.read(filename_queue, name='file_reading_op')

        default_line = [['None'], ['None']]
        path, label = tf.decode_csv(value, record_defaults=default_line, field_delim=params.csv_delimiter,
                                    name='csv_reading_op')

        image, img_width = image_reading(path, resized_size=params.input_shape, params=params,
                                         data_augmentation=data_augmentation, padding=True)

        to_batch = {'images': image, 'images_widths': img_width, 'filenames': path, 'labels': label}
        prepared_batch = tf.train.shuffle_batch(to_batch,
                                                batch_size=batch_size,
                                                min_after_dequeue=500,
                                                num_threads=15, capacity=4000,
                                                allow_smaller_final_batch=False,
                                                name='prepared_batch_queue')

        if image_summaries:
            tf.summary.image('input/image', prepared_batch.get('images'), max_outputs=1)
        tf.summary.text('input/labels', prepared_batch.get('labels')[:10])
        tf.summary.text('input/widths', tf.as_string(prepared_batch.get('images_widths')))

        return prepared_batch, prepared_batch.get('labels')

    return input_fn


def image_reading(path: str, params: Params, resized_size: Tuple[int, int] = None, data_augmentation: bool = False,
                  padding: bool = False) -&gt; Tuple[tf.Tensor, tf.Tensor]:
    # Read image
    image_content = tf.read_file(path, name='image_reader')
    image = tf.cond(tf.equal(tf.string_split([path], '.').values[1], tf.constant('jpg', dtype=tf.string)),
                    true_fn=lambda: tf.image.decode_jpeg(image_content, channels=params.image_channels,
                                                         try_recover_truncated=True),  # TODO channels = 3 ?
                    false_fn=lambda: tf.image.decode_png(image_content, channels=params.image_channels),
                    name='image_decoding')

    # Data augmentation
    if data_augmentation:
        image = augment_data(image)

    # Padding
    if padding:
        with tf.name_scope('padding'):
            image, img_width = padding_inputs_width(image, resized_size, increment=CONST.DIMENSION_REDUCTION_W_POOLING)
    # Resize
    else:
        image = tf.image.resize_images(image, size=resized_size)
        img_width = tf.shape(image)[1]

    with tf.control_dependencies([tf.assert_equal(image.shape[:2], resized_size)]):
        return image, img_width


def random_rotation(img: tf.Tensor, max_rotation: float = 0.1, crop: bool = True) -&gt; tf.Tensor:  # from SeguinBe
    with tf.name_scope('RandomRotation'):
        rotation = tf.random_uniform([], -max_rotation, max_rotation)
        rotated_image = tf.contrib.image.rotate(img, rotation, interpolation='BILINEAR')
        if crop:
            rotation = tf.abs(rotation)
            original_shape = tf.shape(rotated_image)[:2]
            h, w = original_shape[0], original_shape[1]
            # see https://stackoverflow.com/questions/16702966/rotate-image-and-crop-out-black-borders for formulae
            old_l, old_s = tf.cond(h &gt; w, lambda: [h, w], lambda: [w, h])
            old_l, old_s = tf.cast(old_l, tf.float32), tf.cast(old_s, tf.float32)
            new_l = (old_l * tf.cos(rotation) - old_s * tf.sin(rotation)) / tf.cos(2 * rotation)
            new_s = (old_s - tf.sin(rotation) * new_l) / tf.cos(rotation)
            new_h, new_w = tf.cond(h &gt; w, lambda: [new_l, new_s], lambda: [new_s, new_l])
            new_h, new_w = tf.cast(new_h, tf.int32), tf.cast(new_w, tf.int32)
            bb_begin = tf.cast(tf.ceil((h - new_h) / 2), tf.int32), tf.cast(tf.ceil((w - new_w) / 2), tf.int32)
            rotated_image_crop = rotated_image[bb_begin[0]:h - bb_begin[0], bb_begin[1]:w - bb_begin[1], :]

            # If crop removes the entire image, keep the original image
            rotated_image = tf.cond(tf.equal(tf.size(rotated_image_crop), 0),
                                    true_fn=lambda: img,
                                    false_fn=lambda: rotated_image_crop)

        return rotated_image


def random_padding(image: tf.Tensor, max_pad_w: int = 5, max_pad_h: int = 10) -&gt; tf.Tensor:
    w_pad = list(np.random.randint(0, max_pad_w, size=[2]))
    h_pad = list(np.random.randint(0, max_pad_h, size=[2]))
    paddings = [h_pad, w_pad, [0, 0]]

    return tf.pad(image, paddings, mode='REFLECT', name='random_padding')


def augment_data(image: tf.Tensor) -&gt; tf.Tensor:
    with tf.name_scope('DataAugmentation'):
        # Random padding
        image = random_padding(image)

        image = tf.image.random_brightness(image, max_delta=0.1)
        image = tf.image.random_contrast(image, 0.5, 1.5)
        image = random_rotation(image, 0.05, crop=True)

        if image.shape[-1] &gt;= 3:
            image = tf.image.random_hue(image, 0.2)
            image = tf.image.random_saturation(image, 0.5, 1.5)

        return image


def padding_inputs_width(image: tf.Tensor, target_shape: Tuple[int, int], increment: int) -&gt; Tuple[
    tf.Tensor, tf.Tensor]:
    target_ratio = target_shape[1] / target_shape[0]
    # Compute ratio to keep the same ratio in new image and get the size of padding
    # necessary to have the final desired shape
    shape = tf.shape(image)
    # 计算宽高比
    ratio = tf.divide(shape[1], shape[0], name='ratio')

    new_h = target_shape[0]
    new_w = tf.cast(tf.round((ratio * new_h) / increment) * increment, tf.int32)
    f1 = lambda: (new_w, ratio)
    f2 = lambda: (new_h, tf.constant(1.0, dtype=tf.float64))
    new_w, ratio = tf.case({tf.greater(new_w, 0): f1,
                            tf.less_equal(new_w, 0): f2},
                           default=f1, exclusive=True)
    target_w = target_shape[1]

    # Definitions for cases
    def pad_fn():
        with tf.name_scope('mirror_padding'):
            pad = tf.subtract(target_w, new_w)

            img_resized = tf.image.resize_images(image, [new_h, new_w])

            # Padding to have the desired width
            paddings = [[0, 0], [0, pad], [0, 0]]
            pad_image = tf.pad(img_resized, paddings, mode='SYMMETRIC', name=None)

            # Set manually the shape
            pad_image.set_shape([target_shape[0], target_shape[1], img_resized.get_shape()[2]])

            return pad_image, (new_h, new_w)

    def replicate_fn():
        with tf.name_scope('replication_padding'):
            img_resized = tf.image.resize_images(image, [new_h, new_w])

            # If one symmetry is not enough to have a full width
            # Count number of replications needed
            n_replication = tf.cast(tf.ceil(target_shape[1] / new_w), tf.int32)
            img_replicated = tf.tile(img_resized, tf.stack([1, n_replication, 1]))
            pad_image = tf.image.crop_to_bounding_box(image=img_replicated, offset_height=0, offset_width=0,
                                                      target_height=target_shape[0], target_width=target_shape[1])

            # Set manually the shape
            pad_image.set_shape([target_shape[0], target_shape[1], img_resized.get_shape()[2]])

            return pad_image, (new_h, new_w)

    def simple_resize():
        with tf.name_scope('simple_resize'):
            img_resized = tf.image.resize_images(image, target_shape)

            img_resized.set_shape([target_shape[0], target_shape[1], img_resized.get_shape()[2]])

            return img_resized, target_shape

    # 3 cases
    pad_image, (new_h, new_w) = tf.case(
        {  # case 1 : new_w &gt;= target_w
            tf.logical_and(tf.greater_equal(ratio, target_ratio),
                           tf.greater_equal(new_w, target_w)): simple_resize,
            # case 2 : new_w &gt;= target_w/2 &amp; new_w &lt; target_w &amp; ratio &lt; target_ratio
            tf.logical_and(tf.less(ratio, target_ratio),
                           tf.logical_and(tf.greater_equal(new_w, tf.cast(tf.divide(target_w, 2), tf.int32)),
                                          tf.less(new_w, target_w))): pad_fn,
            # case 3 : new_w &lt; target_w/2 &amp; new_w &lt; target_w &amp; ratio &lt; target_ratio
            tf.logical_and(tf.less(ratio, target_ratio),
                           tf.logical_and(tf.less(new_w, target_w),
                                          tf.less(new_w, tf.cast(tf.divide(target_w, 2), tf.int32)))): replicate_fn
        },
        default=simple_resize, exclusive=True)

    return pad_image, new_w  # new_w = image width used for computing sequence lengths


def preprocess_image_for_prediction(fixed_height: int = 32, min_width: int = 8):
    &quot;&quot;&quot;
    Input function to use when exporting the model for making predictions (see estimator.export_savedmodel)
    :param fixed_height: height of the input image after resizing
    :param min_width: minimum width of image after resizing
    :return:
    &quot;&quot;&quot;

    def serving_input_fn():
        # define placeholder for input image
        image = tf.placeholder(dtype=tf.float32, shape=[None, None, 1])

        shape = tf.shape(image)
        # Assert shape is h x w x c with c = 1

        ratio = tf.divide(shape[1], shape[0])
        increment = CONST.DIMENSION_REDUCTION_W_POOLING
        new_width = tf.cast(tf.round((ratio * fixed_height) / increment) * increment, tf.int32)

        resized_image = tf.cond(new_width &lt; tf.constant(min_width, dtype=tf.int32),
                                true_fn=lambda: tf.image.resize_images(image, size=(fixed_height, min_width)),
                                false_fn=lambda: tf.image.resize_images(image, size=(fixed_height, new_width))
                                )

        # Features to serve
        features = {'images': resized_image[None],  # cast to 1 x h x w x c
                    'images_widths': new_width[None]  # cast to tensor
                    }

        # Inputs received
        receiver_inputs = {'images': image}

        return tf.estimator.export.ServingInputReceiver(features, receiver_inputs)

    return serving_input_fn"><pre class="notranslate"><span class="pl-c">#!/usr/bin/env python</span>
<span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>
<span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">from</span> .<span class="pl-s1">config</span> <span class="pl-k">import</span> <span class="pl-v">Params</span>, <span class="pl-v">CONST</span>
<span class="pl-k">from</span> <span class="pl-s1">typing</span> <span class="pl-k">import</span> <span class="pl-v">Tuple</span>


<span class="pl-k">def</span> <span class="pl-en">data_loader</span>(<span class="pl-s1">csv_filename</span>: <span class="pl-s1">str</span>, <span class="pl-s1">params</span>: <span class="pl-v">Params</span>, <span class="pl-s1">batch_size</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">128</span>, <span class="pl-s1">data_augmentation</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>,
                <span class="pl-s1">num_epochs</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">None</span>, <span class="pl-s1">image_summaries</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>):
    <span class="pl-k">def</span> <span class="pl-en">input_fn</span>():
        <span class="pl-c"># Choose case one csv file or list of csv files</span>
        <span class="pl-k">if</span> <span class="pl-c1">not</span> <span class="pl-en">isinstance</span>(<span class="pl-s1">csv_filename</span>, <span class="pl-s1">list</span>):
            <span class="pl-s1">filename_queue</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">train</span>.<span class="pl-en">string_input_producer</span>([<span class="pl-s1">csv_filename</span>], <span class="pl-s1">num_epochs</span><span class="pl-c1">=</span><span class="pl-s1">num_epochs</span>,
                                                            <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'filename_queue'</span>)
        <span class="pl-k">elif</span> <span class="pl-en">isinstance</span>(<span class="pl-s1">csv_filename</span>, <span class="pl-s1">list</span>):
            <span class="pl-s1">filename_queue</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">train</span>.<span class="pl-en">string_input_producer</span>(<span class="pl-s1">csv_filename</span>, <span class="pl-s1">num_epochs</span><span class="pl-c1">=</span><span class="pl-s1">num_epochs</span>, <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'filename_queue'</span>)

        <span class="pl-c"># Skip lines that have already been processed</span>
        <span class="pl-s1">reader</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-v">TextLineReader</span>(<span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'CSV_Reader'</span>, <span class="pl-s1">skip_header_lines</span><span class="pl-c1">=</span><span class="pl-c1">0</span>)
        <span class="pl-s1">key</span>, <span class="pl-s1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">reader</span>.<span class="pl-en">read</span>(<span class="pl-s1">filename_queue</span>, <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'file_reading_op'</span>)

        <span class="pl-s1">default_line</span> <span class="pl-c1">=</span> [[<span class="pl-s">'None'</span>], [<span class="pl-s">'None'</span>]]
        <span class="pl-s1">path</span>, <span class="pl-s1">label</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">decode_csv</span>(<span class="pl-s1">value</span>, <span class="pl-s1">record_defaults</span><span class="pl-c1">=</span><span class="pl-s1">default_line</span>, <span class="pl-s1">field_delim</span><span class="pl-c1">=</span><span class="pl-s1">params</span>.<span class="pl-s1">csv_delimiter</span>,
                                    <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'csv_reading_op'</span>)

        <span class="pl-s1">image</span>, <span class="pl-s1">img_width</span> <span class="pl-c1">=</span> <span class="pl-en">image_reading</span>(<span class="pl-s1">path</span>, <span class="pl-s1">resized_size</span><span class="pl-c1">=</span><span class="pl-s1">params</span>.<span class="pl-s1">input_shape</span>, <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">params</span>,
                                         <span class="pl-s1">data_augmentation</span><span class="pl-c1">=</span><span class="pl-s1">data_augmentation</span>, <span class="pl-s1">padding</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)

        <span class="pl-s1">to_batch</span> <span class="pl-c1">=</span> {<span class="pl-s">'images'</span>: <span class="pl-s1">image</span>, <span class="pl-s">'images_widths'</span>: <span class="pl-s1">img_width</span>, <span class="pl-s">'filenames'</span>: <span class="pl-s1">path</span>, <span class="pl-s">'labels'</span>: <span class="pl-s1">label</span>}
        <span class="pl-s1">prepared_batch</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">train</span>.<span class="pl-en">shuffle_batch</span>(<span class="pl-s1">to_batch</span>,
                                                <span class="pl-s1">batch_size</span><span class="pl-c1">=</span><span class="pl-s1">batch_size</span>,
                                                <span class="pl-s1">min_after_dequeue</span><span class="pl-c1">=</span><span class="pl-c1">500</span>,
                                                <span class="pl-s1">num_threads</span><span class="pl-c1">=</span><span class="pl-c1">15</span>, <span class="pl-s1">capacity</span><span class="pl-c1">=</span><span class="pl-c1">4000</span>,
                                                <span class="pl-s1">allow_smaller_final_batch</span><span class="pl-c1">=</span><span class="pl-c1">False</span>,
                                                <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'prepared_batch_queue'</span>)

        <span class="pl-k">if</span> <span class="pl-s1">image_summaries</span>:
            <span class="pl-s1">tf</span>.<span class="pl-s1">summary</span>.<span class="pl-en">image</span>(<span class="pl-s">'input/image'</span>, <span class="pl-s1">prepared_batch</span>.<span class="pl-en">get</span>(<span class="pl-s">'images'</span>), <span class="pl-s1">max_outputs</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
        <span class="pl-s1">tf</span>.<span class="pl-s1">summary</span>.<span class="pl-en">text</span>(<span class="pl-s">'input/labels'</span>, <span class="pl-s1">prepared_batch</span>.<span class="pl-en">get</span>(<span class="pl-s">'labels'</span>)[:<span class="pl-c1">10</span>])
        <span class="pl-s1">tf</span>.<span class="pl-s1">summary</span>.<span class="pl-en">text</span>(<span class="pl-s">'input/widths'</span>, <span class="pl-s1">tf</span>.<span class="pl-en">as_string</span>(<span class="pl-s1">prepared_batch</span>.<span class="pl-en">get</span>(<span class="pl-s">'images_widths'</span>)))

        <span class="pl-k">return</span> <span class="pl-s1">prepared_batch</span>, <span class="pl-s1">prepared_batch</span>.<span class="pl-en">get</span>(<span class="pl-s">'labels'</span>)

    <span class="pl-k">return</span> <span class="pl-s1">input_fn</span>


<span class="pl-k">def</span> <span class="pl-en">image_reading</span>(<span class="pl-s1">path</span>: <span class="pl-s1">str</span>, <span class="pl-s1">params</span>: <span class="pl-v">Params</span>, <span class="pl-s1">resized_size</span>: <span class="pl-v">Tuple</span>[<span class="pl-s1">int</span>, <span class="pl-s1">int</span>] <span class="pl-c1">=</span> <span class="pl-c1">None</span>, <span class="pl-s1">data_augmentation</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>,
                  <span class="pl-s1">padding</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>) <span class="pl-c1">-&gt;</span> <span class="pl-v">Tuple</span>[<span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>, <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>]:
    <span class="pl-c"># Read image</span>
    <span class="pl-s1">image_content</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">read_file</span>(<span class="pl-s1">path</span>, <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'image_reader'</span>)
    <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cond</span>(<span class="pl-s1">tf</span>.<span class="pl-en">equal</span>(<span class="pl-s1">tf</span>.<span class="pl-en">string_split</span>([<span class="pl-s1">path</span>], <span class="pl-s">'.'</span>).<span class="pl-s1">values</span>[<span class="pl-c1">1</span>], <span class="pl-s1">tf</span>.<span class="pl-en">constant</span>(<span class="pl-s">'jpg'</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">string</span>)),
                    <span class="pl-s1">true_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">decode_jpeg</span>(<span class="pl-s1">image_content</span>, <span class="pl-s1">channels</span><span class="pl-c1">=</span><span class="pl-s1">params</span>.<span class="pl-s1">image_channels</span>,
                                                         <span class="pl-s1">try_recover_truncated</span><span class="pl-c1">=</span><span class="pl-c1">True</span>),  <span class="pl-c"># TODO channels = 3 ?</span>
                    <span class="pl-s1">false_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">decode_png</span>(<span class="pl-s1">image_content</span>, <span class="pl-s1">channels</span><span class="pl-c1">=</span><span class="pl-s1">params</span>.<span class="pl-s1">image_channels</span>),
                    <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'image_decoding'</span>)

    <span class="pl-c"># Data augmentation</span>
    <span class="pl-k">if</span> <span class="pl-s1">data_augmentation</span>:
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-en">augment_data</span>(<span class="pl-s1">image</span>)

    <span class="pl-c"># Padding</span>
    <span class="pl-k">if</span> <span class="pl-s1">padding</span>:
        <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'padding'</span>):
            <span class="pl-s1">image</span>, <span class="pl-s1">img_width</span> <span class="pl-c1">=</span> <span class="pl-en">padding_inputs_width</span>(<span class="pl-s1">image</span>, <span class="pl-s1">resized_size</span>, <span class="pl-s1">increment</span><span class="pl-c1">=</span><span class="pl-v">CONST</span>.<span class="pl-v">DIMENSION_REDUCTION_W_POOLING</span>)
    <span class="pl-c"># Resize</span>
    <span class="pl-k">else</span>:
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span><span class="pl-s1">resized_size</span>)
        <span class="pl-s1">img_width</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">shape</span>(<span class="pl-s1">image</span>)[<span class="pl-c1">1</span>]

    <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">control_dependencies</span>([<span class="pl-s1">tf</span>.<span class="pl-en">assert_equal</span>(<span class="pl-s1">image</span>.<span class="pl-s1">shape</span>[:<span class="pl-c1">2</span>], <span class="pl-s1">resized_size</span>)]):
        <span class="pl-k">return</span> <span class="pl-s1">image</span>, <span class="pl-s1">img_width</span>


<span class="pl-k">def</span> <span class="pl-en">random_rotation</span>(<span class="pl-s1">img</span>: <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>, <span class="pl-s1">max_rotation</span>: <span class="pl-s1">float</span> <span class="pl-c1">=</span> <span class="pl-c1">0.1</span>, <span class="pl-s1">crop</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">True</span>) <span class="pl-c1">-&gt;</span> <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>:  <span class="pl-c"># from SeguinBe</span>
    <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'RandomRotation'</span>):
        <span class="pl-s1">rotation</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">random_uniform</span>([], <span class="pl-c1">-</span><span class="pl-s1">max_rotation</span>, <span class="pl-s1">max_rotation</span>)
        <span class="pl-s1">rotated_image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">contrib</span>.<span class="pl-s1">image</span>.<span class="pl-en">rotate</span>(<span class="pl-s1">img</span>, <span class="pl-s1">rotation</span>, <span class="pl-s1">interpolation</span><span class="pl-c1">=</span><span class="pl-s">'BILINEAR'</span>)
        <span class="pl-k">if</span> <span class="pl-s1">crop</span>:
            <span class="pl-s1">rotation</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">abs</span>(<span class="pl-s1">rotation</span>)
            <span class="pl-s1">original_shape</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">shape</span>(<span class="pl-s1">rotated_image</span>)[:<span class="pl-c1">2</span>]
            <span class="pl-s1">h</span>, <span class="pl-s1">w</span> <span class="pl-c1">=</span> <span class="pl-s1">original_shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">original_shape</span>[<span class="pl-c1">1</span>]
            <span class="pl-c"># see https://stackoverflow.com/questions/16702966/rotate-image-and-crop-out-black-borders for formulae</span>
            <span class="pl-s1">old_l</span>, <span class="pl-s1">old_s</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cond</span>(<span class="pl-s1">h</span> <span class="pl-c1">&gt;</span> <span class="pl-s1">w</span>, <span class="pl-k">lambda</span>: [<span class="pl-s1">h</span>, <span class="pl-s1">w</span>], <span class="pl-k">lambda</span>: [<span class="pl-s1">w</span>, <span class="pl-s1">h</span>])
            <span class="pl-s1">old_l</span>, <span class="pl-s1">old_s</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">old_l</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">float32</span>), <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">old_s</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">float32</span>)
            <span class="pl-s1">new_l</span> <span class="pl-c1">=</span> (<span class="pl-s1">old_l</span> <span class="pl-c1">*</span> <span class="pl-s1">tf</span>.<span class="pl-en">cos</span>(<span class="pl-s1">rotation</span>) <span class="pl-c1">-</span> <span class="pl-s1">old_s</span> <span class="pl-c1">*</span> <span class="pl-s1">tf</span>.<span class="pl-en">sin</span>(<span class="pl-s1">rotation</span>)) <span class="pl-c1">/</span> <span class="pl-s1">tf</span>.<span class="pl-en">cos</span>(<span class="pl-c1">2</span> <span class="pl-c1">*</span> <span class="pl-s1">rotation</span>)
            <span class="pl-s1">new_s</span> <span class="pl-c1">=</span> (<span class="pl-s1">old_s</span> <span class="pl-c1">-</span> <span class="pl-s1">tf</span>.<span class="pl-en">sin</span>(<span class="pl-s1">rotation</span>) <span class="pl-c1">*</span> <span class="pl-s1">new_l</span>) <span class="pl-c1">/</span> <span class="pl-s1">tf</span>.<span class="pl-en">cos</span>(<span class="pl-s1">rotation</span>)
            <span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cond</span>(<span class="pl-s1">h</span> <span class="pl-c1">&gt;</span> <span class="pl-s1">w</span>, <span class="pl-k">lambda</span>: [<span class="pl-s1">new_l</span>, <span class="pl-s1">new_s</span>], <span class="pl-k">lambda</span>: [<span class="pl-s1">new_s</span>, <span class="pl-s1">new_l</span>])
            <span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">new_h</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>), <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)
            <span class="pl-s1">bb_begin</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">ceil</span>((<span class="pl-s1">h</span> <span class="pl-c1">-</span> <span class="pl-s1">new_h</span>) <span class="pl-c1">/</span> <span class="pl-c1">2</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>), <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">ceil</span>((<span class="pl-s1">w</span> <span class="pl-c1">-</span> <span class="pl-s1">new_w</span>) <span class="pl-c1">/</span> <span class="pl-c1">2</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)
            <span class="pl-s1">rotated_image_crop</span> <span class="pl-c1">=</span> <span class="pl-s1">rotated_image</span>[<span class="pl-s1">bb_begin</span>[<span class="pl-c1">0</span>]:<span class="pl-s1">h</span> <span class="pl-c1">-</span> <span class="pl-s1">bb_begin</span>[<span class="pl-c1">0</span>], <span class="pl-s1">bb_begin</span>[<span class="pl-c1">1</span>]:<span class="pl-s1">w</span> <span class="pl-c1">-</span> <span class="pl-s1">bb_begin</span>[<span class="pl-c1">1</span>], :]

            <span class="pl-c"># If crop removes the entire image, keep the original image</span>
            <span class="pl-s1">rotated_image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cond</span>(<span class="pl-s1">tf</span>.<span class="pl-en">equal</span>(<span class="pl-s1">tf</span>.<span class="pl-en">size</span>(<span class="pl-s1">rotated_image_crop</span>), <span class="pl-c1">0</span>),
                                    <span class="pl-s1">true_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">img</span>,
                                    <span class="pl-s1">false_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">rotated_image_crop</span>)

        <span class="pl-k">return</span> <span class="pl-s1">rotated_image</span>


<span class="pl-k">def</span> <span class="pl-en">random_padding</span>(<span class="pl-s1">image</span>: <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>, <span class="pl-s1">max_pad_w</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">5</span>, <span class="pl-s1">max_pad_h</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">10</span>) <span class="pl-c1">-&gt;</span> <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>:
    <span class="pl-s1">w_pad</span> <span class="pl-c1">=</span> <span class="pl-en">list</span>(<span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">randint</span>(<span class="pl-c1">0</span>, <span class="pl-s1">max_pad_w</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span>[<span class="pl-c1">2</span>]))
    <span class="pl-s1">h_pad</span> <span class="pl-c1">=</span> <span class="pl-en">list</span>(<span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">randint</span>(<span class="pl-c1">0</span>, <span class="pl-s1">max_pad_h</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span>[<span class="pl-c1">2</span>]))
    <span class="pl-s1">paddings</span> <span class="pl-c1">=</span> [<span class="pl-s1">h_pad</span>, <span class="pl-s1">w_pad</span>, [<span class="pl-c1">0</span>, <span class="pl-c1">0</span>]]

    <span class="pl-k">return</span> <span class="pl-s1">tf</span>.<span class="pl-en">pad</span>(<span class="pl-s1">image</span>, <span class="pl-s1">paddings</span>, <span class="pl-s1">mode</span><span class="pl-c1">=</span><span class="pl-s">'REFLECT'</span>, <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'random_padding'</span>)


<span class="pl-k">def</span> <span class="pl-en">augment_data</span>(<span class="pl-s1">image</span>: <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>) <span class="pl-c1">-&gt;</span> <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>:
    <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'DataAugmentation'</span>):
        <span class="pl-c"># Random padding</span>
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-en">random_padding</span>(<span class="pl-s1">image</span>)

        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">random_brightness</span>(<span class="pl-s1">image</span>, <span class="pl-s1">max_delta</span><span class="pl-c1">=</span><span class="pl-c1">0.1</span>)
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">random_contrast</span>(<span class="pl-s1">image</span>, <span class="pl-c1">0.5</span>, <span class="pl-c1">1.5</span>)
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-en">random_rotation</span>(<span class="pl-s1">image</span>, <span class="pl-c1">0.05</span>, <span class="pl-s1">crop</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)

        <span class="pl-k">if</span> <span class="pl-s1">image</span>.<span class="pl-s1">shape</span>[<span class="pl-c1">-</span><span class="pl-c1">1</span>] <span class="pl-c1">&gt;=</span> <span class="pl-c1">3</span>:
            <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">random_hue</span>(<span class="pl-s1">image</span>, <span class="pl-c1">0.2</span>)
            <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">random_saturation</span>(<span class="pl-s1">image</span>, <span class="pl-c1">0.5</span>, <span class="pl-c1">1.5</span>)

        <span class="pl-k">return</span> <span class="pl-s1">image</span>


<span class="pl-k">def</span> <span class="pl-en">padding_inputs_width</span>(<span class="pl-s1">image</span>: <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>, <span class="pl-s1">target_shape</span>: <span class="pl-v">Tuple</span>[<span class="pl-s1">int</span>, <span class="pl-s1">int</span>], <span class="pl-s1">increment</span>: <span class="pl-s1">int</span>) <span class="pl-c1">-&gt;</span> <span class="pl-v">Tuple</span>[
    <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>, <span class="pl-s1">tf</span>.<span class="pl-v">Tensor</span>]:
    <span class="pl-s1">target_ratio</span> <span class="pl-c1">=</span> <span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>] <span class="pl-c1">/</span> <span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>]
    <span class="pl-c"># Compute ratio to keep the same ratio in new image and get the size of padding</span>
    <span class="pl-c"># necessary to have the final desired shape</span>
    <span class="pl-s1">shape</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">shape</span>(<span class="pl-s1">image</span>)
    <span class="pl-c"># 计算宽高比</span>
    <span class="pl-s1">ratio</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">divide</span>(<span class="pl-s1">shape</span>[<span class="pl-c1">1</span>], <span class="pl-s1">shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">'ratio'</span>)

    <span class="pl-s1">new_h</span> <span class="pl-c1">=</span> <span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>]
    <span class="pl-s1">new_w</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">round</span>((<span class="pl-s1">ratio</span> <span class="pl-c1">*</span> <span class="pl-s1">new_h</span>) <span class="pl-c1">/</span> <span class="pl-s1">increment</span>) <span class="pl-c1">*</span> <span class="pl-s1">increment</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)
    <span class="pl-s1">f1</span> <span class="pl-c1">=</span> <span class="pl-k">lambda</span>: (<span class="pl-s1">new_w</span>, <span class="pl-s1">ratio</span>)
    <span class="pl-s1">f2</span> <span class="pl-c1">=</span> <span class="pl-k">lambda</span>: (<span class="pl-s1">new_h</span>, <span class="pl-s1">tf</span>.<span class="pl-en">constant</span>(<span class="pl-c1">1.0</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">float64</span>))
    <span class="pl-s1">new_w</span>, <span class="pl-s1">ratio</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">case</span>({<span class="pl-s1">tf</span>.<span class="pl-en">greater</span>(<span class="pl-s1">new_w</span>, <span class="pl-c1">0</span>): <span class="pl-s1">f1</span>,
                            <span class="pl-s1">tf</span>.<span class="pl-en">less_equal</span>(<span class="pl-s1">new_w</span>, <span class="pl-c1">0</span>): <span class="pl-s1">f2</span>},
                           <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s1">f1</span>, <span class="pl-s1">exclusive</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
    <span class="pl-s1">target_w</span> <span class="pl-c1">=</span> <span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>]

    <span class="pl-c"># Definitions for cases</span>
    <span class="pl-k">def</span> <span class="pl-en">pad_fn</span>():
        <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'mirror_padding'</span>):
            <span class="pl-s1">pad</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">subtract</span>(<span class="pl-s1">target_w</span>, <span class="pl-s1">new_w</span>)

            <span class="pl-s1">img_resized</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, [<span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span>])

            <span class="pl-c"># Padding to have the desired width</span>
            <span class="pl-s1">paddings</span> <span class="pl-c1">=</span> [[<span class="pl-c1">0</span>, <span class="pl-c1">0</span>], [<span class="pl-c1">0</span>, <span class="pl-s1">pad</span>], [<span class="pl-c1">0</span>, <span class="pl-c1">0</span>]]
            <span class="pl-s1">pad_image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">pad</span>(<span class="pl-s1">img_resized</span>, <span class="pl-s1">paddings</span>, <span class="pl-s1">mode</span><span class="pl-c1">=</span><span class="pl-s">'SYMMETRIC'</span>, <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-c1">None</span>)

            <span class="pl-c"># Set manually the shape</span>
            <span class="pl-s1">pad_image</span>.<span class="pl-en">set_shape</span>([<span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>], <span class="pl-s1">img_resized</span>.<span class="pl-en">get_shape</span>()[<span class="pl-c1">2</span>]])

            <span class="pl-k">return</span> <span class="pl-s1">pad_image</span>, (<span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span>)

    <span class="pl-k">def</span> <span class="pl-en">replicate_fn</span>():
        <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'replication_padding'</span>):
            <span class="pl-s1">img_resized</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, [<span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span>])

            <span class="pl-c"># If one symmetry is not enough to have a full width</span>
            <span class="pl-c"># Count number of replications needed</span>
            <span class="pl-s1">n_replication</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">ceil</span>(<span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>] <span class="pl-c1">/</span> <span class="pl-s1">new_w</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)
            <span class="pl-s1">img_replicated</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">tile</span>(<span class="pl-s1">img_resized</span>, <span class="pl-s1">tf</span>.<span class="pl-en">stack</span>([<span class="pl-c1">1</span>, <span class="pl-s1">n_replication</span>, <span class="pl-c1">1</span>]))
            <span class="pl-s1">pad_image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">crop_to_bounding_box</span>(<span class="pl-s1">image</span><span class="pl-c1">=</span><span class="pl-s1">img_replicated</span>, <span class="pl-s1">offset_height</span><span class="pl-c1">=</span><span class="pl-c1">0</span>, <span class="pl-s1">offset_width</span><span class="pl-c1">=</span><span class="pl-c1">0</span>,
                                                      <span class="pl-s1">target_height</span><span class="pl-c1">=</span><span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">target_width</span><span class="pl-c1">=</span><span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>])

            <span class="pl-c"># Set manually the shape</span>
            <span class="pl-s1">pad_image</span>.<span class="pl-en">set_shape</span>([<span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>], <span class="pl-s1">img_resized</span>.<span class="pl-en">get_shape</span>()[<span class="pl-c1">2</span>]])

            <span class="pl-k">return</span> <span class="pl-s1">pad_image</span>, (<span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span>)

    <span class="pl-k">def</span> <span class="pl-en">simple_resize</span>():
        <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-en">name_scope</span>(<span class="pl-s">'simple_resize'</span>):
            <span class="pl-s1">img_resized</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, <span class="pl-s1">target_shape</span>)

            <span class="pl-s1">img_resized</span>.<span class="pl-en">set_shape</span>([<span class="pl-s1">target_shape</span>[<span class="pl-c1">0</span>], <span class="pl-s1">target_shape</span>[<span class="pl-c1">1</span>], <span class="pl-s1">img_resized</span>.<span class="pl-en">get_shape</span>()[<span class="pl-c1">2</span>]])

            <span class="pl-k">return</span> <span class="pl-s1">img_resized</span>, <span class="pl-s1">target_shape</span>

    <span class="pl-c"># 3 cases</span>
    <span class="pl-s1">pad_image</span>, (<span class="pl-s1">new_h</span>, <span class="pl-s1">new_w</span>) <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">case</span>(
        {  <span class="pl-c"># case 1 : new_w &gt;= target_w</span>
            <span class="pl-s1">tf</span>.<span class="pl-en">logical_and</span>(<span class="pl-s1">tf</span>.<span class="pl-en">greater_equal</span>(<span class="pl-s1">ratio</span>, <span class="pl-s1">target_ratio</span>),
                           <span class="pl-s1">tf</span>.<span class="pl-en">greater_equal</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">target_w</span>)): <span class="pl-s1">simple_resize</span>,
            <span class="pl-c"># case 2 : new_w &gt;= target_w/2 &amp; new_w &lt; target_w &amp; ratio &lt; target_ratio</span>
            <span class="pl-s1">tf</span>.<span class="pl-en">logical_and</span>(<span class="pl-s1">tf</span>.<span class="pl-en">less</span>(<span class="pl-s1">ratio</span>, <span class="pl-s1">target_ratio</span>),
                           <span class="pl-s1">tf</span>.<span class="pl-en">logical_and</span>(<span class="pl-s1">tf</span>.<span class="pl-en">greater_equal</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">divide</span>(<span class="pl-s1">target_w</span>, <span class="pl-c1">2</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)),
                                          <span class="pl-s1">tf</span>.<span class="pl-en">less</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">target_w</span>))): <span class="pl-s1">pad_fn</span>,
            <span class="pl-c"># case 3 : new_w &lt; target_w/2 &amp; new_w &lt; target_w &amp; ratio &lt; target_ratio</span>
            <span class="pl-s1">tf</span>.<span class="pl-en">logical_and</span>(<span class="pl-s1">tf</span>.<span class="pl-en">less</span>(<span class="pl-s1">ratio</span>, <span class="pl-s1">target_ratio</span>),
                           <span class="pl-s1">tf</span>.<span class="pl-en">logical_and</span>(<span class="pl-s1">tf</span>.<span class="pl-en">less</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">target_w</span>),
                                          <span class="pl-s1">tf</span>.<span class="pl-en">less</span>(<span class="pl-s1">new_w</span>, <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">divide</span>(<span class="pl-s1">target_w</span>, <span class="pl-c1">2</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)))): <span class="pl-s1">replicate_fn</span>
        },
        <span class="pl-s1">default</span><span class="pl-c1">=</span><span class="pl-s1">simple_resize</span>, <span class="pl-s1">exclusive</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)

    <span class="pl-k">return</span> <span class="pl-s1">pad_image</span>, <span class="pl-s1">new_w</span>  <span class="pl-c"># new_w = image width used for computing sequence lengths</span>


<span class="pl-k">def</span> <span class="pl-en">preprocess_image_for_prediction</span>(<span class="pl-s1">fixed_height</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">32</span>, <span class="pl-s1">min_width</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-c1">8</span>):
    <span class="pl-s">"""</span>
<span class="pl-s">    Input function to use when exporting the model for making predictions (see estimator.export_savedmodel)</span>
<span class="pl-s">    :param fixed_height: height of the input image after resizing</span>
<span class="pl-s">    :param min_width: minimum width of image after resizing</span>
<span class="pl-s">    :return:</span>
<span class="pl-s">    """</span>

    <span class="pl-k">def</span> <span class="pl-en">serving_input_fn</span>():
        <span class="pl-c"># define placeholder for input image</span>
        <span class="pl-s1">image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">placeholder</span>(<span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">float32</span>, <span class="pl-s1">shape</span><span class="pl-c1">=</span>[<span class="pl-c1">None</span>, <span class="pl-c1">None</span>, <span class="pl-c1">1</span>])

        <span class="pl-s1">shape</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">shape</span>(<span class="pl-s1">image</span>)
        <span class="pl-c"># Assert shape is h x w x c with c = 1</span>

        <span class="pl-s1">ratio</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">divide</span>(<span class="pl-s1">shape</span>[<span class="pl-c1">1</span>], <span class="pl-s1">shape</span>[<span class="pl-c1">0</span>])
        <span class="pl-s1">increment</span> <span class="pl-c1">=</span> <span class="pl-v">CONST</span>.<span class="pl-v">DIMENSION_REDUCTION_W_POOLING</span>
        <span class="pl-s1">new_width</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cast</span>(<span class="pl-s1">tf</span>.<span class="pl-en">round</span>((<span class="pl-s1">ratio</span> <span class="pl-c1">*</span> <span class="pl-s1">fixed_height</span>) <span class="pl-c1">/</span> <span class="pl-s1">increment</span>) <span class="pl-c1">*</span> <span class="pl-s1">increment</span>, <span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>)

        <span class="pl-s1">resized_image</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">cond</span>(<span class="pl-s1">new_width</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">tf</span>.<span class="pl-en">constant</span>(<span class="pl-s1">min_width</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">int32</span>),
                                <span class="pl-s1">true_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span>(<span class="pl-s1">fixed_height</span>, <span class="pl-s1">min_width</span>)),
                                <span class="pl-s1">false_fn</span><span class="pl-c1">=</span><span class="pl-k">lambda</span>: <span class="pl-s1">tf</span>.<span class="pl-s1">image</span>.<span class="pl-en">resize_images</span>(<span class="pl-s1">image</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span>(<span class="pl-s1">fixed_height</span>, <span class="pl-s1">new_width</span>))
                                )

        <span class="pl-c"># Features to serve</span>
        <span class="pl-s1">features</span> <span class="pl-c1">=</span> {<span class="pl-s">'images'</span>: <span class="pl-s1">resized_image</span>[<span class="pl-c1">None</span>],  <span class="pl-c"># cast to 1 x h x w x c</span>
                    <span class="pl-s">'images_widths'</span>: <span class="pl-s1">new_width</span>[<span class="pl-c1">None</span>]  <span class="pl-c"># cast to tensor</span>
                    }

        <span class="pl-c"># Inputs received</span>
        <span class="pl-s1">receiver_inputs</span> <span class="pl-c1">=</span> {<span class="pl-s">'images'</span>: <span class="pl-s1">image</span>}

        <span class="pl-k">return</span> <span class="pl-s1">tf</span>.<span class="pl-s1">estimator</span>.<span class="pl-s1">export</span>.<span class="pl-v">ServingInputReceiver</span>(<span class="pl-s1">features</span>, <span class="pl-s1">receiver_inputs</span>)

    <span class="pl-k">return</span> <span class="pl-s1">serving_input_fn</span></pre></div>
<p dir="auto">log<br>
tensorflow1.4</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="INFO:tensorflow:Using config: {'_model_dir': 'models_vgg_100K_no_eval', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': gpu_options {
  per_process_gpu_memory_fraction: 0.6
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_service': None, '_cluster_spec': &lt;tensorflow.python.training.server_lib.ClusterSpec object at 0x000002BAAA7A6780&gt;, '_task_type': 'worker', '_task_id': 0, '_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
INFO:tensorflow:Starting evaluation at 2017-11-28-12:21:42
INFO:tensorflow:Restoring parameters from model_test\model.ckpt-54692
2017-11-28 20:22:04.720980: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.236689657]
INFO:tensorflow:Evaluation [1/3]
2017-11-28 20:28:32.360331: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.238805175]
INFO:tensorflow:Evaluation [2/3]
2017-11-28 20:35:41.020994: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.237995088]
INFO:tensorflow:Evaluation [3/3]
INFO:tensorflow:Finished evaluation at 2017-11-28-12:43:21
INFO:tensorflow:Saving dict for global step 54692: eval/CER = 0.0108218, eval/accuracy = 0.929688, global_step = 54692, loss = 0.23783
time:1306.1133954524994
model: model_test\model.ckpt-54692 Evaluation results: {'eval/CER': 0.01082176, 'eval/accuracy': 0.9296875, 'loss': 0.23782997, 'global_step': 54692}"><pre class="notranslate">INFO:tensorflow:Using config: {<span class="pl-s"><span class="pl-pds">'</span>_model_dir<span class="pl-pds">'</span></span>: <span class="pl-s"><span class="pl-pds">'</span>models_vgg_100K_no_eval<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>_tf_random_seed<span class="pl-pds">'</span></span>: None, <span class="pl-s"><span class="pl-pds">'</span>_save_summary_steps<span class="pl-pds">'</span></span>: 100, <span class="pl-s"><span class="pl-pds">'</span>_save_checkpoints_steps<span class="pl-pds">'</span></span>: None, <span class="pl-s"><span class="pl-pds">'</span>_save_checkpoints_secs<span class="pl-pds">'</span></span>: 600, <span class="pl-s"><span class="pl-pds">'</span>_session_config<span class="pl-pds">'</span></span>: gpu_options {
  per_process_gpu_memory_fraction: 0.6
}
, <span class="pl-s"><span class="pl-pds">'</span>_keep_checkpoint_max<span class="pl-pds">'</span></span>: 5, <span class="pl-s"><span class="pl-pds">'</span>_keep_checkpoint_every_n_hours<span class="pl-pds">'</span></span>: 10000, <span class="pl-s"><span class="pl-pds">'</span>_log_step_count_steps<span class="pl-pds">'</span></span>: 100, <span class="pl-s"><span class="pl-pds">'</span>_service<span class="pl-pds">'</span></span>: None, <span class="pl-s"><span class="pl-pds">'</span>_cluster_spec<span class="pl-pds">'</span></span>: <span class="pl-k">&lt;</span>tensorflow.python.training.server_lib.ClusterSpec object at 0x000002BAAA7A<span class="pl-k">6780&gt;</span>, <span class="pl-s"><span class="pl-pds">'</span>_task_type<span class="pl-pds">'</span></span>: <span class="pl-s"><span class="pl-pds">'</span>worker<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>_task_id<span class="pl-pds">'</span></span>: 0, <span class="pl-s"><span class="pl-pds">'</span>_master<span class="pl-pds">'</span></span>: <span class="pl-s"><span class="pl-pds">'</span><span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>_is_chief<span class="pl-pds">'</span></span>: True, <span class="pl-s"><span class="pl-pds">'</span>_num_ps_replicas<span class="pl-pds">'</span></span>: 0, <span class="pl-s"><span class="pl-pds">'</span>_num_worker_replicas<span class="pl-pds">'</span></span>: 1}
INFO:tensorflow:Starting evaluation at 2017-11-28-12:21:42
INFO:tensorflow:Restoring parameters from model_test<span class="pl-cce">\m</span>odel.ckpt-54692
2017-11-28 20:22:04.720980: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.236689657]
INFO:tensorflow:Evaluation [1/3]
2017-11-28 20:28:32.360331: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.238805175]
INFO:tensorflow:Evaluation [2/3]
2017-11-28 20:35:41.020994: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.237995088]
INFO:tensorflow:Evaluation [3/3]
INFO:tensorflow:Finished evaluation at 2017-11-28-12:43:21
INFO:tensorflow:Saving dict <span class="pl-k">for</span> global step 54692: eval/CER = 0.0108218, eval/accuracy = 0.929688, global_step = 54692, loss = 0.23783
time:1306.1133954524994
model: model_test<span class="pl-cce">\m</span>odel.ckpt-54692 Evaluation results: {<span class="pl-s"><span class="pl-pds">'</span>eval/CER<span class="pl-pds">'</span></span>: 0.01082176, <span class="pl-s"><span class="pl-pds">'</span>eval/accuracy<span class="pl-pds">'</span></span>: 0.9296875, <span class="pl-s"><span class="pl-pds">'</span>loss<span class="pl-pds">'</span></span>: 0.23782997, <span class="pl-s"><span class="pl-pds">'</span>global_step<span class="pl-pds">'</span></span>: 54692}</pre></div>
<p dir="auto">tensorflow 1.3</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="INFO:tensorflow:Using config: {'_model_dir': 'models_vgg_100K_no_eval', '_tf_random_seed': 1, '_save_summary_steps': 100, '_save_checkpoints_secs': 600, '_save_checkpoints_steps': None, '_session_config': gpu_options {
  per_process_gpu_memory_fraction: 0.6
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100}
INFO:tensorflow:Starting evaluation at 2017-11-28-12:49:50
INFO:tensorflow:Restoring parameters from model_test\model.ckpt-54692
2017-11-28 20:50:12.841210: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.17519826]
INFO:tensorflow:Evaluation [1/3]
2017-11-28 20:51:03.366275: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.2987892]
INFO:tensorflow:Evaluation [2/3]
2017-11-28 20:51:49.843030: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] * Loss : [0.20660429]
INFO:tensorflow:Evaluation [3/3]
INFO:tensorflow:Finished evaluation at 2017-11-28-12:52:19
INFO:tensorflow:Saving dict for global step 54692: eval/CER = 0.01188, eval/accuracy = 0.924479, global_step = 54692, loss = 0.226864
time:157.26274514198303
model: model_test\model.ckpt-54692 Evaluation results: {'eval/CER': 0.011879961, 'eval/accuracy': 0.92447919, 'loss': 0.22686392, 'global_step': 54692}"><pre class="notranslate">INFO:tensorflow:Using config: {<span class="pl-s"><span class="pl-pds">'</span>_model_dir<span class="pl-pds">'</span></span>: <span class="pl-s"><span class="pl-pds">'</span>models_vgg_100K_no_eval<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>_tf_random_seed<span class="pl-pds">'</span></span>: 1, <span class="pl-s"><span class="pl-pds">'</span>_save_summary_steps<span class="pl-pds">'</span></span>: 100, <span class="pl-s"><span class="pl-pds">'</span>_save_checkpoints_secs<span class="pl-pds">'</span></span>: 600, <span class="pl-s"><span class="pl-pds">'</span>_save_checkpoints_steps<span class="pl-pds">'</span></span>: None, <span class="pl-s"><span class="pl-pds">'</span>_session_config<span class="pl-pds">'</span></span>: gpu_options {
  per_process_gpu_memory_fraction: 0.6
}
, <span class="pl-s"><span class="pl-pds">'</span>_keep_checkpoint_max<span class="pl-pds">'</span></span>: 5, <span class="pl-s"><span class="pl-pds">'</span>_keep_checkpoint_every_n_hours<span class="pl-pds">'</span></span>: 10000, <span class="pl-s"><span class="pl-pds">'</span>_log_step_count_steps<span class="pl-pds">'</span></span>: 100}
INFO:tensorflow:Starting evaluation at 2017-11-28-12:49:50
INFO:tensorflow:Restoring parameters from model_test<span class="pl-cce">\m</span>odel.ckpt-54692
2017-11-28 20:50:12.841210: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.17519826]
INFO:tensorflow:Evaluation [1/3]
2017-11-28 20:51:03.366275: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.2987892]
INFO:tensorflow:Evaluation [2/3]
2017-11-28 20:51:49.843030: I C:<span class="pl-cce">\t</span>f_jenkins<span class="pl-cce">\h</span>ome<span class="pl-cce">\w</span>orkspace<span class="pl-cce">\r</span>el-win<span class="pl-cce">\M\w</span>indows<span class="pl-cce">\P</span>Y<span class="pl-cce">\3</span>6<span class="pl-cce">\t</span>ensorflow<span class="pl-cce">\c</span>ore<span class="pl-cce">\k</span>ernels<span class="pl-cce">\l</span>ogging_ops.cc:79] <span class="pl-k">*</span> Loss <span class="pl-c1">:</span> [0.20660429]
INFO:tensorflow:Evaluation [3/3]
INFO:tensorflow:Finished evaluation at 2017-11-28-12:52:19
INFO:tensorflow:Saving dict <span class="pl-k">for</span> global step 54692: eval/CER = 0.01188, eval/accuracy = 0.924479, global_step = 54692, loss = 0.226864
time:157.26274514198303
model: model_test<span class="pl-cce">\m</span>odel.ckpt-54692 Evaluation results: {<span class="pl-s"><span class="pl-pds">'</span>eval/CER<span class="pl-pds">'</span></span>: 0.011879961, <span class="pl-s"><span class="pl-pds">'</span>eval/accuracy<span class="pl-pds">'</span></span>: 0.92447919, <span class="pl-s"><span class="pl-pds">'</span>loss<span class="pl-pds">'</span></span>: 0.22686392, <span class="pl-s"><span class="pl-pds">'</span>global_step<span class="pl-pds">'</span></span>: 54692}</pre></div>
<p dir="auto"><em>Please make sure that this is a bug. As per our <a href="https://github.com/tensorflow/tensorflow/blob/master/ISSUES.md">GitHub Policy</a>, we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:bug_template</em></p>
<p dir="auto"><strong>System information</strong></p>
<ul dir="auto">
<li>
<p dir="auto">Have I written custom code (as opposed to using a stock example script provided in TensorFlow):</p>
</li>
<li>
<p dir="auto">OS Platform and Distribution (e.g., Linux Ubuntu 16.04):</p>
</li>
</ul>
<p dir="auto">Linux Ubuntu 16.04.3</p>
<ul dir="auto">
<li>Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device:</li>
<li>TensorFlow installed from (source or binary):</li>
</ul>
<p dir="auto">source</p>
<ul dir="auto">
<li>TensorFlow version (use command below):</li>
</ul>
<p dir="auto">ToT</p>
<ul dir="auto">
<li>Python version:</li>
</ul>
<p dir="auto">3.6</p>
<ul dir="auto">
<li>Bazel version (if compiling from source):</li>
</ul>
<p dir="auto">19.04</p>
<ul dir="auto">
<li>GCC/Compiler version (if compiling from source):</li>
</ul>
<p dir="auto">5.4.0</p>
<ul dir="auto">
<li>CUDA/cuDNN version:</li>
</ul>
<p dir="auto">10.0/7.4</p>
<ul dir="auto">
<li>GPU model and memory:</li>
</ul>
<p dir="auto">You can collect some of this information using our environment capture<br>
<a href="https://github.com/tensorflow/tensorflow/tree/master/tools/tf_env_collect.sh">script</a><br>
You can also obtain the TensorFlow version with: 1. TF 1.0: <code class="notranslate">python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)"</code> 2. TF 2.0: <code class="notranslate">python -c "import tensorflow as tf; print(tf.version.GIT_VERSION, tf.version.VERSION)"</code></p>
<p dir="auto"><strong>Describe the current behavior</strong></p>
<p dir="auto">When XLA is off,  the BERT compiles fine.</p>
<p dir="auto"><strong>Describe the expected behavior</strong></p>
<p dir="auto"><strong>Code to reproduce the issue</strong><br>
Provide a reproducible test case that is the bare minimum necessary to generate the problem.</p>
<p dir="auto">The following code pattern in the TF graph will expose the problem,</p>
<p dir="auto">op0:  Node "VarHandleOp"<br>
op1:  Node "Switch" op0, pred<br>
op2:  Node "ReadVariableOp" op0<br>
op3:  Node "ReadVariableOp" op1</p>
<p dir="auto">Whem op2 and op3 are clustered together in XLA,  the inputs op0 and op1 are<br>
considered resource arguments, and they happen to map the the same resource<br>
op0, and lead to the error  "Duplicate variable passed to XLA cluster" reported at<br>
line 135, xla_launch_util.cc.</p>
<p dir="auto">I am worarounding the problem by placing constraint on clustable nodes in<br>
mark_for_compilation_pass.cc, so that nodes with resource input from a "Switch"<br>
node be rejected for clustering.  Some people suggest that it may be better to fix<br>
the problem where the problem is reported.</p>
<p dir="auto"><strong>Other info / logs</strong><br>
Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached.</p>