'Network training loop.'

def train_model(self, sess, max_iters):

    data_layer = get_data_layer(self.roidb, self.imdb.num_classes)
    rpn_cls_score = tf.reshape(self.net.get_output('rpn_cls_score_reshape'), [(-1), 2])
    rpn_label = tf.reshape(self.net.get_output('rpn-data')[0], [(-1)])
    rpn_cls_score = tf.reshape(tf.gather(rpn_cls_score, tf.where(tf.not_equal(rpn_label, (-1)))), [(-1), 2])
    rpn_label = tf.reshape(tf.gather(rpn_label, tf.where(tf.not_equal(rpn_label, (-1)))), [(-1)])
    rpn_cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=rpn_cls_score, labels=rpn_label))
    rpn_bbox_pred = self.net.get_output('rpn_bbox_pred')
    rpn_bbox_targets = tf.transpose(self.net.get_output('rpn-data')[1], [0, 2, 3, 1])
    rpn_bbox_inside_weights = tf.transpose(self.net.get_output('rpn-data')[2], [0, 2, 3, 1])
    rpn_bbox_outside_weights = tf.transpose(self.net.get_output('rpn-data')[3], [0, 2, 3, 1])
    rpn_smooth_l1 = self._modified_smooth_l1(3.0, rpn_bbox_pred, rpn_bbox_targets, rpn_bbox_inside_weights, rpn_bbox_outside_weights)
    rpn_loss_box = tf.reduce_mean(tf.reduce_sum(rpn_smooth_l1, reduction_indices=[1, 2, 3]))
    cls_score = self.net.get_output('cls_score')
    label = tf.reshape(self.net.get_output('roi-data')[1], [(-1)])
    cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=cls_score, labels=label))
    bbox_pred = self.net.get_output('bbox_pred')
    bbox_targets = self.net.get_output('roi-data')[2]
    bbox_inside_weights = self.net.get_output('roi-data')[3]
    bbox_outside_weights = self.net.get_output('roi-data')[4]
    smooth_l1 = self._modified_smooth_l1(1.0, bbox_pred, bbox_targets, bbox_inside_weights, bbox_outside_weights)
    loss_box = tf.reduce_mean(tf.reduce_sum(smooth_l1, reduction_indices=[1]))
    loss = (((cross_entropy + loss_box) + rpn_cross_entropy) + rpn_loss_box)
    global_step = tf.Variable(0, trainable=False)
    lr = tf.train.exponential_decay(cfg.TRAIN.LEARNING_RATE, global_step, cfg.TRAIN.STEPSIZE, 0.1, staircase=True)
    momentum = cfg.TRAIN.MOMENTUM
    train_op = tf.train.MomentumOptimizer(lr, momentum).minimize(loss, global_step=global_step)
    sess.run(tf.global_variables_initializer())
    if (self.pretrained_model is not None):
        print 'Loading    pretrained    model    weights    from    {:s}'.format(self.pretrained_model)
        self.net.load(self.pretrained_model, sess, self.saver, True)
    last_snapshot_iter = (-1)
    timer = Timer()
    for iter in range(max_iters):
        blobs = data_layer.forward()
        feed_dict = {self.net.data: blobs['data'], self.net.im_info: blobs['im_info'], self.net.keep_prob: 0.5, self.net.gt_boxes: blobs['gt_boxes']}
        run_options = None
        run_metadata = None
        if cfg.TRAIN.DEBUG_TIMELINE:
            run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
            run_metadata = tf.RunMetadata()
        timer.tic()
        (rpn_loss_cls_value, rpn_loss_box_value, loss_cls_value, loss_box_value, _) = sess.run([rpn_cross_entropy, rpn_loss_box, cross_entropy, loss_box, train_op], feed_dict=feed_dict, options=run_options, run_metadata=run_metadata)
        timer.toc()
        if cfg.TRAIN.DEBUG_TIMELINE:
            trace = timeline.Timeline(step_stats=run_metadata.step_stats)
            trace_file = open((str(long((time.time() * 1000))) + '-train-timeline.ctf.json'), 'w')
            trace_file.write(trace.generate_chrome_trace_format(show_memory=False))
            trace_file.close()
        if (((iter + 1) % cfg.TRAIN.DISPLAY) == 0):
            print ('iter:    %d    /    %d,    total    loss:    %.4f,    rpn_loss_cls:    %.4f,    rpn_loss_box:    %.4f,    loss_cls:    %.4f,    loss_box:    %.4f,    lr:    %f' % ((iter + 1), max_iters, (((rpn_loss_cls_value + rpn_loss_box_value) + loss_cls_value) + loss_box_value), rpn_loss_cls_value, rpn_loss_box_value, loss_cls_value, loss_box_value, lr.eval()))
            print 'speed:    {:.3f}s    /    iter'.format(timer.average_time)
        if (((iter + 1) % cfg.TRAIN.SNAPSHOT_ITERS) == 0):
            last_snapshot_iter = iter
            self.snapshot(sess, iter)
    if (last_snapshot_iter != iter):
        self.snapshot(sess, iter)
