全栈工程师开发手册 (作者:栾鹏)
一、数据预处理
1、序列预处理
1.1、填充序列pad_sequences
keras.preprocessing.sequence.pad_sequences(sequences, maxlen=None, dtype='int32',padding='pre', truncating='pre', value=0.)
将长为nb_samples的序列(标量序列)转化为形如(nb_samples,nb_timesteps)2D numpy array。如果提供了参数maxlen,nb_timesteps=maxlen,否则其值为最长序列的长度。其他短于该长度的序列都会在后部填充0以达到该长度。长于nb_timesteps的序列将会被截断,以使其匹配目标长度。padding和截断发生的位置分别取决于padding和truncating.
参数
- sequences:浮点数或整数构成的两层嵌套列表
- maxlen:None或整数,为序列的最大长度。大于此长度的序列将被截短,小于此长度的序列将在后部填0.
- dtype:返回的numpy array的数据类型
- padding:‘pre’或‘post’,确定当需要补0时,在序列的起始还是结尾补
- truncating:‘pre’或‘post’,确定当需要截断序列时,从起始还是结尾截断
- value:浮点数,此值将在填充时代替默认的填充值0
返回值:返回形如(nb_samples,nb_timesteps)的2D张量
1.2、跳字skipgrams
keras.preprocessing.sequence.skipgrams(sequence, vocabulary_size,window_size=4, negative_samples=1., shuffle=True,categorical=False, sampling_table=None)
skipgrams将一个词向量下标的序列转化为下面的一对tuple:
- 对于正样本,转化为(word,word in the same window)
- 对于负样本,转化为(word,random word from the vocabulary)
【Tips】根据维基百科,n-gram代表在给定序列中产生连续的n项,当序列句子时,每项就是单词,此时n-gram也称为shingles。而skip-gram的推广,skip-gram产生的n项子序列中,各个项在原序列中不连续,而是跳了k个字。例如,对于句子:
“the rain in Spain falls mainly on the plain”
其 2-grams为子序列集合:
the rain,rain in,in Spain,Spain falls,falls mainly,mainly on,on the,the plain
其 1-skip-2-grams为子序列集合:
the in, rain Spain, in falls, Spain mainly, falls on, mainly the, on plain.
更多详情请参考Efficient Estimation of Word Representations in Vector Space
参数
- sequence:下标的列表,如果使用sampling_tabel,则某个词的下标应该为它在数据库中的顺序。(从1开始)
- vocabulary_size:整数,字典大小
- window_size:整数,正样本对之间的最大距离
- negative_samples:大于0的浮点数,等于0代表没有负样本,等于1代表负样本与正样本数目相同,以此类推(即负样本的数目是正样本的negative_samples倍)
- shuffle:布尔值,确定是否随机打乱样本
- categorical:布尔值,确定是否要使得返回的标签具有确定类别
- sampling_table:形如(vocabulary_size,)的numpy array,其中sampling_table[i]代表没有负样本或随机负样本。等于1为与正样本的数目相同 采样到该下标为i的单词的概率(假定该单词是数据库中第i常见的单词)
输出:函数的输出是一个(couples,labels)的元组,其中:
- couples是一个长为2的整数列表:[word_index,other_word_index]
- labels是一个仅由0和1构成的列表,1代表other_word_index在word_index的窗口,0代表other_word_index是词典里的随机单词。
- 如果设置categorical为True,则标签将以one-hot的方式给出,即1变为[0,1],0变为[1,0]
1.3、获取采样表make_sampling_table
keras.preprocessing.sequence.make_sampling_table(size, sampling_factor=1e-5)
该函数用以产生skipgrams中所需要的参数sampling_table。这是一个长为size的向量,sampling_table[i]代表采样到数据集中第i常见的词的概率(为平衡期起见,对于越经常出现的词,要以越低的概率采到它)
参数
- size:词典的大小
- sampling_factor:此值越低,则代表采样时更缓慢的概率衰减(即常用的词会被以更低的概率被采到),如果设置为1,则代表不进行下采样,即所有样本被采样到的概率都是1。
2、文本预处理
2.1、句子分割text_to_word_sequence
keras.preprocessing.text.text_to_word_sequence(text,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n',
lower=True,
split=" ")
本函数将一个句子拆分成单词构成的列表
参数
- text:字符串,待处理的文本
- filters:需要滤除的字符的列表或连接形成的字符串,例如标点符号。默认值为 ‘!"#$%&()*+,-./:;<=>?@[]^_`{|}~\t\n’,包含标点符号,制表符和换行符等
- lower:布尔值,是否将序列设为小写形式
- split:字符串,单词的分隔符,如空格
返回值:字符串列表
2.2、one-hot编码
keras.preprocessing.text.one_hot(text,
n,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n',
lower=True,
split=" ")
本函数将一段文本编码为one-hot形式的码,即仅记录词在词典中的下标。
【Tips】 从定义上,当字典长为n时,每个单词应形成一个长为n的向量,其中仅有单词本身在字典中下标的位置为1,其余均为0,这称为one-hot。
为了方便起见,函数在这里仅把“1”的位置,即字典中词的下标记录下来。
参数:
- n:整数,字典长度
返回值:
整数列表,每个整数是[1,n]之间的值,代表一个单词(不保证唯一性,即如果词典长度不够,不同的单词可能会被编为同一个码)。
2.3、特征哈希hashing_trick
keras.preprocessing.text.hashing_trick(text,
n,
hash_function=None,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n',
lower=True,
split=' ')
将文本转换为固定大小的哈希空间中的索引序列
参数
- n: 哈希空间的维度
- hash_function: 默认为 python hash 函数, 可以是 ‘md5’ 或任何接受输入字符串, 并返回 int 的函数. 注意 hash 不是一个稳定的哈希函数, 因此在不同执行环境下会产生不同的结果, 作为对比, ‘md5’ 是一个稳定的哈希函数.
返回值:整数列表
2.4、分词器Tokenizer
keras.preprocessing.text.Tokenizer(num_words=None,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n',
lower=True,
split=" ",
char_level=False)
Tokenizer是一个用于向量化文本,或将文本转换为序列(即单词在字典中的下标构成的列表,从1算起)的类。
构造参数
- 与text_to_word_sequence同名参数含义相同
- num_words:None或整数,处理的最大单词数量。若被设置为整数,则分词器将被限制为待处理数据集中最常见的num_words个单词
- char_level: 如果为 True, 每个字符将被视为一个标记
类方法
- fit_on_texts(texts),其中texts:要用以训练的文本列表
- texts_to_sequences(texts),其中texts:待转为序列的文本列表,返回值:序列的列表,列表中每个序列对应于一段输入文本
- texts_to_sequences_generator(texts),本函数是texts_to_sequences的生成器函数版,其中texts:待转为序列的文本列表。返回值:每次调用返回对应于一段输入文本的序列
- texts_to_matrix(texts, mode),其中texts:待向量化的文本列表,mode:‘binary’,‘count’,‘tfidf’,‘freq’之一,默认为‘binary’。返回值:形如(len(texts), nb_words)的numpy array
- fit_on_sequences(sequences),其中sequences:要用以训练的序列列表
- sequences_to_matrix(sequences),其中sequences:待向量化的序列列表,mode:‘binary’,‘count’,‘tfidf’,‘freq’之一,默认为‘binary’。返回值:形如(len(sequences), nb_words)的numpy array
属性
- word_counts:字典,将单词(字符串)映射为它们在训练期间出现的次数。仅在调用fit_on_texts之后设置。
- word_docs: 字典,将单词(字符串)映射为它们在训练期间所出现的文档或文本的数量。仅在调用fit_on_texts之后设置。
- word_index: 字典,将单词(字符串)映射为它们的排名或者索引。仅在调用fit_on_texts之后设置。
- document_count: 整数。分词器被训练的文档(文本或者序列)数量。仅在调用fit_on_texts或fit_on_sequences之后设置。
3、图片预处理
3.1、图片生成器ImageDataGenerator
keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
zca_epsilon=1e-6,
rotation_range=0.,
width_shift_range=0.,
height_shift_range=0.,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode='nearest',
cval=0.,
horizontal_flip=False,
vertical_flip=False,
rescale=None,
preprocessing_function=None,
data_format=K.image_data_format())
用以生成一个batch的图像数据,支持实时数据提升。训练时该函数会无限生成数据,直到达到规定的epoch次数为止。
参数
- featurewise_center:布尔值,使输入数据集去中心化(均值为0), 按feature执行
- samplewise_center:布尔值,使输入数据的每个样本均值为0
featurewise_std_normalization:布尔值,将输入除以数据集的标准差以完成标准化, 按feature执行 - samplewise_std_normalization:布尔值,将输入的每个样本除以其自身的标准差
- zca_whitening:布尔值,对输入数据施加ZCA白化
- zca_epsilon: ZCA使用的eposilon,默认1e-6
- rotation_range:整数,数据提升时图片随机转动的角度
- width_shift_range:浮点数,图片宽度的某个比例,数据提升时图片水平偏移的幅度
- height_shift_range:浮点数,图片高度的某个比例,数据提升时图片竖直偏移的幅度
- shear_range:浮点数,剪切强度(逆时针方向的剪切变换角度)
- zoom_range:浮点数或形如[lower,upper]的列表,随机缩放的幅度,若为浮点数,则相当于[lower,upper] = [1 - zoom_range, 1+zoom_range]
- channel_shift_range:浮点数,随机通道偏移的幅度
- fill_mode:;‘constant’,‘nearest’,‘reflect’或‘wrap’之一,当进行变换时超出边界的点将根据本参数给定的方法进行处理
- cval:浮点数或整数,当fill_mode=constant时,指定要向超出边界的点填充的值
- horizontal_flip:布尔值,进行随机水平翻转
- vertical_flip:布尔值,进行随机竖直翻转
- rescale: 重放缩因子,默认为None. 如果为None或0则不进行放缩,否则会将该数值乘到数据上(在应用其他变换之前)
- preprocessing_function: 将被应用于每个输入的函数。该函数将在任何其他修改之前运行。该函数接受一个参数,为一张图片(秩为3的numpy array),并且输出一个具有相同shape的numpy array
- data_format:字符串,“channel_first”或“channel_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channel_last”对应原本的“tf”,“channel_first”对应原本的“th”。以128x128的RGB图像为例,“channel_first”应将数据组织为(3,128,128),而“channel_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channel_last”
方法
- fit(x, augment=False,rounds=1):计算依赖于数据的变换所需要的统计信息(均值方差等),只有使用featurewise_center,featurewise_std_normalization或zca_whitening时需要此函数。
- X:numpy array,样本数据,秩应为4.在黑白图像的情况下channel轴的值为1,在彩色图像情况下值为3
- augment:布尔值,确定是否使用随即提升过的数据
- round:若设augment=True,确定要在数据上进行多少轮数据提升,默认值为1 seed: 整数,随机数种子
- flow(self, X, y, batch_size=32, shuffle=True, seed=None,save_to_dir=None, save_prefix=’’,save_format=‘png’):接收numpy数组和标签为参数,生成经过数据提升或标准化后的batch数据,并在一个无限循环中不断的返回batch数据
- x:样本数据,秩应为4.在黑白图像的情况下channel轴的值为1,在彩色图像情况下值为3 y:标签
- batch_size:整数,默认32 shuffle:布尔值,是否随机打乱数据,默认为True
- save_to_dir:None或字符串,该参数能让你将提升后的图片保存起来,用以可视化
- save_prefix:字符串,保存提升后图片时使用的前缀, 仅当设置了save_to_dir时生效
- save_format:“png"或"jpeg"之一,指定保存图片的数据格式,默认"jpeg”
- yields:形如(x,y)的tuple,x是代表图像数据的numpy数组.y是代表标签的numpy数组.该迭代器无限循环.
- seed: 整数,随机数种子
- flow_from_directory(directory):以文件夹路径为参数,生成经过数据提升/归一化后的数据,在一个无限循环中无限产生batch数据
- directory:目标文件夹路径,对于每一个类,该文件夹都要包含一个子文件夹.子文件夹中任何JPG、PNG、BNP、PPM的图片都会被生成器使用.详情请查看此脚本
- target_size: 整数tuple,默认为(256, 256). 图像将被resize成该尺寸
color_mode: 颜色模式,为"grayscale",“rgb"之一,默认为"rgb”.代表这些图片是否会被转换为单通道或三通道的图片. - classes: 可选参数,为子文件夹的列表,如[‘dogs’,‘cats’]默认为None. 若未提供,则该类别列表将从directory下的子文件夹名称/结构自动推断。每一个子文件夹都会被认为是一个新的类。(类别的顺序将按照字母表顺序映射到标签值)。通过属性class_indices可获得文件夹名与类的序号的对应字典。
- class_mode: “categorical”, “binary”, "sparse"或None之一. 默认为"categorical. 该参数决定了返回的标签数组的形式, "categorical"会返回2D的one-hot编码标签,"binary"返回1D的二值标签."sparse"返回1D的整数标签,如果为None则不返回任何标签, 生成器将仅仅生成batch数据, 这种情况在使用model.predict_generator()和model.evaluate_generator()等函数时会用到.
- batch_size: batch数据的大小,默认32
- shuffle: 是否打乱数据,默认为True
- seed: 可选参数,打乱数据和进行变换时的随机数种子
- save_to_dir: None或字符串,该参数能让你将提升后的图片保存起来,用以可视化
- save_prefix:字符串,保存提升后图片时使用的前缀, 仅当设置了save_to_dir时生效
- save_format:“png"或"jpeg"之一,指定保存图片的数据格式,默认"jpeg”
- flollow_links: 是否访问子文件夹中的软链接
例子
使用.flow()的例子
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
y_train = np_utils.to_categorical(y_train, num_classes)
y_test = np_utils.to_categorical(y_test, num_classes)
datagen = ImageDataGenerator(
featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True)
# compute quantities required for featurewise normalization
# (std, mean, and principal components if ZCA whitening is applied)
datagen.fit(x_train)
# fits the model on batches with real-time data augmentation:
model.fit_generator(datagen.flow(x_train, y_train, batch_size=32),
steps_per_epoch=len(x_train), epochs=epochs)
# here's a more "manual" example
for e in range(epochs):
print 'Epoch', e
batches = 0
for x_batch, y_batch in datagen.flow(x_train, y_train, batch_size=32):
loss = model.train(x_batch, y_batch)
batches += 1
if batches >= len(x_train) / 32:
# we need to break the loop by hand because
# the generator loops indefinitely
break
使用.flow_from_directory(directory)的例子
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
'data/train',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
'data/validation',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
model.fit_generator(
train_generator,
steps_per_epoch=2000,
epochs=50,
validation_data=validation_generator,
validation_steps=800)
同时变换图像和mask
# we create two instances with the same arguments
data_gen_args = dict(featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=90.,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
# Provide the same seed and keyword arguments to the fit and flow methods
seed = 1
image_datagen.fit(images, augment=True, seed=seed)
mask_datagen.fit(masks, augment=True, seed=seed)
image_generator = image_datagen.flow_from_directory(
'data/images',
class_mode=None,
seed=seed)
mask_generator = mask_datagen.flow_from_directory(
'data/masks',
class_mode=None,
seed=seed)
# combine generators into one which yields image and masks
train_generator = zip(image_generator, mask_generator)
model.fit_generator(
train_generator,
steps_per_epoch=2000,
epochs=50)
二、网络模型
网络模型可以将上面定义了各种基本网络层组合起来。
Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。
两类模型有一些方法是相同的:
model的方法:
model.summary() : 打印出模型概况,它实际调用的是keras.utils.print_summary
model.get_config() :返回包含模型配置信息的Python字典
model = Model.from_config(config) 模型从它的config信息中重构回去
model = Sequential.from_config(config) 模型从它的config信息中重构回去
model.get_weights():返回模型权重张量的列表,类型为numpy array
model.set_weights():从numpy array里将权重载入给模型
model.to_json:返回代表模型的JSON字符串,仅包含网络结构,不包含权值。可以从JSON字符串中重构原模型:
from models import model_from_json
json_string = model.to_json()
model = model_from_json(json_string)
model.to_yaml:与model.to_json类似,同样可以从产生的YAML字符串中重构模型
from models import model_from_yaml
yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)
model.save_weights(filepath):将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)
model.load_weights(filepath, by_name=False):从HDF5文件中加载权重到当前模型中, 默认情况下模型的结构将保持不变。如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重
keras有两种model,分别是Sequential模型和泛型模型
1、Sequential模型
Sequential是多个网络层的线性堆叠
可以通过向Sequential模型传递一个layer的list来构造该模型:
from keras.models import Sequential
from keras.layers import Dense, Activation
model = Sequential([
Dense(32, input_dim=784),
Activation('relu'),
Dense(10),
Activation('softmax'),
])
也可以通过.add()方法一个个的将layer加入模型中:
model = Sequential()
model.add(Dense(32, input_dim=784))
model.add(Activation('relu'))
还可以通过merge将两个Sequential模型通过某种方式合并
Sequential模型的方法:
compile(self, optimizer, loss, metrics=[], sample_weight_mode=None)
fit(self, x, y, batch_size=32, nb_epoch=10, verbose=1, callbacks=[], validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None)
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
#按batch获得输入数据对应的输出,函数的返回值是预测值的numpy array
predict(self, x, batch_size=32, verbose=0)
#按batch产生输入数据的类别预测结果,函数的返回值是类别预测结果的numpy array或numpy
predict_classes(self, x, batch_size=32, verbose=1)
#本函数按batch产生输入数据属于各个类别的概率,函数的返回值是类别概率的numpy array
predict_proba(self, x, batch_size=32, verbose=1)
train_on_batch(self, x, y, class_weight=None, sample_weight=None)
test_on_batch(self, x, y, sample_weight=None)
predict_on_batch(self, x)
fit_generator(self, generator, samples_per_epoch, nb_epoch, verbose=1, callbacks=[], validation_data=None, nb_val_samples=None, class_weight=None, max_q_size=10)
evaluate_generator(self, generator, val_samples, max_q_size=10)
2、泛型模型(函数式模型)
Keras泛型模型接口是:
用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径
适用于实现:全连接网络和多输入多输出模型
多输入多输出,官方例子给出:预测一条新闻的点赞转发数,主要输入是新闻本身,还可以加入额外输入,比如新闻发布日期,新闻作者等,具体的实现还是看官网文档吧:
http://keras-cn.readthedocs.io/en/latest/getting_started/functional_API/
所以感觉这个模型可以针对特定task搞一些创新哦
泛型模型model的属性:
model.layers:组成模型图的各个层
model.inputs:模型的输入张量列表
model.outputs:模型的输出张量列表
方法:类似序列模型的方法
补充get_layer
get_layer(self, name=None, index=None)
本函数依据模型中层的下标或名字获得层对象,泛型模型中层的下标依据自底向上,水平遍历的顺序。
name:字符串,层的名字
index: 整数,层的下标
函数的返回值是层对象
from keras.models import Model
from keras.layers import Input, Dense
a = Input(shape=(32,))
b = Dense(32)(a)
model = Model(inputs=a, outputs=b)
三、网络配置
compile(self, optimizer, loss, metrics=None, sample_weight_mode=None)
- optimizer:优化器
- loss:损失函数
- metrics:评估模型
- sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。默认为“None”,代表按样本赋权(1D权)。在下面fit函数的解释中有相关的参考内容。
- weighted_metrics:metrics列表,在训练和测试过程中,这些metrics将由sample_weight或clss_weight计算并赋权
- target_tensors: 默认情况下,Keras将为模型的目标创建一个占位符,该占位符在训练过程中将被目标数据代替。如果你想使用自己的目标张量(相应的,Keras将不会在训练时期望为这些目标张量载入外部的numpy数据),你可以通过该参数手动指定。目标张量可以是一个单独的张量(对应于单输出模型),也可以是一个张量列表,或者一个name->tensor的张量字典。
- kwargs:使用TensorFlow作为后端请忽略该参数,若使用Theano/CNTK作为后端,kwargs的值将会传递给 K.function。如果使用TensorFlow为后端,这里的值会被传给tf.Session.run
在开始进行训练前,我们需要配置模型训练的结构,也就是编译网络模型。
1、目标函数(损失函数loss)
model.compile(loss='mean_squared_error', optimizer='sgd')
#或者
from keras import losses
model.compile(loss=losses.mean_squared_error, optimizer='sgd')
可以通过传递预定义目标函数名字指定目标函数,也可以传递一个Theano/TensroFlow的符号函数作为目标函数,该函数对每个数据点应该只返回一个标量值,并以下列两个参数为参数:
可用的目标函数:
1.1、mean_squared_error:均方误差,也称标准差,缩写为MSE,可以反映一个数据集的离散程度。标准误差定义为各测量值误差的平方和的平均值的平方根,故又称为均方误差。
公式意义:可以理解为一个从n维空间的一个点到一条直线的距离的函数。(此为在图形上的理解,关键看个人怎么理解了)
1.2、mean_absolute_error:平均绝对误差,缩写MAE。平均绝对误差是所有单个观测值与算术平均值的偏差的绝对值的平均。
1.3、mean_absolute_percentage_error译为平均绝对百分比误差 ,缩写MAPE。
1.4、mean_squared_logarithmic_error译为均方对数误差,缩写MSLE。
1.5、 squared_hinge
$ sh = \frac{1}{m}\sum_{i}m(max(0,1-y_i*\widetilde{y_i})2) $
1.6、hinge
$ hinge= \frac{1}{m}\sum_{i}^m(max(0,1-y_i*\widetilde{y_i})) $
1.7、binary_crossentropy即对数损失函数,log loss,与sigmoid相对应的损失函数。该函数主要用来做极大似然估计的,这样做会方便计算。因为极大似然估计用来求导会非常的麻烦,一般是求对数然后求导再求极值点。损失函数一般是每条数据的损失之和,恰好取了对数,就可以把每个损失相加起来。负号的意思是极大似然估计对应最小损失。
$ L(Y,P(Y|X)) = -logP(Y|X) $
1.8、categorical_crossentropy多分类的对数损失函数,与softmax分类器相对应的损失函数,理同上。
注意: 当使用"categorical_crossentropy"作为目标函数时,标签应该为多类模式,即one-hot编码的向量,而不是单个数值. 可以使用工具中的to_categorical函数完成该转换.示例如下:
from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels, num_classes=None)
tip:此损失函数与上一类同属对数损失函数,sigmoid和softmax的区别主要是,sigmoid用于二分类,softmax用于多分类。
2、优化器optimizer
from keras import optimizers
model = Sequential()
model.add(Dense(64, kernel_initializer='uniform', input_shape=(10,)))
model.add(Activation('tanh'))
model.add(Activation('softmax'))
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
#或者
model.compile(loss='mean_squared_error', optimizer='sgd')
可以在调用model.compile()之前初始化一个优化器对象,然后传入该函数(如上所示),也可以在调用model.compile()时传递一个预定义优化器名。在后者情形下,优化器的参数将使用默认值
SGD
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
随机梯度下降法,支持动量参数,支持学习衰减率,支持Nesterov动量
参数
- lr:大或等于0的浮点数,学习率
- momentum:大或等于0的浮点数,动量参数
- decay:大或等于0的浮点数,每次更新后的学习率衰减值
- nesterov:布尔值,确定是否使用Nesterov动量
RMSprop
keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=1e-06)
除学习率可调整外,建议保持优化器的其他默认参数不变
该优化器通常是面对递归神经网络时的一个良好选择
参数
- lr:大或等于0的浮点数,学习率
- rho:大或等于0的浮点数
- epsilon:大或等于0的小浮点数,防止除0错误
Adagrad
keras.optimizers.Adagrad(lr=0.01, epsilon=1e-06)
建议保持优化器的默认参数不变
参数
- lr:大或等于0的浮点数,学习率
- epsilon:大或等于0的小浮点数,防止除0错误
Adadelta
keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=1e-06)
建议保持优化器的默认参数不变
参数
- lr:大或等于0的浮点数,学习率
- rho:大或等于0的浮点数
- epsilon:大或等于0的小浮点数,防止除0错误
Adam
keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
该优化器的默认值来源于参考文献
参数
- lr:大或等于0的浮点数,学习率
- beta_1/beta_2:浮点数, 0<beta<1,通常很接近1
- epsilon:大或等于0的小浮点数,防止除0错误
Adamax
keras.optimizers.Adamax(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
Adamax优化器来自于Adam的论文的Section7,该方法是基于无穷范数的Adam方法的变体。
默认参数由论文提供
参数
- lr:大或等于0的浮点数,学习率
- beta_1/beta_2:浮点数, 0<beta<1,通常很接近1
- epsilon:大或等于0的小浮点数,防止除0错误
Nadam
keras.optimizers.Nadam(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=1e-08, schedule_decay=0.004)
Nesterov Adam optimizer: Adam本质上像是带有动量项的RMSprop,Nadam就是带有Nesterov 动量的Adam RMSprop
默认参数来自于论文,推荐不要对默认参数进行更改。
参数
- lr:大或等于0的浮点数,学习率
- beta_1/beta_2:浮点数, 0<beta<1,通常很接近1
- epsilon:大或等于0的小浮点数,防止除0错误
TFOptimizer
keras.optimizers.TFOptimizer(optimizer)
TF优化器的包装器
3、激活函数Activations
激活函数可以通过设置单独的激活层实现,也可以在构造层对象时通过传递activation参数实现。
from keras.layers import Activation, Dense
model.add(Dense(64))
model.add(Activation('tanh'))
等价于
model.add(Dense(64, activation='tanh'))
也可以通过传递一个逐元素运算的Theano/TensorFlow/CNTK函数来作为激活函数:
from keras import backend as K
def tanh(x):
return K.tanh(x)
model.add(Dense(64, activation=tanh))
model.add(Activation(tanh))
预定义激活函数
- softmax:对输入数据的最后一维进行softmax,输入数据应形如(nb_samples, nb_timesteps,nb_dims)或(nb_samples,nb_dims)
- elu
- selu: 可伸缩的指数线性单元(Scaled Exponential Linear Unit),参考Self-Normalizing Neural Networks
- softplus
- softsign
- relu
- tanh
- sigmoid
- hard_sigmoid
- linear
4、性能评估metrics
性能评估模块提供了一系列用于模型性能评估的函数,这些函数在模型编译时由metrics关键字设置。性能评估函数类似与目标函数, 只不过该性能的评估结果讲不会用于训练.
可以通过字符串来使用域定义的性能评估函数
model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=['mae', 'acc'])
也可以自定义一个Theano/TensorFlow函数并使用之
from keras import metrics
model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=[metrics.mae, metrics.categorical_accuracy])
参数
y_true:真实标签,theano/tensorflow张量
y_pred:预测值, 与y_true形式相同的theano/tensorflow张量
返回值:单个用以代表输出各个数据点上均值的值。
可用预定义张量
除fbeta_score额外拥有默认参数beta=1外,其他各个性能指标的参数均为y_true和y_pred
- binary_accuracy: 对二分类问题,计算在所有预测值上的平均正确率
- categorical_accuracy:对多分类问题,计算在所有预测值上的平均正确率
- sparse_categorical_accuracy:与categorical_accuracy相同,在对稀疏的目标值预测时有用
- top_k_categorical_accracy: 计算top-k正确率,当预测值的前k个值中存在目标类别即认为预测正确
- sparse_top_k_categorical_accuracy:与top_k_categorical_accracy作用相同,但适用于稀疏情况
定制评估函数
定制的评估函数可以在模型编译时传入,该函数应该以(y_true, y_pred)为参数,并返回单个张量,或从metric_name映射到metric_value的字典,下面是一个示例:
(y_true, y_pred) as arguments and return a single tensor value.
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred])
5、初始化方法Initializers
初始化方法定义了对Keras层设置初始化权重的方法
不同的层可能使用不同的关键字来传递初始化方法,一般来说指定初始化方法的关键字是kernel_initializer 和 bias_initializer,例如:
model.add(Dense(64,
kernel_initializer='random_uniform',
bias_initializer='zeros'))
一个初始化器可以由字符串指定(必须是下面的预定义初始化器之一),或一个callable的函数,例如
from keras import initializers
model.add(Dense(64, kernel_initializer=initializers.random_normal(stddev=0.01)))
# also works; will use the default parameters.
model.add(Dense(64, kernel_initializer='random_normal'))
Initializer
Initializer是所有初始化方法的父类,不能直接使用,如果想要定义自己的初始化方法,请继承此类。
预定义初始化方法
- keras.initializers.Zeros()
全零初始化 - keras.initializers.Ones()
全1初始化 - keras.initializers.Constant(value=0)
初始化为固定值value - keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None))
正态分布初始化(mean:均值, stddev:标准差, seed:随机数种子) - keras.initializers.RandomUniform(minval=-0.05, maxval=0.05, seed=None)
均匀分布初始化( minval:均匀分布下边界, maxval:均匀分布上边界 ,seed:随机数种子) - keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)
截尾高斯分布初始化,该初始化方法与RandomNormal类似,但位于均值两个标准差以外的数据将会被丢弃并重新生成,形成截尾分布。该分布是神经网络权重和滤波器的推荐初始化方法。(mean:均值、stddev:标准差、seed:随机数种子) - keras.initializers.VarianceScaling(scale=1.0, mode=‘fan_in’, distribution=‘normal’, seed=None)
该初始化方法能够自适应目标张量的shape。(scale: 放缩因子,正浮点数;mode: 字符串,“fan_in”,“fan_out”或“fan_avg”fan_in", “fan_out”, “fan_avg”;distribution: 字符串,“normal”或“uniform”;seed: 随机数种子)
当distribution="normal"时,样本从0均值,标准差为sqrt(scale / n)的截尾正态分布中产生。其中: - 当
mode = "fan_in"
时,权重张量的输入单元数。 - 当
mode = "fan_out"
时,权重张量的输出单元数 - 当
mode = "fan_avg"
时,权重张量的输入输出单元数的均值
当distribution="uniform"时,权重从[-limit, limit]范围内均匀采样,其中limit = limit = sqrt(3 * scale / n) - keras.initializers.Orthogonal(gain=1.0, seed=None)
用随机正交矩阵初始化(gain: 正交矩阵的乘性系数;seed:随机数种子) - keras.initializers.Identity(gain=1.0)
使用单位矩阵初始化,仅适用于2D方阵(gain:单位矩阵的乘性系数) - lecun_uniform(seed=None)
LeCun均匀分布初始化方法,参数由[-limit, limit]的区间中均匀采样获得,其中limit=sqrt(3 / fan_in), fin_in是权重向量的输入单元数(扇入) - lecun_normal(seed=None)
LeCun正态分布初始化方法,参数由0均值,标准差为stddev = sqrt(1 / fan_in)的正态分布产生,其中fan_in和fan_out是权重张量的扇入扇出(即输入和输出单元数目) - glorot_normal(seed=None)
Glorot正态分布初始化方法,也称作Xavier正态分布初始化,参数由0均值,标准差为sqrt(2 / (fan_in + fan_out))的正态分布产生,其中fan_in和fan_out是权重张量的扇入扇出(即输入和输出单元数目) - glorot_uniform(seed=None)
Glorot均匀分布初始化方法,又成Xavier均匀初始化,参数从[-limit, limit]的均匀分布产生,其中limit为sqrt(6 / (fan_in + fan_out))。fan_in为权值张量的输入单元数,fan_out是权重张量的输出单元数。 - he_normal(seed=None)
He正态分布初始化方法,参数由0均值,标准差为sqrt(2 / fan_in) 的正态分布产生,其中fan_in权重张量的扇入 - he_normal(seed=None)
LeCun均匀分布初始化方法,参数由[-limit, limit]的区间中均匀采样获得,其中limit=sqrt(6 / fan_in), fin_in是权重向量的输入单元数(扇入)
自定义初始化器
如果需要传递自定义的初始化器,则该初始化器必须是callable的,并且接收shape(将被初始化的张量shape)和dtype(数据类型)两个参数,并返回符合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, init=my_init))
6、正则项
正则项在优化过程中层的参数或层的激活值添加惩罚项,这些惩罚项将与损失函数一起作为网络的最终优化目标
惩罚项基于层进行惩罚,目前惩罚项的接口与层有关,但Dense, Conv1D, Conv2D, Conv3D具有共同的接口。
这些层有三个关键字参数以施加正则项:
kernel_regularizer:施加在权重上的正则项,为keras.regularizer.Regularizer对象
bias_regularizer:施加在偏置向量上的正则项,为keras.regularizer.Regularizer对象
activity_regularizer:施加在输出上的正则项,为keras.regularizer.Regularizer对象
例子
from keras import regularizers
model.add(Dense(64, input_dim=64,
kernel_regularizer=regularizers.l2(0.01),
activity_regularizer=regularizers.l1(0.01)))
可用正则项
keras.regularizers.l1(0.)
keras.regularizers.l2(0.)
keras.regularizers.l1_l2(0.)
开发新的正则项
任何以权重矩阵作为输入并返回单个数值的函数均可以作为正则项,示例:
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)
7、约束项
来自constraints模块的函数在优化过程中为网络的参数施加约束
惩罚项基于层进行惩罚,目前惩罚项的接口与层有关,但Dense, Conv1D, Conv2D, Conv3D具有共同的接口。
这些层通过一下关键字施加约束项
- kernel_constraint:对主权重矩阵进行约束
- bias_constraint:对偏置向量进行约束
from keras.constraints import maxnorm
model.add(Dense(64, kernel_constraint=max_norm(2.)))
预定义约束项
- max_norm(m=2):最大模约束
- non_neg():非负性约束
- unit_norm():单位范数约束,强制矩阵沿最后一个轴拥有单位范数
- min_max_norm(min_value=0.0, max_value=1.0, rate=1.0, axis=0): 最小/最大范数约束
8、回调函数Callbacks
回调函数是一组在训练的特定阶段被调用的函数集,你可以使用回调函数来观察训练过程中网络内部的状态和统计信息。通过传递回调函数列表到模型的.fit()中,即可在给定的训练阶段调用该函数集中的函数。
【Tips】虽然我们称之为回调“函数”,但事实上Keras的回调函数是一个类,回调函数只是习惯性称呼
8.1、Callback
keras.callbacks.Callback()
这是回调函数的抽象类,定义新的回调函数必须继承自该类
类属性
- params:字典,训练参数集(如信息显示方法verbosity,batch大小,epoch数)
- model:keras.models.Model对象,为正在训练的模型的引用
回调函数以字典logs为参数,该字典包含了一系列与当前batch或epoch相关的信息。
目前,模型的.fit()中有下列参数会被记录到logs中:
- 在每个epoch的结尾处(on_epoch_end),logs将包含训练的正确率和误差,acc和loss,如果指定了验证集,还会包含验证集正确率和误差val_acc)和val_loss,val_acc还额外需要在.compile中启用metrics=[‘accuracy’]。
- 在每个batch的开始处(on_batch_begin):logs包含size,即当前batch的样本数
- 在每个batch的结尾处(on_batch_end):logs包含loss,若启用accuracy则还包含acc
8.2、BaseLogger
keras.callbacks.BaseLogger()
该回调函数用来对每个epoch累加metrics指定的监视指标的epoch平均值
该回调函数在每个Keras模型中都会被自动调用
8.3、ProgbarLogger
keras.callbacks.ProgbarLogger()
该回调函数用来将metrics指定的监视指标输出到标准输出上
8.4、History
keras.callbacks.History()
该回调函数在Keras模型上会被自动调用,History对象即为fit方法的返回值
8.5、ModelCheckpoint
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)
该回调函数将在每个epoch后保存模型到filepath
filepath可以是格式化的字符串,里面的占位符将会被epoch值和传入on_epoch_end的logs关键字所填入
例如,filepath若为weights.{epoch:02d-{val_loss:.2f}}.hdf5,则会生成对应epoch和验证集loss的多个文件。
参数
- filename:字符串,保存模型的路径
- monitor:需要监视的值
- verbose:信息展示模式,0或1
- save_best_only:当设置为True时,将只保存在验证集上性能最好的模型
- mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
- save_weights_only:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
- period:CheckPoint之间的间隔的epoch数
8.6、EarlyStopping
keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto')
当监测值不再改善时,该回调函数将中止训练
参数
- monitor:需要监视的量
- patience:当early stop被激活(如发现loss相比上一个epoch训练没有下降),则经过patience个epoch后停止训练。
- verbose:信息展示模式
- mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。
8.7、RemoteMonitor
keras.callbacks.RemoteMonitor(root='http://localhost:9000')
该回调函数用于向服务器发送事件流,该回调函数需要requests库
参数
- root:该参数为根url,回调函数将在每个epoch后把产生的事件流发送到该地址,事件将被发往root +’/publish/epoch/end/’。发送方法为HTTP POST,其data字段的数据是按JSON格式编码的事件字典。
8.8、LearningRateScheduler
keras.callbacks.LearningRateScheduler(schedule)
该回调函数是学习率调度器
参数
- schedule:函数,该函数以epoch号为参数(从0算起的整数),返回一个新学习率(浮点数)
8.9、TensorBoard
keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, write_graph=True, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)
该回调函数是一个可视化的展示器
TensorBoard是TensorFlow提供的可视化工具,该回调函数将日志信息写入TensorBorad,使得你可以动态的观察训练和测试指标的图像以及不同层的激活值直方图。
8.10、ReduceLROnPlateau
keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', epsilon=0.0001, cooldown=0, min_lr=0)
当评价指标不在提升时,减少学习率
当学习停滞时,减少2倍或10倍的学习率常常能获得较好的效果。该回调函数检测指标的情况,如果在patience个epoch中看不到模型性能提升,则减少学习率
参数
- monitor:被监测的量
- factor:每次减少学习率的因子,学习率将以lr = lr*factor的形式被减少
- patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
- mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。
- epsilon:阈值,用来确定是否进入检测值的“平原区”
- cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
- min_lr:学习率的下限
8.11、CSVLogger
keras.callbacks.CSVLogger(filename, separator=',', append=False)
将epoch的训练结果保存在csv文件中,支持所有可被转换为string的值,包括1D的可迭代数值如np.ndarray.
参数
- fiename:保存的csv文件名,如run/log.csv
- separator:字符串,csv分隔符
- append:默认为False,为True时csv文件如果存在则继续写入,为False时总是覆盖csv文件
8.12、LambdaCallback
keras.callbacks.LambdaCallback(on_epoch_begin=None, on_epoch_end=None, on_batch_begin=None, on_batch_end=None, on_train_begin=None, on_train_end=None)
用于创建简单的callback的callback类
该callback的匿名函数将会在适当的时候调用,注意,该回调函数假定了一些位置参数on_eopoch_begin和on_epoch_end假定输入的参数是epoch, logs. on_batch_begin和on_batch_end假定输入的参数是batch, logs,on_train_begin和on_train_end假定输入的参数是logs
参数
- on_epoch_begin: 在每个epoch开始时调用
- on_epoch_end: 在每个epoch结束时调用
- on_batch_begin: 在每个batch开始时调用
- on_batch_end: 在每个batch结束时调用
- on_train_begin: 在训练开始时调用
- on_train_end: 在训练结束时调用
编写自己的回调函数
我们可以通过继承keras.callbacks.Callback编写自己的回调函数,回调函数通过类成员self.model访问访问,该成员是模型的一个引用。
这里是一个简单的保存每个batch的loss的回调函数:
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.losses = []
def on_batch_end(self, batch, logs={}):
self.losses.append(logs.get('loss'))
四、模型训练
fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
1、输入参数
本函数将模型训练nb_epoch轮,其参数有:
x:输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
y:标签,numpy array
batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
epochs:整数,训练终止时的epoch值,训练将在达到该epoch值时停止,当没有设置initial_epoch时,它就是训练的总轮数,否则训练的总轮数为epochs - inital_epoch
verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
validation_data:形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。
class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)
sample_weight:权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。
2、返回值
fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况。
五、模型评估
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
1、输入参数:
本函数按batch计算在某些输入数据上模型的误差,其参数有:
x:输入数据,与fit一样,是numpy array或numpy array的list
y:标签,numpy array
batch_size:整数,含义同fit的同名参数
verbose:含义同fit的同名参数,但只能取0或1
sample_weight:numpy array,含义同fit的同名参数
2、返回值
本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。
六、模型预测
1、按batch获得输入数据对应的输出
predict(self, x, batch_size=32, verbose=0)
函数的返回值是预测值的numpy array
2、在一个batch的数据上进行一次参数更新
train_on_batch(self, x, y, class_weight=None, sample_weight=None)
函数返回训练误差的标量值或标量值的list,与evaluate的情形相同。
3、在一个batch的样本上对模型进行评估
test_on_batch(self, x, y, sample_weight=None)
函数的返回与evaluate的情形相同
4、在一个batch的样本上对模型进行测试
predict_on_batch(self, x)
函数返回模型在一个batch上的预测结果