'Builds a training loop for this component.
This loop repeatedly evaluates the network and computes the loss, but it
does not advance using the predictions of the network. Instead, it advances
using the oracle defined in the underlying transition system. The final
state will always correspond to the gold annotation.
Args:
state: MasterState from the \'AdvanceMaster\' op that advances the
underlying master to this component.
network_states: NetworkState object containing component TensorArrays.
Returns:
(state, cost, correct, total) -- These are TF ops corresponding to
the final state after unrolling, the total cost, the total number of
correctly predicted actions, and the total number of actions.'

def build_greedy_training(self, state, network_states):

    logging.info('Building    component:    %s', self.spec.name)
    with tf.control_dependencies([tf.assert_equal(self.training_beam_size, 1)]):
        stride = (state.current_batch_size * self.training_beam_size)
    cost = tf.constant(0.0)
    correct = tf.constant(0)
    total = tf.constant(0)
    def cond(handle, *_):
        all_final = dragnn_ops.emit_all_final(handle, component=self.name)
        return tf.logical_not(tf.reduce_all(all_final))
    def body(handle, cost, correct, total, *arrays):
        'Runs    the    network    and    advances    the    state    by    a    step.'
        with tf.control_dependencies(([handle, cost, correct, total] + [x.flow for x in arrays])):
            updated_state = MasterState(handle, state.current_batch_size)
            network_tensors = self._feedforward_unit(updated_state, arrays, network_states, stride, during_training=True)
            next_arrays = update_tensor_arrays(network_tensors, arrays)
            with tf.control_dependencies([x.flow for x in next_arrays]):
                with tf.name_scope('compute_loss'):
                    gold = dragnn_ops.emit_oracle_labels(handle, component=self.name)
                    gold.set_shape([None])
                    valid = tf.greater(gold, (-1))
                    valid_ix = tf.reshape(tf.where(valid), [(-1)])
                    gold = tf.gather(gold, valid_ix)
                    logits = self.network.get_logits(network_tensors)
                    logits = tf.gather(logits, valid_ix)
                    cost += tf.reduce_sum(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.cast(gold, tf.int64), logits=logits))
                    if (self.eligible_for_self_norm and (self.master.hyperparams.self_norm_alpha > 0)):
                        log_z = tf.reduce_logsumexp(logits, [1])
                        cost += (self.master.hyperparams.self_norm_alpha * tf.nn.l2_loss(log_z))
                    correct += tf.reduce_sum(tf.to_int32(tf.nn.in_top_k(logits, gold, 1)))
                    total += tf.size(gold)
            with tf.control_dependencies([cost, correct, total, gold]):
                handle = dragnn_ops.advance_from_oracle(handle, component=self.name)
            return ([handle, cost, correct, total] + next_arrays)
    with tf.name_scope((self.name + '/train_state')):
        init_arrays = []
        for layer in self.network.layers:
            init_arrays.append(layer.create_array(state.current_batch_size))
    output = tf.while_loop(cond, body, ([state.handle, cost, correct, total] + init_arrays), name=('train_%s' % self.name))
    state.handle = output[0]
    correct = output[2]
    total = output[3]
    arrays = output[4:]
    cost = output[1]
    network_state = network_states[self.name]
    with tf.name_scope((self.name + '/stored_act')):
        for (index, layer) in enumerate(self.network.layers):
            network_state.activations[layer.name] = network_units.StoredActivations(array=arrays[index])
    with tf.control_dependencies([tf.assert_greater(total, 0)]):
        cost /= tf.to_float(total)
    cost = self.add_regularizer(cost)
    with tf.control_dependencies([x.flow for x in arrays]):
        return (tf.identity(state.handle), cost, correct, total)
