def __init__(self, env, handle, name,
                 batch_size=64, learning_rate=1e-4, reward_decay=0.99,
                 train_freq=1, target_update=2000, memory_size=2 ** 20, eval_obs=None,
                 use_dueling=True, use_double=True, infer_batch_size=8192,
                 custom_view_space=None, custom_feature_space=None, num_gpu=1):
        """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
        num_gpu: int
            number of gpu
        infer_batch_size: int
            batch size while inferring actions
        custom_feature_space: tuple
            customized feature space
        custom_view_space: tuple
            customized feature space
        """
        MXBaseModel.__init__(self, env, handle, name, "mxdqn")
        # ======================== 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.infer_batch_size = infer_batch_size
        self.learning_rate = learning_rate
        self.train_freq    = train_freq      # train time of every sample (s,a,r,s')
        self.target_update = target_update   # update frequency of target network
        self.eval_obs      = eval_obs
        self.num_gpu       = num_gpu

        self.use_dueling  = use_dueling
        self.use_double   = use_double

        self.train_ct = 0

        # ======================= build network =======================
        self.ctx = self._get_ctx()
        if self.num_gpu > 1 and self.ctx == mx.gpu():
            self.ctx = []
            for i in range(self.num_gpu):
                self.ctx.append(mx.gpu(i))

        self.input_view = mx.sym.var("input_view")
        self.input_feature = mx.sym.var("input_feature")
        self.mask   = mx.sym.var("mask")
        self.action = mx.sym.var("action")
        self.target = mx.sym.var("target")

        self.qvalues = self._create_network(self.input_view, self.input_feature)
        self.gamma = reward_decay
        self.action_onehot = mx.sym.one_hot(self.action, depth=self.num_actions)
        td_error = mx.sym.square(self.target - mx.sym.sum(self.qvalues * self.action_onehot, axis=1))
        self.loss = mx.sym.sum(td_error * self.mask) / mx.sym.sum(self.mask)
        self.loss = mx.sym.MakeLoss(data=self.loss)

        self.out_qvalues = mx.sym.BlockGrad(self.qvalues)
        self.output = mx.sym.Group([self.out_qvalues, self.loss])

        self.model = mx.mod.Module(self.output,
                                   data_names=['input_view', 'input_feature'],
                                   label_names=['action', 'target', 'mask'], context=self.ctx)

        self.target_model = mx.mod.Module(self.qvalues,
                                          data_names=['input_view', 'input_feature'],
                                          label_names=[], context=self.ctx)

        # bind (set initial batch size)
        self.bind_size = batch_size
        self.model.bind(data_shapes=[('input_view', (batch_size,) + self.view_space),
                                     ('input_feature', (batch_size,) + self.feature_space)],
                        label_shapes=[('action', (batch_size,)),
                                      ('target', (batch_size,)),
                                      ('mask', (batch_size,))])
        self.target_model.bind(data_shapes=[('input_view', (batch_size,) + self.view_space),
                                            ('input_feature', (batch_size,) + self.feature_space)])

        # init params
        self.model.init_params(initializer=mx.init.Xavier())
        self.model.init_optimizer(optimizer='adam', optimizer_params={
            'learning_rate': learning_rate,
            'clip_gradient': 10.0})

        self._copy_network(self.target_model, self.model)

        # init replay buffers
        self.replay_buf_len = 0
        self.memory_size = memory_size
        self.replay_buf_view     = ReplayBuffer(shape=(memory_size,) + self.view_space)
        self.replay_buf_feature  = ReplayBuffer(shape=(memory_size,) + self.feature_space)
        self.replay_buf_action   = ReplayBuffer(shape=(memory_size,), dtype=np.int32)
        self.replay_buf_reward   = ReplayBuffer(shape=(memory_size,))
        self.replay_buf_terminal = ReplayBuffer(shape=(memory_size,), dtype=np.bool)
        self.replay_buf_mask     = ReplayBuffer(shape=(memory_size,))
        # if mask[i] == 0, then the item is used for padding, not for training

        # print("parameters", self.model.get_params())
        # mx.viz.plot_network(self.loss).view()
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
        num_gpu: int
            number of gpu
        infer_batch_size: int
            batch size while inferring actions
        custom_feature_space: tuple
            customized feature space
        custom_view_space: tuple
            customized feature space
        
python/magent/builtin/mx_model/dqn.py