def METHOD_NAME(self, state, action, target=False):
    T = state[:, 6 : 7]
    gt = state[:, 3 : 6].float() / 255
    canvas0 = state[:, :3].float() / 255
    with torch.no_grad(): # model free
        canvas1 = decode(action, canvas0)
    gan_reward = cal_reward(canvas1, gt) - cal_reward(canvas0, gt) # (batchsize, 64)
    # L2_reward = ((canvas0 - gt) ** 2).mean(1).mean(1).mean(1) - ((canvas1 - gt) ** 2).mean(1).mean(1).mean(1)        
    coord_ = coord.expand(state.shape[0], 2, 128, 128)
    merged_state = torch.cat([canvas0, gt, (T + 1).float() / self.max_step, coord_], 1)
    if target:
        Q = self.critic_target([merged_state, action])
        return Q, gan_reward
    else:
        Q = self.critic([merged_state, action])
        if self.log % 20 == 0:
            self.writer.add_scalar('train/expect_reward', Q.mean(), self.log)
            self.writer.add_scalar('train/gan_reward', gan_reward.mean(), self.log)
        return Q, gan_reward