Estás leyendo la publicación: Una guía para construir modelos de aprendizaje por refuerzo en PyTorch
PyTorch es uno de los marcos más utilizados en el campo del aprendizaje profundo. Podemos usar esta biblioteca en todos los aspectos y campos de la ciencia de datos y el aprendizaje automático. También podemos usarlo para el aprendizaje por refuerzo. En uno de nuestros artículos, analizamos en detalle el aprendizaje por refuerzo y el procedimiento que se puede seguir para crear modelos de aprendizaje por refuerzo con TensorFlow. En este artículo, discutiremos cómo podemos construir modelos de aprendizaje por refuerzo utilizando PyTorch. Los puntos principales que se discutirán en este artículo se enumeran a continuación.
Tabla de contenido
- El problema de CartPole
- Importación de bibliotecas
- Definición de configuración
- Almacenamiento de memoria
- Algoritmo de red Deep Q
- Entrenamiento de red
Empecemos por comprender el problema de CartPole.
El problema de CartPole
En este artículo, tratamos el problema de CartPole. Donde intentaremos que un agente aprenda a decidir si mover el carro del lado izquierdo o del lado derecho para que el poste unido al carro quede recto. Podemos ver un ejemplo en la siguiente imagen.
Internamente, cualquier acción realizada por un agente depende del estado del entorno, a medida que el entorno cambia de estado, devuelve una recompensa al agente que decide la acción del agente en ese estado del entorno.
Aquí, en este procedimiento, usaremos recompensas de +1 en cada paso de tiempo y si el carrito se mueve más de un límite desde el centro (aquí son 2,4 unidades) o el poste se cae demasiado, el entorno no devolverá ninguna recompensa. el agente. Así es como, si el agente se está desempeñando bien, solo funcionará durante más tiempo y obtendrá mayores recompensas.
Usando las siguientes líneas de códigos, podemos representar el problema de CartPole.
import gym import numpy as np import matplotlib.pyplot as plt from IPython import display as ipythondisplay from pyvirtualdisplay import Display display = Display(visible=0, size=(400, 300)) display.start() env = gym.make(” CartPole-v0″) env.reset() prev_screen = env.render(mode=”rgb_array”) plt.imshow(prev_screen) for i in range(50): acción = env.action_space.sample() obs, recompensa, hecho , info = env.step(action) screen = env.render(mode=”rgb_array”) plt.imshow(screen) ipythondisplay.clear_output(wait=True) ipythondisplay.display(plt.gcf()) si se hace: romper ipythondisplay .clear_output(esperar=Verdadero) env.cerrar()
Producción:
Dado que es una combinación de diferentes marcos, no podemos publicar esto aquí. Ejecutar los códigos anteriores le dará todos los estados del agente y también a través de la visualización podemos decir que el entorno tiene algunos estados como velocidad y posición. Comencemos nuestro procedimiento importando bibliotecas.
Importación de bibliotecas
En este artículo, veremos cómo podemos usar PyTorch para el aprendizaje por refuerzo. Para ello, estamos obligados a tener instalado PyTorch y un entorno de gimnasio en nuestro entorno. La instalación se puede realizar utilizando las siguientes líneas de códigos.
!pip instalar gimnasio !pip instalar pytorch
Como estoy usando google colab para esto, ya tengo estas bibliotecas instaladas en el entorno. Las siguientes bibliotecas son necesarias en nuestro proceso.
importar gimnasio importar matemáticas importar aleatorio importar numpy como np importar matplotlib importar matplotlib.pyplot como plt de colecciones importar namedtuple, deque de itertools importar conteo de PIL importar imagen
Desde PyTorch, debemos llamar a las siguientes bibliotecas.
importar antorcha importar antorcha.nn como nn importar antorcha.optim como optim importar antorcha.nn.funcional como F importar antorchavision.transforms como T
Usando los paquetes anteriores, definiremos capas en nuestra red neuronal y el módulo opitm ayudará en la optimización del modelo y el módulo autograd ayudará en la diferenciación automática.
Definición de configuración
Usando las siguientes líneas de código, estamos desenvolviendo el CartPole-v0, configurando matplotlib para la visualización e iniciando la GPU para el entorno.
env = gym.make(‘CartPole-v0’).unwrapped is_ipython = ‘inline’ en matplotlib.get_backend() if is_ipython: from IPython import display plt.ion() device = torch.device(“cuda” if torch.cuda .is_disponible() más “cpu”)
Almacenamiento de memoria
El aprendizaje por refuerzo básico requiere memoria de repetición para el entrenamiento de la red. Entonces, en algún tipo de almacenamiento, debemos almacenar las observaciones del agente que se pueden usar más adelante. Usando dos clases podemos almacenar memoria.
Transición = tupla nombrada(‘Transición’, (‘estado’, ‘acción’, ‘siguiente_estado’, ‘recompensa’))
Esta clase se llama tupla, esta tupla representa la transición única de nuestro entorno.
class ReplayMemory(objeto): def __init__(self, capacidad): self.memory = deque([],maxlen=capacidad) def push(self, *args): self.memory.append(Transition(*args)) def sample(self, batch_size): return random.sample(self.memory, batch_size) def __len__(self) : return len(self.memory)
El motivo principal de definir esta clase es amortiguar la transición observada recientemente de forma cíclica. También definimos muestras en esta clase que seleccionarán un lote aleatorio de transiciones para el entrenamiento.
Algoritmo de red Deep Q
Al igual que en el procedimiento normal de aprendizaje por refuerzo, aquí también nuestro objetivo es capacitar a un agente en la política que puede maximizar la recompensa acumulativa. Hablar de la idea principal detrás de Q-learning es utilizar una función que pueda decirnos cuál será el retorno de cualquier acción.
Dada cualquier acción con respecto a un estado, podemos maximizar nuestras recompensas usando una política. En nuestra red, vamos a utilizar 5 capas convolucionales de PyTorch, lo que significa que nuestra red es una red neuronal convolucional. También tenemos dos salidas. En efecto, nuestra red intentará predecir el rendimiento esperado de cada acción dado el estado actual.
class DQN(nn.Module): def __init__(self, h, w, outputs): super(DQN, self).__init__() self.conv1 = nn.Conv2d(3, 16, kernel_size=5, stride=2) self.bn1 = nn.BatchNorm2d(16) self.conv2 = nn.Conv2d(16, 32, kernel_size=5, stride=2) self.bn2 = nn.BatchNorm2d(32) self.conv3 = nn.Conv2d(32, 32, kernel_size=5, stride=2) self.bn3 = nn.BatchNorm2d(32) def conv2d_size_out(size, kernel_size = 5, stride = 2): return (size – (kernel_size – 1) – 1) // zancada + 1 convw = conv2d_size_out(conv2d_size_out(conv2d_size_out(w))) convh = conv2d_size_out(conv2d_size_out(conv2d_size_out(conv2d_size_out(h))) linear_input_size = convw * convh * 32 self.head = nn.Linear(linear_input_size, outputs)
Usando las siguientes líneas de código, podemos llamar a cualquiera de los elementos para determinar la siguiente acción durante la optimización.
def adelante(self, x): x = x.to(dispositivo) x = F.relu(self.bn1(self.conv1(x))) x = F.relu(self.bn2(self.conv2(x) )) x = F.relu(self.bn3(self.conv3(x))) return self.head(x.view(x.size(0), -1))
Entrenamiento de red
Usando los códigos a continuación, podemos instanciar nuestro modelo y su optimizador.
Definición de parámetros
BATCH_SIZE = 128 GAMMA = 0,999 EPS_START = 0,9 EPS_END = 0,05 EPS_DECAY = 200 TARGET_UPDATE = 10
Obtener el tamaño de la pantalla nos ayudará a inicializar las capas correctamente en función de la forma devuelta del entorno del gimnasio y obtener la cantidad de acciones.
init_screen = get_screen() _, _, screen_height, screen_width = init_screen.shape n_actions = env.action_space.n
Definición de la red política y la red objetivo y evaluación de la red objetivo
policy_net = DQN(screen_height, screen_width, n_actions).to(dispositivo) target_net = DQN(screen_height, screen_width, n_actions).to(dispositivo) target_net.load_state_dict(policy_net.state_dict()) target_net.eval()
Definición de optimizador
optimizador = optim.RMSprop(policy_net.parameters()) memoria = ReplayMemory(10000)
También podemos definir algunas utilidades para mostrar los resultados.
Select_action es una utilidad para seleccionar acciones usando la política greedy de epsilon. Plot_durations es una utilidad para trazar la duración de los episodios. La trama resultante contendrá el ciclo de entrenamiento principal.
pasos_hechos = 0 def select_action(estado): global pasos_hechos muestra = aleatorio.aleatorio() eps_umbral = EPS_END + (EPS_START – EPS_END) * \ math.exp(-1. * pasos_hechos / EPS_DECAY) pasos_hechos += 1 si muestra > eps_umbral: con torch.no_grad(): return policy_net(estado).max(1)[1].view(1, 1) else: return torch.tensor([[random.randrange(n_actions)]], dispositivo=dispositivo, dtype=torch.long)
Duración de la trama
episodios_duraciones = []
def plot_durations(): plt.figure(2) plt.clf() durations_t = torch.tensor(episode_durations, dtype=torch.float) plt.title(‘Entrenamiento…’) plt.xlabel(‘Episodio’) plt .ylabel(‘Duración’) plt.plot(duraciones_t.numpy()) if len(duraciones_t) >= 100: significa = duraciones_t.unfold(0, 100, 1).media(1).vista(-1) significa = torch.cat((torch.zeros(99), significa)) plt.plot(means.numpy()) plt.pause(0.001) if is_ipython: display.clear_output(wait=True) display.display(plt.gcf ())
Bucle de entrenamiento
Después de definir la configuración del modelo y del optimizador, podemos entrenar nuestro modelo.
def optimizar_modelo(): if len(memoria) < BATCH_SIZE: return transiciones = memoria.muestra(BATCH_SIZE) lote = Transición(*zip(*transiciones)) non_final_mask = torch.tensor(tuple(map(lambda s: s no es Ninguno , lote.siguiente_estado)), dispositivo=dispositivo, dtype=antorcha.bool) non_final_next_states = antorcha.cat([s for s in batch.next_state if s is not None]) estado_lote = antorcha.cat(lote.estado) acción_lote = antorcha.cat(lote.acción) recompensa_lote = antorcha.cat(lote.recompensa) estado_acción_valores = política_net(estado_lote).reunir(1, acción_lote) siguiente_estado_valores = antorcha.ceros( BATCH_SIZE, dispositivo=dispositivo) next_state_values[non_final_mask] = target_net(non_final_next_states).max(1)[0].detach() valores_de_acción_de_estado_esperados = (valores_de_estado_siguientes * GAMMA) + criterio de lote de recompensa = nn.SmoothL1Loss() pérdida = criterio(valores_de_acción_de_estado, valores_de_acción_de_estado_esperados.unsqueeze(1)) Optimizer.zero_grad() loss.backward() for param in policy_net.parameters( ): param.grad.data.clamp_(-1, 1) optimizador.paso()
En los códigos anteriores, primero transponemos la matriz de transición por lotes calculando la máscara de los estados no finales. Con esto, calculamos los valores q esperados, la pérdida de Huber y optimizamos el modelo. Usando el siguiente código podemos visualizar el bucle de entrenamiento principal. Al restablecer el tensor de estado, muestreamos la acción y la ejecutamos nuevamente, muestreamos la siguiente acción y repetimos la ejecución en el bucle.
num_episodes = 50 for i_episode in range(num_episodes): env.reset() last_screen = get_screen() current_screen = get_screen() state = current_screen – last_screen for t in count(): acción = seleccionar_acción(estado) _, recompensa, hecho, _ = env.paso(acción.elemento()) recompensa = antorcha.tensor([reward]dispositivo=dispositivo) última_pantalla = pantalla_actual pantalla_actual = obtener_pantalla() si no se hace: siguiente_estado = pantalla_actual – última_pantalla más: siguiente_estado = ninguno memory.push(estado, acción, siguiente_estado, recompensa) estado = siguiente_estado optimizar_modelo() si se hace: episodios_duraciones. append(t + 1) plot_durations() break if i_episode % TARGET_UPDATE == 0: target_net.load_state_dict(policy_net.state_dict()) print(‘Complete’) env.render() env.close() plt.ioff() plt .espectáculo()
Producción:
Podemos ver salidas en el tiempo de ejecución de la celda, para mejores resultados y optimización podemos mejorar el número de episodios. El código completo para el procedimiento se puede encontrar aquí.
Ultimas palabras
En este artículo, hemos discutido el problema de CartPole. Para el entorno, usamos el kit de herramientas Gym, y para resolverlo hasta cierto punto usando un agente y un algoritmo de aprendizaje por refuerzo. Usamos el marco PyTorch para que todos funcionen juntos.
Referencias