Я хочу научиться водить машину по прямой дороге, используя библиотеку Deeplearning4j (обучение подкреплению). Награды выдаются следующим образом: в случае автокатастрофы он получает -100, а если нет, то получает 1. Ожидающий автомобиль должен через некоторое время научиться ехать до конца дороги. Действия поворачиваются направо или налево на 4 градуса. Заметил, что автомобиль лучше совершает случайные действия, которые принимают меры на основе значений из q-таблицы, что я делаю не так? Обычно, если policy.EpsGreedy - EP: очень мало, он обычно придерживается одного действия. Ввод в непосредственной близости от машины - для оптимизации тренировочного процесса (20x20px).
Шаги агента:
public StepReply<Screen> step(Integer action) {
final Car car = scene.getCar();
final float speed = 4.0f;
switch (action) {
case ACTION_TOP_LEFT:
car.addAngle(-ANGLE_ADDITION);
computeNewLocation(car, speed);
break;
case ACTION_BOTTOM_RIGHT:
car.addAngle(+ANGLE_ADDITION);
computeNewLocation(car, speed);
break;
}
scene.draw();
double reward = scene.isCarScrashing() ? -100 : 1;
return new StepReply<>(new Screen(scene.toByteArray()), reward, scene.isCarScrashing(), null);
}
private void computeNewLocation(Car car, float speed) {
double x = car.getCurrentPositionX() + (speed * Math.cos(car.getRadianAngle().getValue()));
double y = car.getCurrentPositionY() + (speed * Math.sin(car.getRadianAngle().getValue()));
car.setCurrentPosition(x, y);
}
Конфигурация QL:
public static QLearning.QLConfiguration QL_CONFIGURATION =
new QLearning.QLConfiguration(
123, //Random seed
8000000, //Max step By epoch
8000000/2, //Max step
1000000/2, //Max size of experience replay
32, //size of batches
10000/2, //target update (hard)
500/2, //num step noop warmup
0.1, //reward scaling
0.99, //gamma
100.0, //td-error clipping
0.1f, //min epsilon
100000/2, //num step for eps greedy anneal
true //double-dqn
);
public static DQNFactoryStdConv.Configuration CONV = new DQNFactoryStdConv.Configuration(
0.1, //learning rate
0.000, //l2 regularization
null,
null
);
Получение непосредственного окружения:
public BufferedImage getCarView(Point sensorOrigin) {
Graphics2D graphics2D = carSensorBuffer.createGraphics();
graphics2D.clearRect(0, 0, SENSOR_WIDTH, SENSOR_HEIGHT);
AffineTransform sensorTransform = AffineTransform.getTranslateInstance(-sensorOrigin.x + (SENSOR_WIDTH / 2), -sensorOrigin.y + (SENSOR_HEIGHT / 2));
sensorTransform.rotate(-car.getRadianAngle().getValue(), sensorOrigin.x, sensorOrigin.y);
graphics2D.drawRenderedImage(frontBuffer, sensorTransform);
final BufferedImage scaledView = ImageUtil.scale(carSensorBuffer, SENSOR_WIDTH_OPTIMIZED, SENSOR_HEIGHT_OPTIMIZED);
final Graphics2D graphics = carSensorBufferOptimized.createGraphics();
graphics.drawImage(scaledView, 0, 0, null);
return carSensorBufferOptimized;
}
public byte[] toByteArray() {
getCarView(car.getSensorOrigin());
return ((DataBufferByte) carSensorBufferOptimized.getRaster().getDataBuffer()).getData();
}
Карта:
Пример ввода:
РЕДАКТИРОВАТЬ:
Забыл поделиться топологией нейронной сети:
public static MultiLayerConfiguration MULTILAYER_CONFIGURATION = new NeuralNetConfiguration.Builder()
.seed(12345)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.l2(0.0)
.updater((new Adam()))
.weightInit(WeightInit.XAVIER)
.l2(0.0)
.list()
.layer(0, new Convolution2D.Builder(new int[]{8, 8}).nIn(HISTORY_LENGTH).nOut(16).stride(new int[]{4, 4}).activation(Activation.RELU).build())
.layer(1, new Convolution2D.Builder(new int[]{4, 4}).nOut(32).stride(new int[]{2, 2}).activation(Activation.RELU).build())
.layer(2, new DenseLayer.Builder().nOut(256).activation(Activation.RELU).build())
.layer(3, new OutputLayer.Builder(LossFunctions.LossFunction.MSE).activation(Activation.IDENTITY).nOut(CarMDP.NUM_ACTIONS).build())
.setInputType(InputType.convolutional(20, 20, 3))
.build();