code: def _define_train(
      train_env,
      ppo_hparams,
      eval_env_fn=None,
      sampling_temp=1.0,
      **collect_kwargs
  ):
    
    memory, collect_summary, train_initialization = (
        _define_collect(
            train_env,
            ppo_hparams,
            "ppo_train",
            eval_phase=False,
            sampling_temp=sampling_temp,
            **collect_kwargs))
    ppo_summary = ppo.define_ppo_epoch(
        memory, ppo_hparams, train_env.action_space, train_env.batch_size)
    train_summary = tf.summary.merge([collect_summary, ppo_summary])
  
    if ppo_hparams.eval_every_epochs:
      # TODO(koz4k): Do we need this at all?
      assert eval_env_fn is not None
      eval_env = eval_env_fn(in_graph=True)
      (_, eval_collect_summary, eval_initialization) = (
          _define_collect(
              eval_env,
              ppo_hparams,
              "ppo_eval",
              eval_phase=True,
              sampling_temp=0.0,
              **collect_kwargs))
      return (train_summary, eval_collect_summary, (train_initialization,
                                                    eval_initialization))
    else:
      return (train_summary, None, (train_initialization,))
docs: Define the training setup.