算法
強化學習的目標是學習一個行為策略π:S→A,使系統選擇的動作能夠獲得環境獎賞的累計值最大,也使得外部環境對學習系統在某種意義下的評價(或整個系統的運行性能)最佳。
Q學習算法可從有延遲的回報中獲取最優控制策略。
偽碼如下
1.Set parameter, and environment reward matrixR
2.Initialize matrixQ as zero matrix
3.For each episode:
- Select random initial state
- Do while not reach goal state
Select one among all possible actions for the current state
Using this possible action, consider to go to the next state
Get maximum Q value of this next state based on all possible actions
-
Compute
Set the next state as the current state
- End Do
End For
學習系數取值范圍是[0,1),如果值接近0,那么表示的是Agent更趨向于注重即時的環境反饋值。反之,則Agent更加考慮的是未來狀態的可能獎勵值。
思路
狀態轉換圖如下
初始化矩陣為
每一episode的過程為
- 隨機選擇初始初始狀態AF(05)
- 循環直到到達目標狀態
- 將當前狀態可做的動作存為一個臨時列表
- 從中隨機選擇一個動作,作為下一狀態
- 根據公式計算新Q值
- 更新Q矩陣
最終學習結果為
得到最優路徑 C->D->E->F
腳本使用方法
創造prim,將腳本附在上面。
迭代次數固定為10次,經測試可以學習出6*6矩陣的結果。
打印出最優路徑。
代碼及注釋
list Q;
list R = [-1,-1,-1,-1,0,-1,-1,-1,-1,0,-1,100,-1,-1,-1,0,-1,-1,-1,0,0,-1,0,-1,0,-1,-1,0,-1,100,-1,0,-1,-1,0,100];
float alpha = 0.8;
// 初始化Q矩陣全零
initQ() {
integer s;
integer a;
Q = [];
for (s = 0; s < 6; s++) {
for (a = 0; a < 6; a++) {
Q = Q + [0];
}
}
}
// 打印Q矩陣
reportQ() {
integer s;
for (s = 0; s < 6; s++)
{
llOwnerSay("State " + (string)s + ": " + llDumpList2String(llList2List(Q, s * 6, s * 6 + 5), ", "));
}
}
// 獲取特定狀態-動作對的Q值,即Q[s,a]
integer getQ(integer s, integer a) {
return llList2Integer(Q, s * 6 + a);
}
// 獲取特定狀態-動作對的R值,即R[s,a]
integer getR(integer s, integer a) {
return llList2Integer(R, s * 6 + a);
}
// 獲取MaxQ值
integer getMaxQ(integer s) {
integer a;
integer max = 0;
for (a = 0; a < 6; a++)
{
if(llList2Integer(Q, s * 6 + a)>max)
{
max = llList2Integer(Q, s * 6 + a);
}
}
return max;
}
// 更新特定狀態-動作對的Q值
setQ(integer s, integer a, integer newQ) {
integer index = s * 6 + a;
Q = llListReplaceList(Q, [newQ], index, index);
}
// 打印結果路徑
reportResult(integer s) {
integer currentS = s;
llOwnerSay((string)currentS + " -> ") ;
while(currentS!=5)
{
integer a;
integer max = 0;
integer nextS;
for (a = 0; a < 6; a++)
{
if(llList2Integer(Q, currentS * 6 + a)>max)
{
max = llList2Integer(Q, s * 6 + a);
nextS = a;
}
}
llOwnerSay((string)nextS + " -> " );
currentS = nextS;
}
}
default
{
state_entry()
{
initQ();
integer episodeCount = 10;
while(episodeCount--)
{
// 隨機選擇初始初始狀態0~5
integer currentS = (integer)llFrand(6);
integer nextS;
integer newQ;
// 循環直到到達目標
while(currentS!=5)
{
// 隨機選擇當前狀態可做的動作
integer a;
list actions = [];
for (a = 0; a < 6; a++)
{
if(getR(currentS,a)!=-1)
{
actions = actions + [a];
}
}
integer index = (integer)llFrand(llGetListLength(actions));
nextS = llList2Integer(actions,index);
// 根據公式
newQ = (integer)((float)getR(currentS,nextS) + alpha * (float)getMaxQ(nextS));
setQ(currentS,nextS,newQ);
currentS = nextS;
}
reportQ();
}
reportResult(2);
}
}