Я новичок в изучении подкрепления. Недавно я узнал о приближенном q-обучении или q-основанном на функциях обучении, в котором вы описываете состояния с помощью функций, чтобы сэкономить место. Я попытался реализовать это в простой игре сетки. Здесь агент должен научиться не входить в огненную яму (обозначенную символом f) и вместо этого съедать как можно больше точек. Вот используемая сетка:
... A
.f.f
.f.f
... е
Здесь A указывает начальное местоположение агента. Теперь при реализации я настроил две функции. Один был 1 / ((расстояние до ближайшей точки) ^ 2), а другой был (расстояние до огненной ямы) + 1. Когда агент входит в огненную яму, программа возвращается с вознаграждением -100. Если он переходит в уже посещенную позицию без огненной ямы (и, таким образом, нет точки, которую нужно съесть), вознаграждение составляет -50. Если он переходит в не посещенную точку, награда +500. В приведенной выше таблице, независимо от того, каковы начальные веса, программа никогда не узнает правильные значения веса. В частности, в выходных данных первая тренировочная сессия получает оценку (сколько точек она съела), равную 3, но для всех других тренировочных сессий оценка составляет всего 1, а веса сходятся к неверному значению -125 для веса 1 ( расстояние до костра) и 25 для веса 2 (расстояние до невидимой точки). Что-то не так с моим кодом или мое понимание приблизительного обучения q неверно?
Я попытался поиграть с наградами, которые дает окружающая среда, а также с начальными весами. Ни один из них не устранил проблему.
Вот ссылка на всю программу: https://repl.it/repls/WrongCheeryInterface
Вот что происходит в основном цикле:
while(points != NUMPOINTS){
bool playerDied = false;
if(!start){
if(!atFirepit()){
r = 0;
if(visited[player.x][player.y] == 0){
points += 1;
r += 500;
}else{
r += -50;
}
}else{
playerDied = true;
r = -100;
}
}
//Update visited
visited[player.x][player.y] = 1;
if(!start){
//This is based off the q learning update formula
pairPoint qAndA = getMaxQAndAction();
double maxQValue = qAndA.q;
double sample = r;
if(!playerDied && points != NUMPOINTS)
sample = r + (gamma2 * maxQValue);
double diff = sample - qVal;
updateWeights(player, diff);
}
// checking end game condition
if(playerDied || points == NUMPOINTS) break;
pairPoint qAndA = getMaxQAndAction();
qVal = qAndA.q;
int bestAction = qAndA.a;
//update player and q value
player.x += dx[bestAction];
player.y += dy[bestAction];
start = false;
}
Я ожидал бы, что оба веса все еще будут положительными, но один из них будет отрицательным (тот, который дает расстояние до костра).
Я также ожидал, что программа сверхурочно узнает, что входить в огненную яму плохо, а также плохо, но не так плохо, идти в не посещенную точку.