Дискретная дилемма
В настоящее время я работаю над известной проблемой Горных Автомобилей из обучения подкреплению. Эта проблема имеет непрерывный характер, то есть у меня есть две переменные: одна позиция - в диапазоне от -1,2 до 0,5 и скорость - в диапазоне от -0,07 до 0,07. И у меня есть 3 возможных действия - обратное ускорение, ускорение вперед и нейтральное, действия приводят к изменению положения в соответствующем направлении. Из-за того, как рассчитывается ускорение, моя переменная положения является непрерывной, что означает, что я не могу использовать справочную таблицу, поэтому я попытался разделить ось положения-скорости в прямоугольных секторах, разделив положение на сегменты шириной 0,05 и скорость на сегменты длиной 0,005, присваивая каждому сектору индекс, я сделал это так:
public int discretiseObservation(Observation observation) {
double position = observation.getDouble(0) ;
double velocity = observation.getDouble(1);
boolean positionNegativeFlag = position < 0;
boolean velocityNegativeFlag = velocity < 0;
double absolutePosition = Math.abs(position);
double absoluteVelocity = Math.abs(velocity);
double discretePosition = Math.floor(absolutePosition / 0.05);
double discreteVelocity = Math.floor(absoluteVelocity / 0.005);
if(velocityNegativeFlag) {
discreteVelocity += 14;
}
if(positionNegativeFlag) {
discretePosition += 10;
}
return (int)discretePosition * 28 + (int)discreteVelocity;
}
Но эта схема приводит к тому, что некоторые сектора имеют одинаковый индекс. Есть ли у вас идеи, как я могу дискретизировать эти две непрерывные переменные?
Upd: Извините, забыл упомянуть, что когда положение или скорость превышает максимальное или минимальное значение, я возвращаю его к максимальному или минимальному значению
2 ответа
Вы слишком усложняете вещи со всеми этими проверками знака. Также вам следует избегать использования магических констант - давать им значимые имена. Код дискретизации должен выглядеть следующим образом:
double normalize(double value, double min, double max) {
return (value - min) / (max - min);
}
int clamp(int value, int min, int max) {
if (value < min) value = min;
if (value > max) value = max;
return value;
}
int discretize(double value, double min, double max, int binCount) {
int discreteValue = (int) (binCount * normalize(value, min, max));
return clamp(discreteValue, 0, binCount - 1);
}
public int discretizeObservation(Observation observation ) {
int position = discretize(observation.getDouble(0), minPosition, maxPosition, positionBinCount);
int velocity = discretize(observation.getDouble(1), minVelocity, maxVelocity, velocityBinCount);
return position * velocityBinCount + velocity;
}
Вы не ограничиваете свою позицию и скорость. Когда они слишком велики (независимо от знака), они будут переполнены жестко закодированными значениями смещения (14 и 10). Вы должны ограничить значения, прежде чем объединять их.