Simulación con Modelo entrenado en PilotNet
Como estas semanas ya disponíamos del servidor Libélula, hemos creado un nuevo dataset con un tamaño mayor de datos (22000 frames) en el que hay mucha variedad de maniobras con los actuadores del vehículo y distintos escenarios del simulador Carla.
Balanceo de un nuevo dataset (Semana 9).
Para balancear el dataset, hemos disminuido a 5000 muestras los casos más frecuentes: (steer=0, throttle = 0) y (steer=0, throttle = 1). El resto de casos, los hemos aumentado a 3000 muestras, cada uno. A continuación, una tabla con la cantidad de muestras por categoría y la imagen del histograma tridimensional del conjunto de datos:
Data Augmentation (Semana 9)
Además, se han hecho varias pruebas de Data Augmentation para que nuestro modelo aprenda a generalizar mejor. Para cada muestra que se ha aumentado, en lugar de duplicar a la original, se ha duplicado y modificado ligeramente la imagen con el siguiente pipeline durante el entrenamiento del modelo:
data_augmentation = Sequential([
RandomBrightness(0.2), # cambio aleatorio de brillo
RandomContrast(0.2), # variación del contraste
RandomZoom(0.1), # zoom de la imagen
GaussianNoise(0.03), # ruido gaussiano
RandomRotation(0.03), # rotación muy pequeña
], name="data_augmentation")
Entrenamiento y simulación con PilotNet
Para esta semana (semana 10) el objetivo era continuar con el entrenamiento de modelos: mejorando u optimizando sus hiperparámetros, y añadiendo aleatoriedad a la distribución de las muestras.
A continuación se muestra el modelo que hemos usado de PilotNet:
pilotnet(input_shape=(120, 160, 3), n_outputs=3, l2=1e-4, dropout=0.2):
reg = tf.keras.regularizers.l2(l2) if l2 and l2 > 0 else None
kw = dict(kernel_initializer="he_normal", kernel_regularizer=reg)
inputs = layers.Input(shape=input_shape)
# Convolucional
x = layers.Conv2D(24, 5, strides=2, activation='relu', **kw)(inputs)
x = layers.Conv2D(36, 5, strides=2, activation='relu', **kw)(x)
x = layers.Conv2D(48, 5, strides=2, activation='relu', **kw)(x)
x = layers.Conv2D(64, 3, strides=1, activation='relu', **kw)(x)
x = layers.Conv2D(64, 3, strides=1, activation='relu', **kw)(x)
x = layers.Flatten()(x)
# Cabezal denso
x = layers.Dense(100, activation='relu', **kw)(x)
if dropout and dropout > 0:
x = layers.Dropout(dropout)(x)
x = layers.Dense(50, activation='relu', **kw)(x)
x = layers.Dense(10, activation='relu', **kw)(x)
outputs = layers.Dense(n_outputs, activation='tanh', name='controls')(x)
model = models.Model(inputs, outputs, name="PilotNet_120x160x3")
model.compile(
optimizer=tf.keras.optimizers.Adam(1e-4),
loss='mse',
metrics=[tf.keras.metrics.MeanAbsoluteError(name='mae')]
)
return model
model = pilotnet(input_shape=(120, 160, 3), n_outputs=3, l2=1e-4, dropout=0.2)
model.summary()
Por fallos en el servidor, no hemos podido seguir el entrenamiento esta semana ni tampoco mostrar los resultados del entrenamiento (no disponemos de los scripts). No obstante, se han podido realizar unos primeros entrenamientos en los que se ha añadido aleatoriedad en el orden del cojunto de datos. Se ha entrenado el modelo con tamaño de lote de 64 (para que aprenda a generalizar mejor épocas), 100 épocas y le hemos añadido un callback EarlyStopping, para que cuando el modelo no pueda aprender más, finalice el entrenamiento
Tras el entrenamiento, se han realizado varios tests online para probar la predicción del modelo mientras conduce un vehículo simulado en Carla. Con respecto a la semana anterior (semana 9), ha mejorado la conducción. Sin embargo, sigo teniendo comportamientos extraños que no sabemos localizar, por el momento, o bien producidos durante el entrenamiento o bien por el dataset en sí, los datos de los que aprende.
A continuación, se pueden visualizar en el siguiente enlace diversas tomas de video en que el vehículo mantiene pulsado throttle y brake a la vez o ambas están a 0 (no avanza el coche), y dirección del volante a partes del escenario sin salida o a la acera y colisión con obstáculos.
- Colisión: https://youtu.be/pZ9LdCIHDBY
- Detención del vehículo : https://youtu.be/vy8HbB6lxGw
Se cree que el primer error podría ser debido a que un tipo de muestra que predomina, es (steer=0, throttle=0), por lo que puede estar aprendiendo o interpretando, en esas muestras que el coche está en movimiento (sin interacción en los actuadores), que está detenido. Por otra parte, las desviaciones del volante fuera de la vía, podría ser que tengamos overfitting. Puede que esté aprendiendo mal o memorizando las muestras, sin ser capaz de aprender bien.
Conclusiones
Como esta semana no se ha podido completar el trabajo a realizar por inaccesibilidad al servidor, se ha estado probando el modelo que se ha podido entrenar (con mucho margen de mejor) para ver los resultados e investigar cómo se pueden mejorar los errores de conducción de cara a futuros entrenamientos.