这里的方格,就是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:
- s: 当前状态state
- a: 从当前状态下,采取的行动action
- s': 今次行动所产生的新一轮state
- a': 次回action
- r: 本次行动的奖励reward
- γγ : 折扣因数,表示牺牲当前收益,换区长远收益的程度。
那么最关键的问题是:如何计算Q?
算法的基本流程:
- 初始化Q-table矩阵
- 选择起始state
- 选择当前state(s)下的一个可能action(a)
- 换移到下一个state(s')
- 重复第3步
- 使用Bellman Equation,更新Q-table
- 将下一个state作为当前state
- 如此迭代三十年,直到大厦崩塌
比如,从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-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 |
#include<time.h>
#include<stdlib.h>
int choice(int arr[])
{
srand(time(NULL));
int seed = rand()%3;
int i = 0;
}
{
int i;
double max = -10000.0;
{
if(max < arr[i])
{
max = arr[i];
}
}
}
{
int i=0;
{
int start_state = 0;
int current_state = start_state;
{
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;
{
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];
}
q_matrix[current_state][action] = q_state;
}
}
int q_i,q_j;
{
for(q_j = 0;q_j < 5;q_j++)
{
printf("%f.2",q_matrix[q_i][q_j]);
}
printf("\n");
}