keras 自定义:激活函数,层,损失函数,正则化器,初始化器,学习率

我不太喜欢通过super来 继承keras类。这里说的是通过功能函数实现的。

自定义激活函数

import os
from keras import backend as K
from keras.layers import Activation,Conv2D
from keras.utils.generic_utils import get_custom_objects
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"


def swish(x):
    '''
    x:每个值
    '''
    return (K.sigmoid(x) * x)


get_custom_objects().update({'swish': Activation(swish)})



# 用法
net  = Activation("swish")(net)
# 或者 都可以
net = (......,activation='swish')(net)

swish为自定义的激活函数,其中x为一个值,而不是tensor。

自定义层

import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
from keras.layer import Lambda,concatenate
from keras.backend import maximum,expand_dims
import keras.activations as activation

def MFM(net):
    n = int(net.get_shape().as_list()[-1]/2)
    tmp = []
    for i in range(n):
        tmp_value = maximum(net[...,i],net[...,-(i+1)])
        tmp.append(expand_dims(tmp_value,axis=-1))
    return concatenate(tmp,axis=-1)

...
...

net =Lambda(MFM,name='MFM')(net)

主要用到了Lambda这个函数。MFM是我定义的层函数。

自定义损失函数

这个不说了,直接放进去就行。

def mean_squared_error(y_true, y_pred):
    return K.mean(K.square(y_pred - y_true), axis=-1)
...
...
model.compile(optimizer='rmsprop',loss=mean_squared_error)

其中必须有y_true和y_pred这两个参数,还可以有别的参数。但是要在他们后面。比如

from keras.layers import Input,Embedding,LSTM,Dense
from keras.models import Model
from keras import backend as K

word_size = 128
nb_features = 10000
nb_classes = 10
encode_size = 64

input = Input(shape=(None,))
embedded = Embedding(nb_features,word_size)(input)
encoder = LSTM(encode_size)(embedded)
predict = Dense(nb_classes, activation='softmax')(encoder)

def mycrossentropy(y_true, y_pred, e=0.1):
    loss1 = K.categorical_crossentropy(y_true, y_pred)
    loss2 = K.categorical_crossentropy(K.ones_like(y_pred)/nb_classes, y_pred)
    return (1-e)*loss1 + e*loss2

model = Model(inputs=input, outputs=predict)
model.compile(optimizer='adam', loss=mycrossentropy)

y_true和y_pred这两个参数可以不用,比如说在定义triplet_loss的时候。

def _triplet_loss(self,y_true,y_pred):
      anc,pos,neg = y_pred[:, 0:128], y_pred[:, 128:256], y_pred[:, 256:]
      print('anc,pos,neg : ',anc.shape,pos.shape,neg.shape)

      pos_dist = K.sum(K.square(anc-pos),axis=-1,keepdims=True)#,keepdims=True)
      neg_dist = K.sum(K.square(anc-neg),axis=-1,keepdims=True)#,keepdims=True)
      basic_loss = pos_dist-neg_dist+self.Margin
      loss = K.maximum(basic_loss,0.0)
      print("[INFO] model - triplet_loss shape: %s" % str(loss.shape))
      return loss

自定义正则化器

任何输入一个权重矩阵、返回一个损失贡献张量的函数,都可以用作正则化器,例如:

 from keras import backend as K
 ​
 def l1_reg(weight_matrix):
     return 0.01 * K.sum(K.abs(weight_matrix))
 ​
 model.add(Dense(64, input_dim=64,
                 kernel_regularizer=l1_reg))

自定义初始化器

如果传递一个自定义的可调用函数,那么它必须使用参数 shape(需要初始化的变量的尺寸)和 dtype(数据类型)

from keras import backend as K

def my_init(shape, dtype=None):
    return K.random_normal(shape, dtype=dtype)

model.add(Dense(64, kernel_initializer=my_init))

要是定义复杂初始化,那么就嵌套函数吧。比如conv+bn融合。

学习率

def lr_scheduler(epoch):
    return learning_rate * (0.5 ** (epoch // lr_drop))

reduce_lr = keras.callbacks.LearningRateScheduler(lr_scheduler)
# 该回调函数是用于动态设置学习率
....
....
....
historytemp = model.fit_generator(datagen.flow(x_train, y_train,
                                                       batch_size=batch_size),
                                          steps_per_epoch=x_train.shape[0] // batch_size,
                                          epochs=maxepoches,
                                          validation_data=(x_test, y_test), callbacks=[reduce_lr], verbose=2)

猜你喜欢

转载自blog.csdn.net/weixin_39875161/article/details/104678867