Keras使用教程

2018/03/24 深度学习

1. 数据预处理

这是预处理模块,包括序列数据的处理、文本数据的处理、图像数据的处理。重点看一下图像数据的处理,keras提供了ImageDataGenerator函数,实现data augmentation,数据集扩增,对图像做一些弹性变换,比如水平翻转、垂直翻转、旋转等。

1.1 序列预处理

填充序列pad_sequences:sequences为浮点数或整数构成的两层嵌套列表。按maxlen长度截断或者补0。

keras.preprocessing.sequence.pad_sequences(sequences, maxlen=None, dtype='int32', padding='pre', truncating='pre', value=0.)

跳字skipgrams:

keras.preprocessing.sequence.skipgrams(sequence, vocabulary_size, window_size=4, negative_samples=1., shuffle=True, categorical=False, sampling_table=None)

1.2 文本预处理

句子分割:本函数将一个句子拆分成单词构成的列表。text是待处理的文本,filters是需要过滤字符的列表或者字符连接形成的字符串,lower表示是否将序列设为小写形式,split是单词的分隔符。

keras.preprocessing.text.text_to_word_sequence(text, filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n', lower=True, split=" ")

one-hot编码:本函数将一段文本编码为one-hot形式的码,即仅记录词在词典中的下标。

keras.preprocessing.text.one_hot(text, n, filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n', lower=True, split=" ")

特征哈希hashing_trick:将文本转换为固定大小的哈希空间中的索引序列;n为哈希空间的维度,hash_function默认为python hash函数。

keras.preprocessing.text.hashing_trick(text, n, hash_function=None, filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n', lower=True, split=' ')

1.3 图片预处理

2. 模型

2.1 序贯模型(Sequential)

2.2 函数式模型(Model)

2.3 两类模型的相同方法

2.3.1 打印模型概况

model.summary():打印出模型概况,它实际调用的是keras.utils.print_summary。

2.3.2 保存、恢复模型的config信息

model.get_config():返回包含模型配置信息的Python字典。模型也可以从它的config信息中重构回去。

config = model.get_config()

model = Model.from_config(config)
# or, for Sequential:
model = Sequential.from_config(config)

2.3.3 保存、恢复模型的层、权重,设置模型的权重

model.get_layer():依据层名或下标获得层对象。

model.get_weights():返回模型权重张量的列表,类型为numpy array。

model.set_weights():从numpy array里将权重载入给模型,要求数组具有与model.get_weights()相同的形状。

2.3.4 得到模型的网络结构 JSON字符串

model.to_json:返回代表模型的JSON字符串,仅包含网络结构,不包含权值。可以从JSON字符串中重构原模型

from models import model_from_json
json_string = model.to_json()
model = model_from_json(json_string)

2.3.5 保存、恢复模型的网络结构 YAML字符串

model.to_yaml:与model.to_json类似,同样可以从产生的YAML字符串中重构模型。

from models import model_from_yaml
yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)

2.3.6 保存、恢复模型的权重

model.save_weights(filepath):将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)。

model.load_weights(filepath, by_name=False):从HDF5文件中加载权重到当前模型中,默认情况下模型的结构将保持不变。如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重。

2.3.7 保存、恢复模型的网络结构和权重

from keras.models import load_model
model.save('my_model.h5')  # creates a HDF5 file 'my_model.h5'
del model  # deletes the existing model
# returns a compiled model
# identical to the previous one
model = load_model('my_model.h5')

2.3.8 获取中间层的输出

要获取中间层的输出,最好的办法是新建一个模型。

from keras.models import Model
model = ...  #原始model
layer_name = "my_layer"
intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict(data)

或者使用keras function来实现返回一个特定的输出。

from keras import backend as K
get_3rd_layer_output = K.function([model.layers[0].input, model.layers[3].output])
layer_output = get_3rd_layer_output([x])[0]

2.3.9 使用history函数来记录每一个epoch的training/validation的loss/accuracy

model.fit()会返回一个History对象。该对象有一个history属性,记录着loss和metrics的信息。

hist = model.fit(x, y, validation_split=0.2)
print(hist.history)

2.3.10 固定某些layer

frozen_layer = Dense(32, trainable=False)

2.3.11 模型的一些常用属性

model.layers: layer的list列表

model.inputs: input tensor的集合

model.outputs: output tensor的集合

3. 网络层

3.1 包装器Wrapper

3.1.1 TimeDistributed包装器

keras.layers.wrappers.TimeDistributed(layer) 

参数:
layer:Keras层对象

输入至少为3D张量,下标为1的维度将被认为是时间维。例如,考虑一个含有32个样本的batch,每个样本都是10个向量组成的序列,每个向量长为16,则其输入维度为(32,10,16),其不包含batch大小的input_shape为(10,16)。

我们可以使用包装器TimeDistributed包装Dense,以产生针对各个时间步信号的独立全连接。

如何在长短期记忆(LSTM)网络中利用TimeDistributed层—python语言

model = Sequential()
model.add(TimeDistributed(Convolution2D(64, 3, 3), input_shape=(10, 3, 299, 299)))

3.1.2 Bidirectional包装器

keras.layers.wrappers.Bidirectional(layer, merge_mode='concat', weights=None)

model.add(Bidirectional(LSTM(10, return_sequences=True)))


双向RNN包装器
参数:
layer: Recurrent对象
merge_mode: 前向和后向RNN输出的结合方式,为sum,mul,concat,ave和None之一,若设为None,则返回值不结合,而是以列表的形式返回。

Keras中Bidirectional定义源码

self.forward_layer = copy.copy(layer)
config = layer.get_config()
config['go_backwards'] = not config['go_backwards']
self.backward_layer = layer.__class__.from_config(config) 两个RNN层,一个go_backwards为True,一个go_backwards为False。

y = self.forward_layer.call(inputs, **kwargs)
y_rev = self.backward_layer.call(inputs, **kwargs)

if self.return_sequences:
	y_rev = K.reverse(y_rev, 1)
if self.merge_mode == 'concat':
	output = K.concatenate([y, y_rev])

3.2 循环层Recurrent

3.2.1 Recurrent层

keras.layers.recurrent.Recurrent(return_sequences=False, go_backwards=False, stateful=False, unroll=False, implementation=0)

参数:
return_sequences: 布尔值,默认False,控制返回类型。若为True则返回整个序列,否则仅返回输出序列的最后一个输出。
go_backwards: 布尔值,默认为False,若为True,则逆向处理输入序列并返回输出序列。

输入shape: 形如(samples,timesteps,input_dim)的3D张量。
输出shape: 如果return_sequences=True,返回形如(samples,timesteps,output_dim)的3D张量;否则,返回形如(samples,output_dim)的2D张量。

4. 网络配置

4.1 初始化方法 Initializer

4.2 激活函数 Activation

4.3 损失函数 loss

4.4 优化器 Optimizer

4.5 正则项 Regularizer

4.6 性能评估 Metrices

5. 利用Keras的扩展性,Keras的高级功能

5.1 自定义loss,并且设置compile的loss、loss_weights、metrics参数

如果是多输出的模型,只能给每个输出分别设置一个loss,然后加权求和,比较复杂的loss就不能定义。记住是“分别设置”、“加权求和”。也就是说loss函数应该以(y_true, y_pred)为参数,并返回单个张量,你有多个输出,每个输出都有这么一个函数,参数就是某个输出和预测的输出。

def mean_pred(y_true, y_pred):
	return K.mean(y_pred)

下面例子,第一个loss参数为train_targets和predict;第二个loss参数为random_y和l2_loss,但是返回值就是l2_loss。整体loss为两个loss的加权和。

metrics为accuracy,参数为train_targets和predict。

model_train = Model(inputs=[input_image,input_target], outputs=[predict,l2_loss])
model_train.compile(optimizer='adam', loss=['sparse_categorical_crossentropy',lambda y_true,y_pred: y_pred], loss_weights=[1.,0.2], metrics={'softmax':'accuracy'})
model_train.fit([train_images,train_targets], [train_targets,random_y], epochs=10)

5.2 Lambda层

如果你只是想对流经该层的数据做个变换,而这个变换本身没有什么需要学习的参数,那么直接用Lambda Layer是最合适的了。

from keras.layers.core import Lambda

def sub_mean(x):
	x -= K.mean(x,axis=1,keepdims=True)  
	return x

model.add(Lambda(sub_mean, output_shape=lambda input_shape:input_shape))

注意Lambda 是可以进行参数传递的。

def slice(x,index):
	return x[:,:,index]

x1 = Lambda(slice,output_shape=(4,1),arguments={'index':0})(a)  
x2 = Lambda(slice,output_shape=(4,1),arguments={'index':1})(a)

keras Lambda自定义层实现数据的切片,Lambda传参数

Keras 自定义层

5.3 自定义非递归层

如果自己想定义的层中有需要学习的变量,那么就不能用lambda层了,需要自己写一个出来。

如下,实现的功能是对张量乘一个正对角阵(换句话说,输入向量与一个要学习的向量逐元素相乘)。

from keras import backend as K
from keras.engine.topology import Layer
import numpy as np

class MyLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel', 
                                      shape=(input_shape[1], self.output_dim),
                                      initializer='uniform',
                                      trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this somewhere!

    def call(self, x):
        return K.dot(x, self.kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

5.4 自定义递归层

递归层的定义方法和非递归层不太一样。根据Keras内LSTM的写法,它还有一个reset_states函数和step函数,这是由递归的性质决定的。例子都在keras/layers/recurrent.py中。

可以在Keras中把LSTM的代码复制过来修修改改。不过LSTM也不能直接复制过来,还需要import如下几个依赖:

from keras.layers.recurrent import LSTM,Recurrent,time_distributed_dense  
from keras import initializations,regularizers,activations  
from keras.engine import InputSpec  

5.5 自定义优化函数

Keras的代码确实好,耦合度很低。Keras内置的优化函数在keras/optimizers.py中,基类Optimizer也在这个文件里。例如把它内置的SGD算法拷贝到自己的文件中,只要先from keras.optimizers import Optimizer就能编译通过。

有时候要得到state-of-the-art的结果,需要用sgd加动量法充分收敛。比如学习率0.01学习上100epoch,再把学习率减半,再学100epoch,依次类推。如果不自定义优化函数的话,就要分阶段调用fit函数,修改学习率,可能还要重新compile。这就不是很优美了。其它一些奇葩的学习策略,也可以通过自定义优化函数来得到。

如何利用Keras的扩展性

编写自己的层

keras中自定义Layer 设置该层的input_spec,这个是通过InputSpec函数来实现。

参考

keras学习笔记

keras系列︱Sequential与Model模型、keras基本结构功能(一)

Keras中自定义复杂的loss函数

keras 多输出与loss, metrics的关系

Search

    Table of Contents