Дискретная дилемма

В настоящее время я работаю над известной проблемой Горных Автомобилей из обучения подкреплению. Эта проблема имеет непрерывный характер, то есть у меня есть две переменные: одна позиция - в диапазоне от -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). Вы должны ограничить значения, прежде чем объединять их.

Другие вопросы по тегам