Example #1
0
        static void _Main(string[] args)
        {
            int success_num;

            double      ITERATION = (3 * 10e5);
            double      GAMMA     = 0.95;
            CartPoleEnv env       = new CartPoleEnv(WinFormEnvViewer.Factory); //or AvaloniaEnvViewer.Factory

            env.Seed(0);
            Space      ob_space   = env.ObservationSpace;
            Policy_net Policy     = new Policy_net("policy", env);
            Policy_net Old_Policy = new Policy_net("old_policy", env);
            PPOTrain   PPO        = new PPOTrain(Policy, Old_Policy, gamma: GAMMA);
            Saver      saver      = tf.train.Saver();

            using (var sess = tf.Session())
            {
                writer = tf.summary.FileWriter("./log/test", sess.graph);
                sess.run(tf.global_variables_initializer());
                saver.restore(sess, "model/model.ckpt");
                obs         = env.reset();
                reward      = 0;
                success_num = 0;

                for (double iteration = 0; iteration < ITERATION; iteration++)
                {  // episode
                    run_policy_steps = 0;
                    env.render();
                    while (true)
                    {                                                            // run policy RUN_POLICY_STEPS which is much less than episode length
                        run_policy_steps += 1;
                        obs = np.stack(new[] { obs }).astype(dtype: np.float32); // prepare to feed placeholder Policy.obs
                        var(act, v_pred) = Policy.act(obs: obs, stochastic: false);

                        act    = act.item();
                        v_pred = v_pred.item();

                        observations.add(obs);
                        actions.add(act);
                        v_preds.add(v_pred);
                        rewards.add(reward);

                        var(next_obs, reward, done, info) = env.Step(act);

                        if (done)
                        {
                            v_preds_next = v_preds[1 :] + [0];  // next state of terminate state has 0 state value
Example #2
0
        public PPOTrain(Policy_net policy, Policy_net old_policy, double gamma = 0.95, double clip_value = 0.2, double c_1 = 1, double c_2 = 0.01)
        {
            /*
             * :param Policy:
             * :param Old_Policy:
             * :param gamma:
             * :param clip_value:
             * :param c_1: parameter for value difference
             * :param c_2: parameter for entropy bonus
             */
            Policy     = policy;
            Old_Policy = old_policy;
            this.gamma = gamma;
            List <IVariableV1> pi_trainable     = Policy.get_trainable_variables() as List <IVariableV1>;
            List <IVariableV1> old_pi_trainable = Old_Policy.get_trainable_variables();

            // assign_operations for (policy parameter values to old policy parameters
            // atribuir operações para valores de parâmetros de política a parâmetros de política antigos
            using (tf.variable_scope("assign_op"))
            {
                foreach ((RefVariable v_old, Tensor v) in zip(old_pi_trainable, pi_trainable))
                {
                    this.assign_ops.Add(tf.assign(v_old, v));
                }
            }
            // inputs for (train_op
            // inputs para train_op
            using (tf.variable_scope("train_inp"))
            {
                this.actions      = tf.placeholder(dtype: tf.int32, shape: (Unknown), name: "actions");
                this.rewards      = tf.placeholder(dtype: tf.float32, shape: (Unknown), name: "rewards");
                this.v_preds_next = tf.placeholder(dtype: tf.float32, shape: (Unknown), name: "v_preds_next");
                this.gaes         = tf.placeholder(dtype: tf.float32, shape: (Unknown), name: "gaes");
            }
            Tensor act_probs     = Policy.act_probs;
            Tensor act_probs_old = Old_Policy.act_probs;

            // probabilidades de ações que o agente executou com a política
            act_probs = act_probs * tf.one_hot(indices: this.actions, depth: act_probs.ToArray <double>().GetLength(1));
            act_probs = tf.reduce_sum(act_probs, axis: 1);

            // probabilidades de ações que o agente executou com a política antiga
            act_probs_old = act_probs_old * tf.one_hot(indices: this.actions, depth: act_probs_old.ToArray <double>().GetLength(1));
            act_probs_old = tf.reduce_sum(act_probs_old, axis: 1);

            using (tf.variable_scope("loss/clip"))
            {
                // ratios = tf.divide(act_probs, act_probs_old)
                Tensor ratios         = tf.exp(tf.log(act_probs) - tf.log(act_probs_old));
                Tensor clipped_ratios = tf.clip_by_value(ratios, clip_value_min: new Tensor(1 - clip_value), clip_value_max: new Tensor(1 + clip_value));
                loss_clip = tf.minimum(tf.multiply(this.gaes, ratios), tf.multiply(this.gaes, clipped_ratios));
                loss_clip = tf.reduce_mean(loss_clip);
                tf.summary.scalar("loss_clip", loss_clip);
            }
            // construct computation graph for (loss of value function
            // constrói gráfico de cálculo para perda da função de valor
            using (tf.variable_scope("loss/vf"))
            {
                Tensor v_preds = Policy.v_preds;
                loss_vf = tf.squared_difference(this.rewards + (gamma * this.v_preds_next), v_preds);
                loss_vf = tf.reduce_mean(loss_vf);
                tf.summary.scalar("loss_vf", loss_vf);
            }
            // construct computation graph for (loss of entropy bonus
            // construir gráfico de computação para perda de bônus de entropia
            using (tf.variable_scope("loss/entropy"))
            {
                entropy = -tf.reduce_sum(Policy.act_probs * tf.log(tf.clip_by_value(Policy.act_probs, new Tensor(1e-10), new Tensor(1.0))), axis: 1);
                entropy = tf.reduce_mean(entropy, axis: new[] { 0 });   // média de entropia de pi (obs)
                tf.summary.scalar("entropy", entropy);
            }
            using (tf.variable_scope("loss"))
            {
                loss = loss_clip - c_1 * loss_vf + c_2 * entropy;
                loss = -loss;  // minimize -loss == maximize loss
                tf.summary.scalar("loss", loss);
            }
            this.merged = tf.summary.merge_all();
            Optimizer optimizer = tf.train.AdamOptimizer(learning_rate: (float)1e-4, epsilon: (float)1e-5);

            this.train_op = optimizer.minimize(loss, var_list: pi_trainable);
        }
Example #3
0
        static void Main(string[] args)
        {
            List <NDArray> observations = new List <NDArray>();
            List <NDArray> actions      = new List <NDArray>();
            List <NDArray> v_preds      = new List <NDArray>();
            List <double>  rewards      = new List <double>();
            List <NDArray> v_preds_next = new List <NDArray>();
            List <NDArray> gaes         = new List <NDArray>();

            double EPISODES = 1e5;
            double GAMMA    = 0.95;

            CartPoleEnv env = new CartPoleEnv(WinFormEnvViewer.Factory);                          //or AvaloniaEnvViewer.Factory  // Instancia o ambiente CartPole

            env.Seed(0);                                                                          //
            Space      ob_space   = env.ObservationSpace;                                         // Descrevem o formato de observações válidas do espaço
            Policy_net Policy     = new Policy_net("policy", env);                                // Cria a rede de Politica
            Policy_net Old_Policy = new Policy_net("old_policy", env);                            // Cria a rede de politica antiga
            PPOTrain   PPO        = new PPOTrain(Policy, Old_Policy, gamma: GAMMA);
            Saver      saver      = tf.train.Saver();                                             //

            using (var sess = tf.Session())                                                       // Bloco da sessão
            {
                FileWriter writer = tf.summary.FileWriter("./log/train", sess.graph);             // Define diretório de logs
                sess.run(tf.global_variables_initializer());                                      // Inicializa as redes

                NDArray obs         = env.Reset();                                                // Resets o ambiente e obtêm a primeira observação
                double  reward      = 0;                                                          // Armazena as recompensas
                int     success_num = 0;                                                          // Contador de sucessos

                for (int episode = 0; episode < EPISODES; episode++)                              // Loop do episodio
                {
                    int run_policy_steps = 0;                                                     // Contador de passos em cada episodio
                    env.Render();                                                                 // Renderiza o ambiente

                    while (true)                                                                  // Execute a política RUN_POLICY_STEPS, que é muito menor que a duração do episódio
                    {
                        run_policy_steps += 1;                                                    // Incrementa contador de passos de cada episodio
                        obs = np.stack(new[] { obs }).astype(dtype: np.float32);                  // prepare to feed placeholder Policy.obs
                        (NDArray _act, NDArray _v_pred) = Policy.act(obs: obs, stochastic: true); // Corre a rede neural e obtêm uma ação e o V previsto
                        int     act    = np.asscalar <int>(_act.ToArray <int>());                 // Transforma um array do numpy
                        NDArray v_pred = np.asscalar <double[]>(_v_pred.ToArray <double>());      // em um objeto scalar do Python
                        //var v_pred = _v_pred.Item();  // em um objeto scalar do Python

                        observations.Add(obs);                           // Adiciona a observação ao buffer de observações
                        actions.Add(act);                                // Adiciona a ação ao buffer de ações
                        v_preds.Add(v_pred);                             // Adiciona a v_pred ao buffer de v_pred
                        rewards.Add(reward);                             // Adiciona a recompensa ao buffer de recompensa

                        var(next_obs, _reward, done, _) = env.Step(act); // envia a ação ao ambiente e recebe a próxima observação, a recompensa e se o passo terminou
                        reward = _reward;

                        if (done)
                        {                           // Se o done for (verdadeiro ...
                            v_preds_next = v_preds; // [1:] seleciona do segundo elemento da lista em diante e + [0] adiciona um elemento de valor zero no final da lista
                            v_preds_next.RemoveAt(0);
                            v_preds_next.Add(0);
                            // next state of terminate state has 0 state value
                            // próximo estado do estado final tem 0 valor de estado
                            obs    = env.Reset(); //   Redefine o ambiente
                            reward = -1;          //   define a recompensa como -1 (?)
                            break;                //   Sai do loop while
                        }
                        else
                        {                   // Senão...
                            obs = next_obs; //   Armazena em obs a próxima observação
                        }
                    }
                    // Armazena em log para visualização no tensorboard
                    //writer.add_summary(tf.Summary(value:[tf.Summary.Value(tag:"episode_length", simple_value:run_policy_steps)]), episode);
                    //writer.add_summary(tf.Summary(value:[tf.Summary.Value(tag:"episode_reward", simple_value:rewards.Sum())]),     episode);

                    // Condicional para finalizar o teste
                    if (rewards.Sum() >= 195)
                    {                                                  // Se a soma das recompensas for (maior ou igual 195
                        success_num += 1;                              //   Incrementa o contador de sucessos
                        if (success_num >= 100)
                        {                                              //   Se ocorrerem 100 sucessos
                            saver.save(sess, "./model/model.ckpt");    //       Salva a sessão
                            Console.WriteLine("Clear!! Model saved."); //       Escreve na tela
                            break;                                     //       Sai do loop
                        }
                    }
                    else
                    {                                                                                    // senão,
                        success_num = 0;                                                                 //   zera o contador de sucessos
                    }
                    Console.WriteLine("EP: ", episode, " Rw: ", rewards.Sum());                          // Escreve na tela o numero do episodio e a recompensa

                    gaes = PPO.get_gaes(rewards: rewards, v_preds: v_preds, v_preds_next: v_preds_next); // ?

                    // Converte lista em NPArray para alimentar o tf.placeholder
                    //int[] newShape = ((-1), (list(ob_space.Shape)));// cria um array [-1, 4]
                    var _observations = np.reshape(observations.ToArray(), shape: ((-1), (4)));// antes, cada linha de observations era um array independente. depois do reshape, observations passou ser um array só com varias linhas.
                    var _actions      = np.array(actions.ToArray(), dtype: np.int32);
                    var _rewards      = np.array(rewards.ToArray(), dtype: np.float32);
                    var _v_preds_next = np.array(v_preds_next.ToArray(), dtype: np.float32);
                    var __gaes        = np.array(gaes.ToArray(), dtype: np.float32);
                    var _gaes         = (__gaes - __gaes.mean()) / __gaes.std(); // subtrai dos itens de gaes a media de todos os itens de gaes e divide todos pelo desvio padrão de gaes

                    PPO.assign_policy_parameters();

                    NDArray[] inp = new[] { _observations, _actions, _rewards, _v_preds_next, _gaes };  // Cria um array com 5 colunas: observações, ações, recompensas,

                    // Treina
                    for (int epoch = 0; epoch < 4; epoch++)
                    {
                        NDArray sample_indices = np.random.randint(low: 0, high: observations.ToArray().GetLength(0), size: new Shape(64));// índices estão em [baixo, alto]
                        var     sampled_inp    = new List <NDArray>();
                        foreach (NDArray arr in inp)
                        {
                            foreach (int indice in sample_indices.ToArray <int>())
                            {
                                sampled_inp.Add(arr[0][indice]);
                            }
                            //sampled_inp.Add(np.Take(a: arr, índices: sample_indices, axis: 0));   // amostra de dados de treinamento
                        }
                        PPO.train(obs: sampled_inp[0], actions: sampled_inp[1], rewards: sampled_inp[2], v_preds_next: sampled_inp[3], gaes: sampled_inp[4]);
                    }
                    var summary = PPO.get_summary(obs: inp[0], actions: inp[1], rewards: inp[2], v_preds_next: inp[3], gaes: inp[4])[0];

                    //writer.add_summary(summary, episode);
                }
                //writer.close(); // Final do episódio
            }
        }