【问题标题】:how to update a parameter (at each epoch based on the input state of that epoch) within a keras custom layer?如何在 keras 自定义层中更新参数(在每个时期基于该时期的输入状态)?
【发布时间】:2020-03-20 08:34:16
【问题描述】:

我有一个 keras 顺序模型,并且我有一个自定义层用于示例,可以说它的名称是“LayerX”。 现在在“LayerX”中,我有一个参数“lambda”,我想用一个值初始化它,例如 lambda = 10,

现在,在训练时,在每个时期,我在“LayerX”层的“调用”方法中获取输入,并根据该时期的输入计算一个值假设“valX”,我想要用这个值'valX'在每个时期更新参数'lamba'。假设,在每个 epoch,lambda = lambda + valX。

我是自定义 keras 层的新手。任何人都可以帮助我了解如何做到这一点吗?

【问题讨论】:

    标签: python tensorflow keras model layer


    【解决方案1】:

    这是一个示例,我在每个 epoch 后提取渐变。您可以对 model.fit 循环进行更改,以对图层进行自定义更改。

    注意:我使用的是 tensorflow 1.15.0

    # (1) Importing dependency
    import keras
    from keras import backend as K
    from keras.models import Sequential
    from keras.layers import Dense, Activation, Dropout, Flatten, Conv2D, MaxPooling2D
    from keras.layers.normalization import BatchNormalization
    import numpy as np
    np.random.seed(1000)
    
    # (2) Get Data
    import tflearn.datasets.oxflower17 as oxflower17
    x, y = oxflower17.load_data(one_hot=True)
    
    # (3) Create a sequential model
    model = Sequential()
    
    # 1st Convolutional Layer
    model.add(Conv2D(filters=96, input_shape=(224,224,3), kernel_size=(11,11), strides=(4,4), padding='valid'))
    model.add(Activation('relu'))
    # Pooling 
    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
    # Batch Normalisation before passing it to the next layer
    model.add(BatchNormalization())
    
    # 2nd Convolutional Layer
    model.add(Conv2D(filters=256, kernel_size=(11,11), strides=(1,1), padding='valid'))
    model.add(Activation('relu'))
    # Pooling
    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # 3rd Convolutional Layer
    model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
    model.add(Activation('relu'))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # 4th Convolutional Layer
    model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
    model.add(Activation('relu'))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # 5th Convolutional Layer
    model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='valid'))
    model.add(Activation('relu'))
    # Pooling
    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # Passing it to a dense layer
    model.add(Flatten())
    # 1st Dense Layer
    model.add(Dense(4096, input_shape=(224*224*3,)))
    model.add(Activation('relu'))
    # Add Dropout to prevent overfitting
    model.add(Dropout(0.4))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # 2nd Dense Layer
    model.add(Dense(4096))
    model.add(Activation('relu'))
    # Add Dropout
    model.add(Dropout(0.4))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # 3rd Dense Layer
    model.add(Dense(1000))
    model.add(Activation('relu'))
    # Add Dropout
    model.add(Dropout(0.4))
    # Batch Normalisation
    model.add(BatchNormalization())
    
    # Output Layer
    model.add(Dense(17))
    model.add(Activation('softmax'))
    
    model.summary()
    
    # (4) Compile 
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    # (5) Define Gradient Function
    def get_gradient_func(model):
        grads = K.gradients(model.total_loss, model.trainable_weights)
        inputs = model.model._feed_inputs + model.model._feed_targets + model.model._feed_sample_weights
        func = K.function(inputs, grads)
        return func
    
    # (6) Train the model such that gradients are captured for every epoch
    epoch_gradient = []
    for epoch in range(1,5):
        model.fit(x, y, batch_size=64, epochs= epoch, initial_epoch = (epoch-1), verbose=1, validation_split=0.2, shuffle=True)
        get_gradient = get_gradient_func(model)
        grads = get_gradient([x, y, np.ones(len(y))])
        # Similarly define your function to play with your model.layers,model.layers[].get_weights(),model.input,model.total_loss,model.trainable_weights etc
        # print("Layer of the model:",model.layers[2])
        # print("Weights of the Layer",model.layers[2].get_weights())
        # print(model.input)
        # print(model.total_loss)
        # print(model.trainable_weights)
        epoch_gradient.append(grads)
    
    # (7) Convert to a 2 dimensiaonal array of (epoch, gradients) type
    gradient = np.asarray(epoch_gradient)
    print("Total number of epochs run:", epoch)
    print("Gradient Array has the shape:",gradient.shape)
    

    【讨论】:

    • 嗨,感谢您的回答,但我的情况更像是在自定义层中,stackoverflow.com/a/41710515/10645817 这个答案提供了一些见解,但我不确定 add_update 方法是否适用于急切执行,目前这对我不起作用
    猜你喜欢
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 2020-11-06
    • 2019-09-11
    • 2019-03-18
    相关资源
    最近更新 更多