Q_learning 强化学习C语言版本

第一次听到 “增强学习”(Reinforcement Learning) 的时候,我以为只是在“深度学习”的基础上又玩儿的新花样。后来稍微了解了一下,发现其实是完全不同的概念,当然它们并非互斥,反而可以组合,于是又有了 “深度增强学习”(Deep Reinforcement Learning)

目前很少有用C语言去写一个强化学习的,我认为在嵌入式以及无线传感网络中强化学习也是很有用处的,因此本小编用C语言写了一个强化学习的Demo,供广大网友参考。----QQ:644250062. 大笑

这里我们采用2*2 的用例,方便大家的学习和借鉴。

这里的方格,就是Environment。虽然对于电脑前的我们,似乎很容易,但是对Agent来说,他尚且对力量一无所知的。不过,只要Agent知道生命的可贵(Reward),就可以训练出一个Policy。

游戏的目的是让分数最大化,比如踩到陷阱了,-10。拿到宝贝了,+10。同样是最终拿到了宝贝,我们希望的是最短路径,那么如果走了多余的路,就要 -1

Q-Learning的目的就是学习特定State下、特定Action的价值。Q并不是某个本质骑士取的字母,而是表示Quality。

Q-Learning的方法是建立一个表,以state为行、action为列。迷宫共有4个格,每个格子都有5个方向,所以Q-table就是4x5的一个表,对应总共20种可能的决策。

首先以0填充Q-table进行初始化,然后观察每一个决策带来的回馈,再更新Q-table。更新的依据是Bellman Equation:

Q(s,a)=r+γ(max(Q(s,a))Q(s,a)=r+γ(max(Q(s′,a′))

  • s: 当前状态state
  • a: 从当前状态下,采取的行动action
  • s': 今次行动所产生的新一轮state
  • a': 次回action
  • r: 本次行动的奖励reward
  • γγ : 折扣因数,表示牺牲当前收益,换区长远收益的程度。

那么最关键的问题是:如何计算Q?

Agent所做的每一轮决策(即一盘游戏),称为一个episode,跟美剧里的“集”单位一样。每一次行动,都会更新Q-table。

算法的基本流程:

  1. 初始化Q-table矩阵
  2. 选择起始state
  3. 选择当前state(s)下的一个可能action(a)
  4. 换移到下一个state(s')
  5. 重复第3步
  6. 使用Bellman Equation,更新Q-table
  7. 将下一个state作为当前state
  8. 如此迭代三十年,直到大厦崩塌

比如,从state-1开始,可能的action有D, R, N。然后我们选择了D,到了state-3,这个state踩中了陷阱,所以-10。

在state-3又有三种可能的action:U, R, N。 又因为此时Q-table还没有经过更新,所以max(Q(s,a)max(Q(s′,a′)当然就是0。假设折扣因数γ=0.7γ=0.7,则有:

Q(1,D)=R(1,D)+0.8×0=10Q(1,D)=R(1,D)+0.8×0=−10

第一次更新Q-table的结果是:

           
  U D L R N
1 0 -10 0 0 0
2 0 0 0 0 0
3 0 0 0 0 0
4 0 0 0 0 0

现在,我们来到了state-3,如果选择R,就到达了state-4,+10。再次更新Q-table为:

           
  U D L R N
1 0 -10 0 0 0
2 0 0 0 0 0
3 0 0 0 +10 0
4 0 0 0 0 0
上面是某位大神的案例 我借用过来,下面就是我介绍的C语言版本的demo。 大笑

#include <stdio.h>
#include<time.h>
#include<stdlib.h>
const double lr = 0.7;
int reward[4][5]={{0,-10,0,-1,-1},{0,10,-1,0,-1},{-1,0,0,10,-1},{-1,0,-10,0,10}};
double q_matrix[4][5] = {{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}};
int transition_matrix[4][5]= {{-1,2,-1,1,1},{-1,3,0,-1,2},{0,-1,-1,3,3},{1,-1,2,-1,4}};
int valid_actions[4][3] = {{1,3,4},{1,2,4},{0,3,4},{0,2,4}};

int choice(int arr[])
{
     srand(time(NULL));
     int seed = rand()%3;
     int i = 0;
     return arr[seed];
}
double max(double arr[])
{
     int i;
     double max = -10000.0;
     for(i = 0; i < 3;i++)
     {
            if(max < arr[i])
        {
             max = arr[i];
        }
     }
     return max;
}

int main()
{
     int i=0;
 
     for(i = 0;i < 1000;i++)
     {
      int start_state = 0;
      int current_state =  start_state;
      while(current_state!=3)
      {
           int action = choice(valid_actions[current_state]);
           int next_state = transition_matrix[current_state][action];
   
           int future[3]={0};
           double future_rewards[3]={0};
           int action_nxt;
           int action_next_next;
       for(action_nxt = 0; action_nxt < 3;action_nxt++)
       {
            future[action_nxt] = valid_actions[next_state][action_nxt]; 
       }
       for(action_next_next = 0;action_next_next < 3;action_next_next++)
       {
            future_rewards[action_next_next] = q_matrix[next_state][action_nxt];
       }
       double q_state = reward[current_state][action] + lr * max(future_rewards);
       q_matrix[current_state][action] = q_state;
       current_state = next_state;
      }
 }
 
     int q_i,q_j;
     for(q_i = 0;q_i < 4;q_i++)
     {
          for(q_j = 0;q_j < 5;q_j++)
       {
           printf("%f.2",q_matrix[q_i][q_j]);
       }    
        printf("\n");
     }
 return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_23144435/article/details/80368635