[PYTHON] Beschreiben eines Netzwerks, das Anmerkungsinformationen von Benutzern in Keras akzeptiert

Als ich die Anmerkungsinformationen (Gewichtungsinformationen) vom Benutzer erhielt, habe ich versucht und einen Fehler gemacht, wie das Deep Learning-Netzwerkmodell implementiert werden soll, das die Verarbeitung mit Keras umschaltet, sodass ich den Inhalt zusammenfassen werde. Vor kurzem wurde es hauptsächlich in PyTorch implementiert, daher war ich durch den Unterschied in der Beschreibungsmethode verwirrt. Verwenden Sie die funktionale API, um komplexe Netzwerke in Keras zu beschreiben. Referenz: Qiita-Seite zur Verwendung der Keras-Funktions-API

In der Funktions-API müssen die in keras.layers definierten Ebenen verbunden werden. Es ist erforderlich, Lambda zu implementieren, um eine Schicht der ursprünglichen Verarbeitung wie in dieser Zeit zu erstellen. Unten finden Sie ein Codebeispiel für ein Netzwerk, das wie gezeigt eine Bilderkennungsaufgabe übernimmt. SelfAttentionNetwork.png

Normalerweise wird das Originalbild als Eingabedaten an das Netzwerk übergeben. Dieses Mal ergeben eine gewichtete Karte, die dem Originalbild entspricht, und ein Flag (0 oder 1), ob die gewichtete Karte verwendet werden soll, insgesamt drei Eingaben. Das Originalbild, die gewichtete Karte und das Flag für die Verwendung der gewichteten Karte werden in keras.layers.Input definiert, da sie je nach Eingabedatensatz unterschiedlich groß sind. Daher ist es nicht möglich, einfach nach der If-Anweisung zu urteilen und die Verarbeitung zu wechseln.

Netzwerkmodellcode

from keras.models import Model
from keras.layers import Conv2D, Activation, BatchNormalization, GlobalAveragePooling2D, Dense, Input, Lambda, Add, Multiply
from keras.backend import switch as k_switch
from keras.backend import equal as k_equal
import numpy as np

def net(x, user_weight_map, user_weight_map_flg, feature_ch=16):
 """
    x:Original Bild
    user_weight_map:Vom Benutzer angegebene gewichtete Karte
    user_weight_map_flg:Flag zur Verwendung der vom Benutzer angegebenen gewichteten Karte
    """
    #Faltung 4 Mal anwenden
    h = Conv2d(feature_ch, 3, strides=2, padding='same')(x)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)

    h = Conv2d(feature_ch*2, 3, strides=2, padding='same')(x)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)
    
    h = Conv2d(feature_ch*4, 3, strides=2, padding='same')(x)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)
    
    h = Conv2d(feature_ch*8, 3, strides=2, padding='same')(x)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)
    
    #---------------------
    #Gewichtete Karte in einem verzweigten Netzwerk(Self Attention)Berechnen
    bh = Conv2D(feature_ch*4, 3, strides=1, padding='same')(h)
    bh = BatchNormalization()(bh)
    bh = Activation(activation='relu')(bh)
    
    bh = Conv2D(feature_ch*2, 3, strides=1, padding='same')(bh)
    bh = BatchNormalization()(bh)
    bh = Activation(activation='relu')(bh)
    
    bh = Conv2D(2, 1, strides=1, padding='same')(bh)
    bh = BatchNormalization()(bh)
    bh = Activation(activation='relu')(bh)
    
    model_weight = Conv2D(1, 3, strides=1, padding='same')(bh)
    model_weight = BatchNormalization()(bh)
    model_weight = Activation(activation='sigmoid', name='model_weight_output')(bh)

    bh = Conv2D(2, 1, strides=1, padding='same')(bh)
    bh = GlobalAveragePooling2D()(ah)
    bh = Dense(1000)(bh)
    #---------------------

    #Lesen Sie die Flag-Informationen und wechseln Sie zwischen der Verwendung der aus dem Netzwerk berechneten gewichteten Karte und der Verwendung der vom Benutzer erstellten gewichteten Karte
    weight_h = Lambda(lambda x: switch_weight_map(x), name='swith_weight_map')([h, model_weight, user_weight_map, user_weight_map_flg])

    h = Add(name='weight_map_add')([h, weight_h])

    h = Conv2d(feature_ch*16, 3, strides=2, padding='same')(h)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)
    
    h = Conv2d(feature_ch*32, 3, strides=2, padding='same')(h)
    h = BatchNormalization()(h)
    h = Activation(activation='relu')(h)

    h = GlobalAveragePooling2D()(h)
    h = Dense(1000)(h)
  
    return h, bh, model_weight

def switch_weight_map(inputs):
    feature_map = inputs[0]
    model_weight_map = inputs[1]
    user_weight_map = inputs[2]
    user_weight_map_flg = inputs[3]
    
    model_weight = Multiply()([feature_map, model_weight_map])
    user_weight = Multiply()([feature_map, user_weight_map])

    weight_cond = k_equal(user_weight_map_flg, 0)
    
    weight_h = k_switch(weight_cond, model_weight, user_weight)

    return weight_h

# Save Network Architecture
def save_network_param(save_path, feature_ch):
    param = {'base_feature_num':feature_ch}
    
    with open(save_path, 'w') as f:
        yaml.dump(param, f, default_flow_style=False)

# Load Network Architecture
def load_network_param(load_path):
    with open(load_path) as f:
        param = yaml.load(f)

    return param

Wenn Sie beim Drehen des Trainingsprozesses versuchen, das Modell für jede Epoche mit dem Argument save_weights_only = False in der Rückruffunktion keras.callbacks.ModelCheckpoint () zu speichern, lautet die Fehlermeldung "_thread.RLock-Objekte können nicht ausgewählt werden". So etwas kam heraus. Als ich versuchte, das Modell mit model.to_json () oder model.to_yaml () zu exportieren, wurde der gleiche Fehler angezeigt. Es schien, dass Pickle nicht serialisiert werden konnte, da es eine unbestimmte Eingabe gab, bis Lambda Eingabedaten erhielt. Speichern Sie in keras.callbacks.ModelCheckpoint () das Argument mit save_weights_only = True. Bereiten Sie save_network_param () und load_network_param () vor und reproduzieren Sie die Netzwerkstruktur mit dem Netzwerkcode und der exportierten yaml-Datei und legen Sie das Gewicht jeder Ebene mit model.load_weights () fest, um das von train erstellte Modell für die Vorhersage zu verwenden. ..

Bei der Implementierung mit Lambda bestand der Trick darin, das Argument x als Liste wie [h, model_weight, user_weight_map, user_weight_map_flg] anzugeben. Wenn Sie für Lambdas Argument x wie unten gezeigt nur user_weight_map_flg verwenden, interpretiert Keras die Netzwerkstruktur und es ist nicht möglich zu bestimmen, ob model_weight beim Speichern oder Laden mit anderen Ebenen verbunden wird. Konnte nicht.

weight_h = Lambda(lambda x:k_switch(k_equal(x, 0), model_weight, user_weight), name='switch_weight_map')(user_weight_map_flg)

Referenzinformationen

https://stackoverflow.com/questions/52448652/attributeerror-nonetype-object-has-no-attribute-inbound-nodes-while-trying https://stackoverflow.com/questions/44855603/typeerror-cant-pickle-thread-lock-objects-in-seq2seq https://github.com/keras-team/keras/issues/8343 https://github.com/matterport/Mask_RCNN/issues/1126 https://stackoverflow.com/questions/53212672/read-only-mode-in-keras https://stackoverflow.com/questions/47066635/checkpointing-keras-model-typeerror-cant-pickle-thread-lock-objects/55229794#55229794 https://blog.shikoan.com/lambda_arguments/ https://github.com/keras-team/keras/issues/6621 https://stackoverflow.com/questions/59635570/keras-backend-k-switch-for-loss-function-error

Recommended Posts

Beschreiben eines Netzwerks, das Anmerkungsinformationen von Benutzern in Keras akzeptiert
In Python habe ich einen LINE-Bot erstellt, der Polleninformationen aus Standortinformationen sendet.
Erstellen Sie in Python einen Dekorator, der Argumente dynamisch akzeptiert. Erstellen Sie einen Dekorator
Schreiben Sie ein Co-Autorennetzwerk in einem bestimmten Feld mit Informationen von arxiv