Entwurf eines Dueling DQN mit keras

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
marcelpn94
User
Beiträge: 5
Registriert: Donnerstag 15. August 2019, 09:56

Hallo zusammen,

ich bin gerade dabei für meinen Roboter einen RL Algo zu schreiben, bin aber auf das folgende Problem gestoßen.
Da der duelingDQN die Layer in eine Aktions- und eine Wertfunktion aufteilt, muss ich diese anschließend wieder zusammenführen um die endgültigen Q-values zu berechnen (über die Summe).

Hier taucht dann jedoch der folgende Fehler auf:

Code: Alles auswählen

q_value_2 =merge([state_value, action_advantage], mode='sum')
TypeError: 'module' object is not callable
Der Code für den RL Algo findet hier nachfolgend:

Code: Alles auswählen

from keras import backend as b
from keras.models import Sequential, load_model
from keras.optimizers import RMSprop
from keras.layers import Dense, Dropout, Activation, Lambda, merge, Input

def buildModel(self):
    
        input = Input(shape=(self.state_size,))
        x = Dense(32, input_shape=(self.state_size,), activation='relu', kernel_initializer='he_uniform')(input)
        x = Dense(16, activation='relu', kernel_initializer='he_uniform')(x)

        state_value = Dense(1, kernel_initializer='he_uniform')(x)
        state_value = Lambda(lambda s: b.expand_dims(s[:, 0], -1), output_shape=(self.action_size,))(state_value)

        action_advantage = Dense(self.action_size, kernel_initializer='he_uniform')(x)
        action_advantage = Lambda(lambda a: a[:, :] - b.mean(a[:, :], keepdims=True),
                                  output_shape=(self.action_size,))(action_advantage)

        q_value_2 =merge([state_value, action_advantage], mode='sum')
        model = Model(input=input, output=q_value_2)
        model.summary()
        model.compile(loss='mse', optimizer=RMSprop(self.learning_rate))
        return model
Wäre cool. wenn ihr mit hier helfen könntet.
BG
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Code: Alles auswählen

q_value_2 =merge([state_value, action_advantage], mode='sum')
da fehlt eine Methode merge.add() z.B.
Methoden siehe hier: http://faroit.com/keras-docs/2.0.2/layers/merge/

Wobei ich die importe so machen würde:

Code: Alles auswählen

from tensorflow.keras import backend as b
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.layers import Dense, Dropout, Activation, Lambda, merge, Input
und dann fällt merge als Fehler raus
ImportError: cannot import name 'merge' from 'tensorflow.keras.layers' (unknown location)
Also schau mal besser hier: https://www.tensorflow.org/api_docs/pyt ... as/layers/
wenn du nicht vorhast, ein anderes Framework wie z.B. Theano zu benutzen.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
marcelpn94
User
Beiträge: 5
Registriert: Donnerstag 15. August 2019, 09:56

Vielen Dank für die Antwort!

Ich habe es die Importe erstmal so belassen. Als ich diese auf deine Schreibweise geändert habe, kam folgender Fehler, den ich nicht auf die Schnelle beheben konnte:

Code: Alles auswählen

from tensorflow.keras import backend as b
ImportError: No module named keras
Deshalb habe ich mich an den ersten Part deines Vorschlags gemacht. Dort habe ich nun

Code: Alles auswählen

added = add([action_value, state_value])
stehen.
Dies funktioniert auch ganz gut. Nur weiß ich hier noch nicht, ob dieser Befehl jeweils den state_value einzeln auf die action_values addiert (action_value_1 + state_value, action_value_2 + state_value, ...), weil auch der Modus sum noch nicht eingebunden ist.

Alternativ habe ich auch diese Lösung probiert:

Code: Alles auswählen

q-value= Sequential()
q_value.add(Merge([state_value, action_value], mode='sum'))
Dort kommt der folgende Fehler: ImportError: cannot import name Merge (mit from keras.layers import Merge).

Ich muss also noch ein wenig probieren.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@marcelpn94: Wo sollte ein `Merge` in `keras.layers` auch herkommen?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Code: Alles auswählen

import tensorflow

# entweder so
from tensorflow import keras
# oder so
# import keras

print(tensorflow.__version__)
print(keras.__version__)

# aktuell sind, alles andere ist antik ;-)
# Tensorflow --> 1.14.0
# Keras --->  2.2.4-tf
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
marcelpn94
User
Beiträge: 5
Registriert: Donnerstag 15. August 2019, 09:56

Danke nochmal für die schnelle Antwort,

ich habe das nochmal ausprobiert. Leider hat das merge immer n och nicht funktioniert. Meine Tensorflow und Keras Versionen sind aber auch auf deinem Stand. Wenn ich

Code: Alles auswählen

from tensorflow.keras.layers import Dense, Dropout, Activation, Lambda, Input, merge
schreibe, dann kommt der folgende Fehler:

Code: Alles auswählen

from tensorflow.keras.layers import Dense, Dropout, Activation, Lambda, Input, merge
ImportError: cannot import name merge

Was ich nun ebenfalls nicht verstehe ist, warum funktioniert das add() ohne Probleme, das merge() aber nicht.

Code: Alles auswählen

from keras import backend as b
from keras.utils import plot_model
from keras.models import Sequential, load_model, Model
from keras.optimizers import RMSprop
from keras.layers import Dense, Dropout, Activation, Lambda , merge, Input, add

def buildModel(self):
        input = Input(shape=(self.state_size,))
        hidden_layer_1 = Dense(64, activation='relu')(input)
        hidden_layer_2 = Dense(64, activation='relu')(hidden_layer_1)

        # State Value Schaetzung   1 Wert fuer den betroffenen State
        state_value_layer = Dense(64, activation='relu')(hidden_layer_2)
        state_value = Dense(1, activation='relu')(state_value_layer)

        # Action Value Schaetzung   5 Werte fuer die unterschiedlichen Lenk Winkel
        action_value_layer = Dense(64, activation='relu')(hidden_layer_2)
        action_value = Dense(self.action_size, activation='relu')(action_value_layer)

        # addieren der action_values mit dem state_value
        output = merge([state_value, action_value], mode='sum') => funktioniert nicht
        output = add([action_value, state_value]) => funktioniert

        model = Model(inputs=input, outputs=output)
        model.compile(optimizer='rmsprop',  loss='categorical_crossentropy', metrics=['accuracy'])
        model.summary()
        # plot_model(model, to_file='model_dueling.png')
        return model
Vielen Dank für die Hilfe!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@marcelpn94: Wo hast Du denn die Idee her, dass es in `keras.layers` eine `merge()`-Funktion gibt? Zeig mal die Stelle in der Keras-Dokumentation wo diese Funktion beschrieben wird.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

@marcelpn94: Es gab mal ein Keras Modul namens merge, wie man hier an diesem Link sehen kann. http://faroit.com/keras-docs/2.0.2/layers/merge/
Aber die Doku dort ist für Keras 2.0.2, dass ist schon etwas länger her.

In aktuellen Version gibt es das Modul nicht mehr, also kannst du es nicht importieren.
Deine erste Fehlermeldung
TypeError: 'module' object is not callable
besagt, dass du es zwar laden konntest (hast halt noch ne alte Keras Version installiert gehabt) aber es nicht aufrufbar ist/war weil es ein Modul und keine Methode ist/war.
In der alten Version gab es Methoden unterhalb von merge, z.B. keras.layers.merge.Add() etc, siehe Link.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
marcelpn94
User
Beiträge: 5
Registriert: Donnerstag 15. August 2019, 09:56

@ThomasL: Alles klar. Ich bin wohl immer auf die alte Doku gestoßen, weil ich immer sehr zielgerichtet nach dem mode='sum' Befehl gesucht und nur da gefunden habe. Bei der neuen add Variante gibt es diesen Zusatz scheinbar nicht mehr. Dort steht für den add() code nur ein Beuspiel beschrieben, in dem zwei gleich große Tensoren summiert werden. Ich war mir diesbezüglich dann unsicher ob ich das add() dann auch für meinen Code nutzen kann.
Antworten