Keras
keras简介
keras的模型
模型的定义
keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。
(a)Sequential顺序模型
单输入单输出,一条路通到底,层与层之间只有相邻关系,没有跨层连接。这种模型编译速度快,操作也比较简单
model = Sequential([
Dense(32, units=784),
Activation('relu'),
Dense(10),
Activation('softmax'),
])
也可以通过.add()
方法一个个的将layer加入模型中:
# LeNet的定义示例:
def build_model():
model = Sequential()
model.add(Conv2D(6, (5, 5), padding='valid', activation = 'relu', kernel_initializer='he_normal', input_shape=(32,32,3)))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(Conv2D(16, (5, 5), padding='valid', activation = 'relu', kernel_initializer='he_normal'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(Flatten())
model.add(Dense(120, activation = 'relu', kernel_initializer='he_normal'))
model.add(Dense(84, activation = 'relu', kernel_initializer='he_normal'))
model.add(Dense(10, activation = 'softmax', kernel_initializer='he_normal'))
return model
(b)函数式Model类模型
多输入多输出,层与层之间任意连接。这种模型编译速度慢。
在函数式 API 中,给定一些输入张量和输出张量,可以通过以下方式实例化一个model:
# LeNet的定义示意
def build_model():
input=Input(shape=(32,32,3))
x = Conv2D(6, (5, 5), padding='valid', activation='relu', kernel_initializer='he_normal')(img_input)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
x = Conv2D(16, (5, 5), padding='valid', activation='relu', kernel_initializer='he_normal', name='conv211')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
x = Flatten()(x)
x = Dense(120, activation='relu', kernel_initializer='he_normal')(x)
x = Dense(84, activation='relu', kernel_initializer='he_normal')(x)
output = Dense(5, activation='softmax', kernel_initializer='he_normal')(x)
model=Model(input,output)
return model
模型的配置训练
compile配置模型
在训练模型之前,我们需要通过compile来对学习过程进行配置。compile接收三个参数:
优化器optimizer:该参数可指定为已预定义的优化器名,如rmsprop、adagrad,或一个Optimizer类的对象,详情见optimizers
损失函数loss:该参数为模型试图最小化的目标函数,它可为预定义的损失函数名,如categorical_crossentropy、mse,也可以为一个损失函数。详情见losses
指标列表metrics:对分类问题,我们一般将该列表设置为metrics=[‘accuracy’]。指标可以是一个预定义指标的名字,也可以是一个用户定制的函数.指标函数应该返回单个张量,或一个完成metric_name - > metric_value映射的字典.请参考性能评估
model.compile(optimizer='sgd',
loss='categorical_crossentropy',
metrics=['accuracy'])
fit训练模型
Keras以Numpy数组作为输入数据和标签的数据类型。训练模型一般使用fit函数
model.fit(x_train, y_train,
epochs=20,
batch_size=128,
validation_data)
predict模型预测
本函数按batch获得输入数据对应的输出,
函数的返回值是预测值的numpy array
model.predict(x, batch_size=32)
fit_generator
利用Python的生成器,逐个生成数据的batch并进行训练。生成器与模型将并行执行以提高效率。例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练
model.fit_generator(datagen.flow(x_train,y_train,batch_size=batch_size),epochs=epochs,validation_data=(x_test,y_test))
def generate_arrays_from_file(path):
while 1:
f = open(path)
for line in f:
# create numpy arrays of input data
# and labels, from each line in the file
x1, x2, y = process_line(line)
yield ({'input_1': x1, 'input_2': x2}, {'output': y})
f.close()
model.fit_generator(generate_arrays_from_file('/my_file.txt'),
steps_per_epoch=10000, epochs=10)
模型的保存和加载
你可以使用model.save(filepath)将Keras模型和权重保存在一个HDF5文件中,该文件将包含:
- 模型的结构,以便重构该模型
- 模型的权重
- 训练配置(损失函数,优化器等)
- 优化器的状态,以便于从上次训练中断的地方开始训练配置
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')
如果需要保存模型的权重,可通过下面的代码利用HDF5进行保存。注意,在使用前需要确保你已安装了HDF5和其Python库h5py
model.save_weights('my_model_weights.h5')
如果你需要在代码中初始化一个完全相同的模型,请使用:
model.load_weights('my_model_weights.h5')
如果你需要加载权重到不同的网络结构(有些层一样)中,例如fine-tune或transfer-learning,你可以通过层名字来加载模型:
model.load_weights('my_model_weights.h5', by_name=True)
数据预处理与数据提升
keras集成数据库的引用
CIFAR10
from keras.datasets import cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
CIFAR100
from keras.datasets import cifar100
(x_train, y_train), (x_test, y_test) = cifar100.load_data(label_mode='fine')
MNIST
from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
图片生成器ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
参数
rotation_range
是一个0~180的度数,用来指定随机选择图片的角度。
width_shift
和height_shift
用来指定水平和竖直方向随机移动的程度,这是两个0~1之间的比例。
rescale
值将在执行其他处理前乘到整个图像上,我们的图像在RGB通道都是0 ~ 255的整数,这样的操作可能使图像的值过高或过低,所以我们将这个值定为0~1之间的数。
shear_range
是用来进行剪切变换的程度,参考剪切变换
zoom_range
用来进行随机的放大
horizontal_flip
随机的对图片进行水平翻转,这个参数适用于水平翻转不影响图片语义的时候
fill_mode
用来指定当需要进行像素填充,如旋转,水平和竖直位移时,如何填充新出现的像素
使用.flow()的方法
model.fit_generator(datagen.flow(x_train, y_train, batch_size=32),
epochs=epochs,validation_data=(x_test,y_test))
flow_from_directory(directory): 以文件夹路径为参数,生成经过数据提升/归一化后的数据,在一个无限循环中无限产生batch数据
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)
keras的常用层
卷积层Conv2D
Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
二维卷积层,即对图像的空域卷积。该层对二维输入进行滑动窗卷积,当使用该层作为第一层时,应提供input_shape
参数。例如input_shape = (128,128,3)代表128*128的彩色RGB图像(data_format=‘channels_last’)
x = Conv2D(64, kernel_size=(3, 3), strides=(1, 1), padding='same', kernel_initializer=he_normal(),
kernel_regularizer=regularizers.l2(weight_decay), use_bias=False)(img_input)
参数:
filters
:卷积核的数目(即输出的维度)
kernel_size
:单个整数或由两个整数构成的list/tuple,卷积核的宽度和长度。如为单个整数,则表示在各个空间维度的相同长度。
strides
:单个整数或由两个整数构成的list/tuple,为卷积的步长。如为单个整数,则表示在各个空间维度的相同步长。任何不为1的strides均与任何不为1的dilation_rate均不兼容
padding
:补0策略,为“valid”, “same”
。“valid”代表只进行有效的卷积,即对边界数据不处理。“same”代表保留边界处的卷积结果,通常会导致输出shape与输入shape相同。
activation
:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)
dilation_rate
:单个整数或由两个个整数构成的list/tuple,指定dilated
convolution
中的膨胀比例。任何不为1的dilation_rate均与任何不为1的strides均不兼容。
use_bias
:布尔值,是否使用偏置项
kernel_initializer
:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers
bias_initializer
:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers
kernel_regularizer
:施加在权重上的正则项,为Regularizer对象
bias_regularizer
:施加在偏置向量上的正则项,为Regularizer对象
activity_regularizer
:施加在输出上的正则项,为Regularizer对象
kernel_constraints
:施加在权重上的约束项,为Constraints对象
bias_constraints
:施加在偏置上的约束项,为Constraints对象
Dense层
Dense就是常用的全连接层,所实现的运算是output = activation(dot(input, kernel)+bias)
。其中activation
是逐元素计算的激活函数,kernel
是本层的权值矩阵,bias
为偏置向量,只有当use_bias=True
才会添加。
x = Dense(120, activation='relu', kernel_initializer='he_normal')(x)
Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
units
:大于0的整数,代表该层的输出维度。
activation
:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)
use_bias
: 布尔值,是否使用偏置项
kernel_initializer
:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers
bias_initializer
:偏置向量初始化方法,为预定义初始化方法名的字符串,或用于初始化偏置向量的初始化器。
kernel_regularizer
:施加在权重上的正则项,为Regularizer对象
bias_regularizer
:施加在偏置向量上的正则项,为Regularizer对象
activity_regularizer
:施加在输出上的正则项,为Regularizer对象
kernel_constraints
:施加在权重上的约束项,为Constraints对象
bias_constraints
:施加在偏置上的约束项,为Constraints对象
Pooling层
MaxPooling2D
为空域信号施加最大值池化
x = MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='valid')
pool_size
:整数或长为2的整数tuple,代表在两个方向(竖直,水平)上的下采样因子,如取(2,2)将使图片在两个维度上均变为原长的一半。为整数意为各个维度值相同且为该数字。
strides
:整数或长为2的整数tuple,或者None,步长值。
border_mode
:‘valid’或者‘same’
AveragePooling2D
为空域信号施加平均值池化
x = AveragePooling2D(pool_size=(2, 2), strides=(1, 1), padding='valid')
批标准化Batch Normalization
该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
BatchNormalization(epsilon=1e-06, mode=0, axis=-1, momentum=0.9, weights=None, beta_init='zero', gamma_init='one')
epsilon
:大于0的小浮点数,用于防止除0错误
mode
:整数,指定规范化的模式,取0或1
axis
:整数,指定当mode=0时规范化的轴。例如输入是形如(samples,channels,rows,cols)的4D图像张量,则应设置规范化的轴为1,意味着对每个特征图进行规范化
momentum
:在按特征规范化时,计算数据的指数平均数和标准差时的动量
Activation层
激活函数可以通过设置单独的激活层实现,也可以在构造层对象时通过传递activation参数实现。
x=Activation('tanh')(x)
也可以通过传递一个逐元素运算的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
: 可伸缩的指数线性单元
●softplus
●softsign
●relu
●tanh
●sigmoid
●hard_sigmoid
●linear
Dropout层
为输入数据施加Dropout。Dropout将在训练过程中每次更新参数时随机断开一定百分比(p)的输入神经元连接,Dropout层用于防止过拟合。
keras.layers.core.Dropout(p)
p
:0~1的浮点数,控制需要断开的链接的比例
Flatten层
keras.layers.core.Flatten()
Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
Merge层
Merge层提供了一系列用于融合两个层或两个张量的层对象和方法。以大写首字母开头的是Layer类,以小写字母开头的是张量的函数。小写字母开头的张量函数在内部实际上是调用了大写字母开头的层。
以两个层或两个层的输出张量相加为例,Add及add的用法:
Add
import keras
input1 = keras.layers.Input(shape=(16,))
x1 = keras.layers.Dense(8, activation='relu')(input1)
input2 = keras.layers.Input(shape=(32,))
x2 = keras.layers.Dense(8, activation='relu')(input2)
Add:
added = keras.layers.Add()([x1, x2])
add:
added = keras.layers.add([x1, x2])
Concatenate
该层接收一个列表的同shape张量,并返回它们的按照给定轴相接构成的向量。
keras.layers.Concatenate(axis=-1)
axis
: 想接的轴
Dot
计算两个tensor中样本的张量乘积。例如,如果两个张量a和b的shape都为(batch_size, n),则输出为形如(batch_size,1)的张量,结果张量每个batch的数据都是a[i,:]和b[i,:]的矩阵(向量)点积。
keras.layers.Dot(axes, normalize=False)
●
axes
: 整数或整数的tuple,执行乘法的轴。
●normalize
: 布尔值,是否沿执行成绩的轴做L2规范化,如果设为True,那么乘积的输出是两个样本的余弦相似性。
优化器optimizers
from keras import optimizers
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
可以在调用model.compile()
之前初始化一个优化器对象,然后传入该函数(如上所示),也可以在调用model.compile()
时传递一个预定义优化器名。在后者情形下,优化器的参数将使用默认值。
# pass optimizer by name: default parameters will be used
model.compile(loss='mean_squared_error', optimizer='sgd')
SGD
随机梯度下降法,支持动量参数,支持学习衰减率,支持Nesterov动量
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
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.Adadelta(lr=1.0, rho=0.95, epsilon=1e-06)
lr
:大或等于0的浮点数,初始学习率
epsilon
:大或等于0的小浮点数,防止除0错误
Adadelta
keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=1e-06)
lr:大或等于0的浮点数,学习率
epsilon:大或等于0的小浮点数,防止除0错误
rho:大或等于0的浮点数
这里ρ是衰减系数,通过这个衰减系数,我们令每一个时刻的gt随之时间按照ρ指数衰减,这样就相当于我们仅使用离当前时刻比较近的gt信息,从而使得还很长时间之后,参数仍然可以得到更新。
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错误
目标函数objectives
目标函数,或称损失函数,是编译一个模型必须的两个参数之一:
model.compile(loss='mean_squared_error', optimizer='sgd')
可以通过传递预定义目标函数名字指定目标函数,也可以传递一个Theano/TensroFlow的符号函数作为目标函数,该函数对每个数据点应该只返回一个标量值,并以下列两个参数为参数:
y_true
:真实的数据标签,Theano/TensorFlow张量
y_pred
:预测值,与y_true相同shape的Theano或 TensorFlow张量
真实的优化目标函数是在各个数据点得到的损失函数值之和的均值
●
mean_squared_error
或mse
●mean_absolute_error
或mae
●mean_absolute_percentage_error
或mape
●mean_squared_logarithmic_error
或msle
●squared_hinge
●hinge
●binary_crossentropy
(亦称作对数损失,logloss)
●categorical_crossentropy
:亦称作多类的对数损失,注意使用该目标函数时,需要将标签转化为形如(nb_samples, nb_classes)
的二值序列
●sparse_categorical_crossentrop
:如上,但接受稀疏标签。注意,使用该函数时仍然需要你的标签与输出值的维度相同,你可能需要在标签数据上增加一个维度:np.expand_dims(y,-1)
●kullback_leibler_divergence
:从预测值概率分布Q到真值概率分布P的信息增益,用以度量两个分布的差异.
●poisson
:即(predictions - targets * log(predictions))
的均值
●cosine_proximity
:即预测值与真实标签的余弦距离平均值的相反数
注意: 当使用"categorical_crossentropy
"作为目标函数时,标签应该为多类模式,即one-hot编码的向量,而不是单个数值. 可以使用工具中的to_categorical
函数完成该转换.示例如下:
from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels, nb_classes=None)
回调函数Callback
def scheduler(epoch):
if epoch < 40:
return 0.1
if epoch < 100:
return 0.01
if epoch < 150:
return 0.001
return 0.0001
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'))
# epoch=logs.get('epoch')
# print(logs.get('epochs'))
print('batch'+str(batch)+'/'+'epoch'+str(count_epoch)+' = '+str(logs.get('loss')))
def on_epoch_begin(self, epoch, logs={}):
print('epoch'+str(epoch)+' start to train')
global count_epoch
count_epoch=epoch
return epoch
def on_epoch_end(self, epoch, logs=None):
vali_loss = logs.get('val_loss')
# lossss.shape
print('validation_loss'+' = '+str(vali_loss)+'--------'+'\n')
vali_pic = self.validation_data
print('\n')
full_valid_loss.append(vali_loss)
plt.ion()
# plt.figure(1)
# plt.draw()
plt.plot(full_valid_loss,'r-')
plt.pause(3)
plt.close()
gan.test_images(0)
# logs.get('')
# set callback
tb_cb = TensorBoard(log_dir='./vgg19_newlog_def/', histogram_freq=0)
change_lr = LearningRateScheduler(scheduler)
history = LossHistory()
cbks = [change_lr, tb_cb, history]
model.fit(X_train, Y_train, batch_size=128, epochs=20, verbose=0, callbacks=cbks)