def train(self, sample_buffer, print_every=1000):
        """feed new data sample and train

        Parameters
        ----------
        sample_buffer: magent.utility.EpisodesBuffer
            buffer contains samples

        Returns
        -------
        loss: list
            policy gradient loss, critic loss, entropy loss
        value: float
            estimated state value
        """
        # calc buffer size
        n = 0
        for episode in sample_buffer.episodes():
            if episode.terminal:
                n += len(episode.rewards)
            else:
                n += len(episode.rewards) - 1

        if n == 0:
            return [0.0, 0.0, 0.0], 0.0

        # resize to the new size
        self.view_buf.resize((n,) + self.view_space)
        self.feature_buf.resize((n,) + self.feature_space)
        self.action_buf.resize(n)
        self.value_buf.resize(n)
        self.advantage_buf.resize(n)
        view, feature = self.view_buf, self.feature_buf
        action, value = self.action_buf, self.value_buf
        advantage     = self.advantage_buf

        ct = 0
        gamma = self.reward_decay
        # collect episodes from multiple separate buffers to a continuous buffer

        for episode in sample_buffer.episodes():
            v, f, a, r = episode.views, episode.features, episode.actions, episode.rewards

            m = len(episode.rewards)
            self._reset_bind_size(m)
            data_batch = mx.io.DataBatch(data=[mx.nd.array(v), mx.nd.array(f)])
            self.model.forward(data_batch, is_train=False)
            value = self.model.get_outputs()[1].asnumpy().flatten()

            delta_t = np.empty(m)
            if episode.terminal:
                delta_t[:m-1] = r[:m-1] + gamma * value[1:m] - value[:m-1]
                delta_t[m-1]  = r[m-1]  + gamma * 0          - value[m-1]
            else:
                delta_t[:m-1] = r[:m-1] + gamma * value[1:m] - value[:m-1]
                m -= 1
                v, f, a = v[:-1], f[:-1], a[:-1]

            if m == 0:
                continue

            # discount advantage
            keep = 0
            for i in reversed(range(m)):
                keep = keep * gamma + delta_t[i]
                advantage[ct+i] = keep

            view[ct:ct+m] = v
            feature[ct:ct+m] = f
            action[ct:ct+m]  = a
            ct += m
        assert n == ct

        n = len(advantage)
        neg_advantage = -advantage

        neg_advs_np = np.zeros((n, self.num_actions), dtype=np.float32)
        neg_advs_np[np.arange(n), action] = neg_advantage
        neg_advs = mx.nd.array(neg_advs_np)

        # the grads of values are exactly negative advantages
        v_grads = mx.nd.array(self.value_coef * (neg_advantage[:, np.newaxis]))
        data_batch = mx.io.DataBatch(data=[mx.nd.array(view), mx.nd.array(feature)])
        self._reset_bind_size(n)
        self.model.forward(data_batch, is_train=True)
        self.model.backward(out_grads=[neg_advs, v_grads])
        self.model.update()
        log_policy, value, entropy_loss, _ = self.model.get_outputs()

        value = mx.nd.mean(value).asnumpy()[0]
        log_policy = log_policy.asnumpy()[np.arange(n), action]
        pg_loss = np.mean(neg_advantage * log_policy)
        entropy_loss = np.mean(entropy_loss.asnumpy())
        value_loss = self.value_coef * np.mean(np.square(advantage))

        print("sample %d  %.4f %.4f %.4f %.4f" % (n, pg_loss, value_loss, entropy_loss, value))
        return [pg_loss, value_loss, entropy_loss], value
feed new data sample and train

        Parameters
        ----------
        sample_buffer: magent.utility.EpisodesBuffer
            buffer contains samples

        Returns
        -------
        loss: list
            policy gradient loss, critic loss, entropy loss
        value: float
            estimated state value
        
python/magent/builtin/mx_model/a2c.py