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)

上述代码展示了在训练过程中观察中间层的平均模长的变化情况。可以看到,主要涉及到两个listmodel.metrics_names是metric的名称,是字符串列表;model.metrics_tensors是metric的张量。只要在这里把你需要展示的量添加进去,就可以在训练过程中显示了。当然,要注意的是,一次性只能添加一个标量

 

参考链接:https://spaces.ac.cn/archives/6311

posted @ 2020-03-05 17:26  光彩照人  阅读(996)  评论(0编辑  收藏  举报