def __init__(self, env, handle, name,
                 batch_size=32, unroll_step=8, reward_decay=0.99, learning_rate=1e-4,
                 train_freq=1, memory_size=20000, target_update=2000, eval_obs=None,
                 use_dueling=True, use_double=True, use_episode_train=False,
                 custom_view_space=None, custom_feature_space=None):
        """init a model

        Parameters
        ----------
        env: Environment
            environment
        handle: Handle (ctypes.c_int32)
            handle of this group, can be got by env.get_handles
        name: str
            name of this model
        learning_rate: float
        batch_size: int
        reward_decay: float
            reward_decay in TD
        train_freq: int
            mean training times of a sample
        target_update: int
            target will update every target_update batches
        memory_size: int
            weight of entropy loss in total loss
        eval_obs: numpy array
            evaluation set of observation
        use_dueling: bool
            whether use dueling q network
        use_double: bool
            whether use double q network
        custom_feature_space: tuple
            customized feature space
        custom_view_space: tuple
            customized feature space
        """
        TFBaseModel.__init__(self, env, handle, name, "tfdrqn")
        # ======================== set config  ========================
        self.env = env
        self.handle = handle
        self.view_space = custom_view_space or env.get_view_space(handle)
        self.feature_space = custom_feature_space or env.get_feature_space(handle)
        self.num_actions = env.get_action_space(handle)[0]

        self.batch_size   = batch_size
        self.unroll_step  = unroll_step
        self.handle = handle
        self.name = name
        self.learning_rate= learning_rate
        self.train_freq   = train_freq   # train time of every sample (s,a,r,s')
        self.target_update= target_update # target network update frequency
        self.eval_obs = eval_obs

        self.use_dueling  = use_dueling
        self.use_double   = use_double
        self.use_episode_train = use_episode_train
        self.skip_error   = 0
        self.pad_before_len = unroll_step - 1

        self.agent_states = {}
        self.train_ct = 0

        # ======================= build network =======================
        # input place holder
        self.target = tf.placeholder(tf.float32, [None])

        self.input_view    = tf.placeholder(tf.float32, (None,) + self.view_space, name="input_view")
        self.input_feature = tf.placeholder(tf.float32, (None,) + self.feature_space, name="input_feature")
        self.action = tf.placeholder(tf.int32, [None], name="action")
        self.mask   = tf.placeholder(tf.float32, [None], name="mask")

        self.batch_size_ph   = tf.placeholder(tf.int32, [])
        self.unroll_step_ph = tf.placeholder(tf.int32, [])

        # build graph
        with tf.variable_scope(self.name):
            with tf.variable_scope("eval_net_scope"):
                self.eval_scope_name   = tf.get_variable_scope().name
                self.qvalues, self.state_in, self.rnn_state = \
                    self._create_network(self.input_view, self.input_feature)

            with tf.variable_scope("target_net_scope"):
                self.target_scope_name = tf.get_variable_scope().name
                self.target_qvalues, self.target_state_in, self.target_rnn_state = \
                    self._create_network(self.input_view, self.input_feature)

        # loss
        self.gamma = reward_decay
        self.actions_onehot = tf.one_hot(self.action, self.num_actions)
        self.td_error = tf.square(
                self.target - tf.reduce_sum(tf.multiply(self.actions_onehot, self.qvalues), axis=1)
            )
        #self.loss = tf.reduce_mean(self.td_error)
        self.loss = tf.reduce_sum(self.td_error * self.mask) / tf.reduce_sum(self.mask)

        # train op (clip gradient)
        optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
        gradients, variables = zip(*optimizer.compute_gradients(self.loss))
        gradients, _ = tf.clip_by_global_norm(gradients, 10.0)
        self.train_op = optimizer.apply_gradients(zip(gradients, variables))

        # target network update op
        self.update_target_op = []
        t_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, self.target_scope_name)
        e_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, self.eval_scope_name)
        for i in range(len(t_params)):
            self.update_target_op.append(tf.assign(t_params[i], e_params[i]))

        # init tensorflow session
        config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
        config.gpu_options.allow_growth = True
        self.sess = tf.Session(config=config)
        self.sess.run(tf.global_variables_initializer())

        # init memory buffers
        self.memory_size = memory_size
        self.replay_buffer_lens = collections.deque(maxlen=memory_size)
        self.replay_buffer = collections.deque(maxlen=memory_size)
        # item format [views, features, actions, rewards, terminals, masks, len]

        # init training buffers
        self.view_buf = np.empty((1,) + self.view_space)
        self.feature_buf = np.empty((1,) + self.feature_space)
        self.action_buf, self.reward_buf = np.empty(1, dtype=np.int32), np.empty(1)
        self.terminal_buf = np.empty(1, dtype=np.bool)
init a model

        Parameters
        ----------
        env: Environment
            environment
        handle: Handle (ctypes.c_int32)
            handle of this group, can be got by env.get_handles
        name: str
            name of this model
        learning_rate: float
        batch_size: int
        reward_decay: float
            reward_decay in TD
        train_freq: int
            mean training times of a sample
        target_update: int
            target will update every target_update batches
        memory_size: int
            weight of entropy loss in total loss
        eval_obs: numpy array
            evaluation set of observation
        use_dueling: bool
            whether use dueling q network
        use_double: bool
            whether use double q network
        custom_feature_space: tuple
            customized feature space
        custom_view_space: tuple
            customized feature space
        
python/magent/builtin/tf_model/drqn.py