1. Lambda:将均值为0的输入数据的正与负部分级联。Lambda用来编写不需要训练的层。
import keras.backend as K
from keras.layers.core import Lambda
from keras.models import Sequential
import numpy as np
np.random.seed(19931221)
def antirectifier(x):
x -= K.mean(x, axis=1, keepdims=True)
# x = K.l2_normalize(x, axis=1)
pos = K.relu(x)
neg = K.relu(-x)
return K.concatenate([pos, neg], axis=1)
def antirectifier_output_shape(input_shape):
shape = list(input_shape)
assert len(shape) == 2 # only valid for 2D tensors
shape[-1] *= 2
return tuple(shape)
input_data=np.random.randint(0,10,(3,2))
x1 = input_data-np.mean(input_data, axis=1, keepdims=True)
model = Sequential()
model.add(Lambda(antirectifier, output_shape=antirectifier_output_shape,input_shape=(2,)))
res=model.predict(input_data)
当Lambda作为第一层时,要指定input_shape;在中间层时,将前一层的输出作为输入。
输入
input_data=[7 7
9 0
8 9]
中间结果
x1=[ 0 0
4.5 -4.5
-0.5 0.5]
最终结果
res=[ 0 0 0 0
4.5 0 0 4.5
0 0.5 0.5 0]
lambda定义多输入层时,如下
import keras.backend as K
def compare(x):
pool_conf, conf = x[0],x[1]
threshold =0.1
sign = (1+K.sign(K.sign(pool_conf-tf.constant(threshold))-0.5))/2
output = (1-sign)*tf.maximum(1-pool_conf, conf)+sign*tf.minimum(1-pool_conf, conf)
# output = tf.cond(tf.less_equal(pool_conf,tf.constant(threshold)),
# tf.maximum(1-pool_conf, conf),
# tf.minimum(1-pool_conf, conf))
return output
def compare_output_shape(input_shape):
return input_shape[0]
prior = Lambda(compare, output_shape=compare_output_shape)([gray_conf, conf])
注意:函数导入输入变量时两个输入作为一个整体,在函数里分开。tf.cond只能用于常数,tensorflow模式固定易出错,尽量用K的函数。K.sign()会得到3种值{-1,0,1},只想用到2种值{0,1},减去0.5后用嵌套,再平移。
2. 自定义非递归层:训练系数,使输出是输入的0.1。
from keras.models import Sequential
import numpy as np
from keras.engine.topology import Layer
np.random.seed(19931221)
class MyLayer(Layer):
def __init__(self, output_dim, **kw):
self.output_dim = output_dim
self.SCALER = None
super(MyLayer, self).__init__(**kw)
def build(self, input_shape):
input_dim = input_shape[1]
self.SCALER=self.add_weight(shape=(input_dim,), initializer='uniform', trainable=True)#注意shape写法
super(MyLayer, self).build(input_shape)
def call(self, x):
x *= self.SCALER
return x
def compute_output_shape(self, input_shape):
return input_shape
input_data=np.random.randint(0, 10, (3000, 2))
test_data=np.random.randint(0, 10, (1, 2)) #test_data=[4, 1]
labels = 0.1*input_data
model = Sequential()
model.add(MyLayer(2, input_shape=(2,)))
model.compile(optimizer='rmsprop', loss='mse')
model.fit(input_data, labels, verbose=1)
res=model.predict(test_data) #res=[0.40302727, 0.09999914]
model.get_weights() #weights=[0.10075682, 0.09999914]
可以不定义输出维度,即在__init__中去掉“self.output_dim”,则MyLayer(input_shape=(2,))即可。
self.SCALER可能要加名字
self.SCALER=self.add_weight(name='scaler', shape=(input_dim, ), initializer='uniform', trainable=True)
3. 对参数进行约束
参考:https://www.colabug.com/5345160.html
4. 共享层。
参考:https://keras-cn.readthedocs.io/en/latest/getting_started/functional_API/#_4
例如:希望两个一样的模块A和B共用权重,且A的输出作用在B的输入
from keras.layers import Conv2D, Input, Multiply, Lambda, Add
from keras.models import Model
input_tensor = Input((5,5,3))
add_tensor = Input((5,5,1))
output0 = Conv2D(6,(3,3), padding='same', name='1')(input_tensor)
output = Add()([output0, add_tensor])
model = Model([input_tensor, add_tensor], output)
mask = Input((5,5,4))
gray = Lambda(lambda z: z[:,:,:,3:]/255, output_shape=(5, 5, 1))(mask)
rgb = Lambda(lambda z: z[:,:,:,:3], output_shape=(5, 5, 1))(mask)
out_all = model([rgb,gray])
out = Lambda(lambda z: z[:,:,:,0:1], output_shape=(5, 5, 1))(out_all)
mask01 = Multiply()([out, gray])
out1 = model([rgb,mask01])
model_all = Model(mask,[out_all, out1])
keras中文文档
keras英文文档
使用预训练模型
预训练模型中文文档(显示中间层)
layer
源码解析之layer
源码解析之layer(二)
编写自己的层
利用keras的扩展性