keras使用中的花式技巧
一、Lambda层的使用
keras.layers.Lambda(function, output_shape=None, mask=None, arguments=None)
作用:将任意表达式封装为 Layer
对象
from keras.layers import Input, Dense,Lambda,merge from keras.models import Model from keras import backend as K import numpy as np # 输入层,注意表示的输入维度是[batch,5],默认不显示batch的,即batch的大小是任意的 inputs = Input(shape=(5,)) #Input(shape=None, batch_shape=None, name=None, dtype=None, sparse=False,tensor=None): #如果用batch_shape则可以显示配置batch def square(x): return x**2 y=Lambda(square)(inputs) model = Model(inputs=inputs, outputs=[y]) # a=np.array([[1,2,3,4,5],[1,2,2,1,1]])
#直接根据输入预测结果 print(model.predict(a))#这里的a必须是numpy.array类型,否则报错
out:
[[1 2 3 4 5] [1 2 2 1 1]] [[ 1. 4. 9. 16. 25.] [ 1. 4. 4. 1. 1.]]
二、可以不要输出
普通模型都是有标准的输入输出结构,然后loss是根据模型输出与真实label的运算。然而,对于比较复杂的模型,如自编码器、GAN、Seq2Seq,这种写法有时候不够方便,loss并不总是需要真实label的。幸好,比较新的Keras版本已经支持更加灵活的loss定义,比如我们可以这样写一个自编码器:
x_in = Input(shape=(784,)) x = x_in x = Dense(100, activation='relu')(x) x = Dense(784, activation='sigmoid')(x) model = Model(x_in, x) loss = K.mean((x - x_in)**2) model.add_loss(loss) model.compile(optimizer='adam') model.fit(x_train, None, epochs=5)
上述写法的几个特点是:
1、compile
的时候并没有传入loss,而是在compile
之前通过另外的方式定义loss,然后通过add_loss
加入到模型中,这样可以随意写足够灵活的loss,比如这个loss可以跟中间层的某个输出有关、跟输入有关,等等。
2、fit
的时候,原来的目标数据,现在是None
,因为这种方式已经把所有的输入输出都通过Input
传递进来了。
三、更随意的metric
另一种输出是训练过程中用来观察的metric。这里的metric,就是指衡量模型性能的一些指标,比如正确率、F1等,Keras内置了一些常见的metric。像开头例子的accuracy
一样,将这些metric的名字加入到model.compile
中,就可以在训练过程中动态地显示这些metric。
当然,你也可以参考Keras中内置的metric来自己定义新metric,但问题是在标准的metric定义方法中,metric是“输出层”与“目标值”之间的运算结果,而我们经常要在训练过程中观察一些特殊的量的变化过程,比如我想观察中间某一层的输出变化情况,这时候标准的metric定义就无法奏效了。
那可以怎么办呢?我们可以去看Keras的源码,去追溯它的metric相关的方法,最终我发现metric实际上定义在两个list
之中,通过修改这两个list
,我们可以非常灵活地显示需要观察的metric,比如
x_in = Input(shape=(784,)) x = x_in x = Dense(100, activation='relu')(x) x_h = x x = Dense(10, activation='softmax')(x) model = Model(x_in, x) model.compile(loss='categorical_crossentropy ', optimizer='adam', metrics=['accuracy']) # 重点来了 model.metrics_names.append('x_h_norm') model.metrics_tensors.append(K.mean(K.sum(x_h**2, 1)))#可以观察到中间结果x_h的变化。 model.fit(x_train, y_train, epochs=5)
上述代码展示了在训练过程中观察中间层的平均模长的变化情况。可以看到,主要涉及到两个list
:model.metrics_names
是metric的名称,是字符串列表;model.metrics_tensors
是metric的张量。只要在这里把你需要展示的量添加进去,就可以在训练过程中显示了。当然,要注意的是,一次性只能添加一个标量