Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ws1819:acrobot

Acrobot

gym environment

Ich habe mich, um das Thema besser zu verstehen, mit den Classic control Acrobot beschäftigt. (https://gym.openai.com/envs/#classic_control)

Hierbei handelt es sich um ein Doppelpendel, welches als Ziel versucht sich über die Linie (höhe 1) zu schwingen.

Die Schwierigkeit liegt bei diesem Environment darin, dass man einen Weg finden muss, dass NN mit den wenigen Erfolgen zu trainieren. (Anfangs kam das Pendel bei 1000 Versuchen ca. 2 mal über die Linie)

Dazu muss man wissen, dass die klassische Künstliche Intelligenz (KI) meist nur durch Belohnungen etwas lernt (die sich durch Zwischenetappen erreichen lassen).

Zum Vergleich: ich habe das Problem mit zwei unterschiedlich starken Neuralen Netzen getestet. Nach mehren hundert Testläufen meinerseits, ergab sich, dass die besten Resultate mit dem Einfachsten NN und ca. 22 Episoden erzielt wurden (Highscore 63).[der vermeintliche Weltrekord liegt bei 42]

63 heißt hierbei aufschwing Versuche.

Ich lasse die Trainingsdaten weg, da ich finde, dass es am meisten Spaß macht beim Lernen zu zugucken (wenn man die Seite bearbeitet ist der Code richtig formatiert/ ich sende ihn gerne via SLACK)

ZIP des Code: acrobotzip.rar

Der Code zum besten Ergebnis

import random
import gym
import numpy as np
from collections import deque
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import Adam
import keras
 
#//////////////////////////////
 
class DQNAgent:
    def __init__(self, state_size, action_size):
        self.state_size = state_size
        self.action_size = action_size
        self.memory = deque(maxlen=2000)
        self.gamma = 1.0   # discount rate
        self.epsilon = 1.0  # exploration rate
        self.epsilon_min = 0.01
        self.epsilon_decay = 0.999
        self.learning_rate = 0.001
        self.model = self._build_model()
 
    def _build_model(self):
        # Einfaches NN 
        model = Sequential()
        model.add(Dense(16, input_dim=self.state_size, activation='relu', 
                        kernel_regularizer=keras.regularizers.l2(0.00001)))
        #model.add(Dropout(0.3))
        #model.add(Dense(24, activation='relu', kernel_regularizer=keras.regularizers.l2(0.00001)))
        model.add(Dense(self.action_size, activation='linear'))
        model.compile(loss='mse',
                      optimizer=Adam(lr=self.learning_rate))
        return model
 
    def remember(self, state, action, reward, next_state, done, total, importance):
        # merkt sich alle bisher durchlaufenen Zustände
        self.memory.append([state, action, reward, next_state, done,total,importance])
 
    def act(self, state):
        # epsilon-greedy: off-policy oder policy
 
        if np.random.rand() <= self.epsilon:
            return random.randrange(self.action_size)
        act_values = self.model.predict(state)
        return np.argmax(act_values[0])  # returns action
 
    def replay(self, batch_size):
        # baut den Vektor der Q-Werte aus 
        # als reward zum Zeitpunkt t + gamma*max(moegliche rewards zum Zeitpunkt t+1)
 
        probabilities = np.array([m[-1] for m in self.memory])
        probabilities = 1./np.sum(probabilities) * probabilities
        #print( probabilities.shape)
        minibatch = [self.memory[i] for i in np.random.choice(range(len(self.memory)),size=batch_size, p=probabilities)]
        states, targets_f = [], []
        for state, action, reward, next_state, done,total,importance in minibatch:
            target = reward
            if not done:
                target = (reward + self.gamma *
                          np.amax(self.model.predict(next_state)[0]))
            target_f = self.model.predict(state)
            target_f[0][action] = target 
            # Filtering out states and targets for training
            states.append(state[0])
            targets_f.append(target_f[0])
        history = self.model.fit(np.array(states), np.array(targets_f), epochs=1, verbose=0)
        # Keeping track of loss
        loss = history.history['loss'][0]
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
        return loss
 
    def load(self, name):
        self.model.load_weights(name)
 
    def save(self, name):
        self.model.save_weights(name)
 
 
EPISODES = 7
 
 
env = gym.make('Acrobot-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
agent = DQNAgent(state_size, action_size)
done = False
batch_size = 32
 
for e in range(EPISODES):
    state = env.reset()
    state = np.reshape(state, [1, state_size])
    cum_reward = 0
    for time in range(500):
        env.render()
        action = agent.act(state)
        next_state, reward, done, _ = env.step(action)
        additional_reward = -(state[0,0] + state[0,0]*state[0,2]-state[0,1]*state[0,3])#*0.2##faktore aus probieren
        reward = reward + additional_reward if not done else 10 #
        cum_reward += reward
        next_state = np.reshape(next_state, [1, state_size])
        agent.remember(state, action, reward, next_state, done,reward,1)
        state = next_state
        if done:
            print("episode: {}/{}, score: {}, e: {:.2}"
                  .format(e, EPISODES, time, agent.epsilon))
            break
        if len(agent.memory) > batch_size:
            loss = agent.replay(batch_size)
            # Logging training loss and actual reward every 10 timesteps
            if time % 10 == 0:
                print("episode: {}/{}, time: {}, cumulative reward: {:.4f}, loss: {:.4f}".format(e, EPISODES, time, cum_reward, loss)) 
 
 
    for i in range(time):
        pos = -i-1
        agent.memory[-i-2][-2] += reward
        for j in range(-time,pos):
            new_total =  agent.memory[j][-2] + agent.memory[pos][2]
            mem = agent.memory[j]
            agent.memory[j][-1] =new_total
 
    for i in range(time):
        pos = -i-1
        imp = max(agent.memory[pos][-2]-agent.model.predict(agent.memory[pos][0])[0,agent.memory[pos][1]],0)
        mem = agent.memory[pos]
        agent.memory[pos][-1] = imp
 
 
    agent.save("qlearning_Acrobot_1000versuche")
 
#//////////////////////////////////////////////
ws1819/acrobot.txt · Zuletzt geändert: 2019/03/31 15:24 von rhotert