首先当然是安装Keras。需要注意的是Keras有三种后端backend。后端是意思是Keras需要依赖他们进行张量的运算。这三种后端是:tensorflow,Theano,CNTK(微软)。这也是keras的优势:可以在多种生态中发布。一般使用Tensorflow作为后端,所以在安装Keras之前需要先安装tensorflow。在安装好Keras之后,命令行中import keras会提示using tenserflow backend,这就是在提示我们正在使用的是Tensorflow的后端,而不是错误信息。
然后介绍模型。Keras的模型有两种方式构造。
第一种是使用Sequential序贯模型。可以直接在Sequential中定义,
from keras.models import Sequential
from keras.layers import Dense, Activation
model = Sequential([
Dense(32, input_shape=(784,)),
Activation('relu'),
Dense(10),
Activation('softmax'),
])
model = Sequential()
model.add(Dense(32, input_dim=784))
model.add(Activation('relu')) #可以通过name设置层名字,加载已有模型可以通过名字判断是否加载这一层的权重
model.pop() #删除最后添加的层
第二种是函数式。
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)
构建好之后使用一行函数就可以打印模型各层的参数。
model.summary()
模型编译
我理解的编译是一个静态的过程。是将模型与loss,优化器optimizer,评估标准metrics联系起来。
# 多分类问题
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 二分类问题
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
# 均方误差回归问题
model.compile(optimizer='rmsprop',
loss='mse')
数据
注意这里的label使用了onehot编码。onehot编码就是使用01字符串对类别标签进行编码,但不同于通信中力求编码长度最短,onehot的one指的就是一次编码中只出现一个1,其余全为0,这样onehot编码长度应该等于种类数。在这个函数中取的是标签列表中最大值+1.所以准确来说返回的是一个01构成的矩阵,矩阵行数是种类类别数,列数是种类标签值的最大值加1.这样做可能是认为种类标签值应该是连续的,为不存在的类别预留位置,同时也体现了类别之间的距离。
import keras
ohl=keras.utils.to_categorical([1,3])
print(ohl)
<<<
[[0. 1. 0. 0.]
[0. 0. 0. 1.]]
对图像数据,一般使用keras提供的函数转换为array。
image = cv2.imread(path)
feature = cv2.resize(image,(IMAGE_DIMS[0],IMAGE_DIMS[1]))
feature = img_to_array(feature) #转换为类似float型的ndarray
features=feature/255.0 # tensor范围是0~1
可以使用yield(data,label)定义函数作为生成器。借助生成器的Next功能,每次只迭代一个值,减少了对内存的消耗。
模型训练
这一步是动态的过程,将模型针对数据做适应,所以使用了fit函数。
# 生成虚拟数据
import numpy as np
data = np.random.random((1000, 100))
labels = np.random.randint(10, size=(1000, 1))
# 将标签转换为分类的 one-hot 编码
one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)
# 训练模型,以 32 个样本为一个 batch 进行迭代
model.fit(data, one_hot_labels, epochs=10, batch_size=32)
但现实中往往没有这么简单。现实中数据量很大,同时我们还需要进行数据增强,所以更多时候使用的是fit_generator方法。这种方法就利用了刚才提到的yeild构成的生成器,生成器作为fit_generator的第一个参数。在生成其函数中就可以进行一些如数据增强等预处理。因为生成器不像return一样输出就停止了,生成器会一直在上一步停止的地方开始执行,且是按照单位输出的(单位一般是batch_size),为了区别epoch的次数,我们还需要明确参数steps_per_epoch的取值。每次epoch遍历了完整的数据集,那么每次epoch就需要(数据长度/生成器每次输出长度) 次的生成器操作。所以我认为下面第二种解释是更合理的。
history = model.fit_generator(generator(),epochs=epochs,steps_per_epoch=len(x_train)//(batch_size*epochs))
history = model.fit_generator(generator(),epochs=epochs,steps_per_epoch=len(x_train)//(batch_size))
此外,还可以使用model.train_on_batch(x,y)
和 model.test_on_batch(x,y)
进行批量训练与测试。model.train_on_batch(x,y)看名字就知道,也是
利用生成器,每次载入一个batch-size。https://github.com/fchollet推荐的是使用fit_generator,因为它也可以使用验证集的生成器。
训练进行中
fit_generator中还有一个可选参数是callback,虽然翻译叫做回调函数,但是它其实是一个类。而回调的意思是在训练的过程中我们可以通过它对模型的参数进行保存和调整。
checkpoint回调函数,可以对模型参数进行保存,这样即便训练过程意外中断,我们可以接着中断的地方继续训练。
LearningStepSchedule回调函数,可以对模型学习率按照策略进行调整。
#keras提供了两种学习率的更新方式
keras.callbacks.LearningRateScheduler(schedule) #第一种通过定义schedule函数,这个函数一般以epoch为自变量进行调整
keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', epsilon=0.0001, cooldown=0, min_lr=0) #第二种自动根据检测量的变化情况调整
#定义checkpoint
filepath="weights-improvement-{epoch:02d}-{val_acc:.2f}.hdf5"
checkpoint= ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
# Earlystop回调函数可以提前终止训练
early_stopping = EarlyStopping(monitor='val_loss', patience=2)
#定义的lr和checkpoint两个回调函数可以同时以列表的形式写在fit参数中
model.fit(train_set_x, train_set_y, validation_split=0.1, nb_epoch=200, batch_size=256, callbacks=[checkpoint,lr])
虽然前面已经对数据做了一些预处理,但是这些数据很可能仍然是不平衡的,或者是其他特殊情况。比如分类中,检测欺诈交易detect fraudulent transactions,不仅不平衡,惩罚的结果也不同,比如回归时,每条数据的可信度是不同的。这就是需要在训练时对loss加权重。类别不平衡时,需要设置的参数是class_weight,这是一个字典,如{0:1.,1:50.,2:3.},int型表示类别,float型表示对应的权重,对于权重大的类别,代表我们更关心这一类,当分错时loss更大,惩罚更大。 This can be useful to tell the model to "pay more attention" to samples from an under-represented class.至于sample_weights,是在类内样本级别的加权,对一些可信度低的数据赋予更低的权重;对实时性教新的数据赋予更高的权重。
模型评估
score = model.evaluate(data_test, label_test, batch_size=32)
Reference:
https://keras-cn.readthedocs.io/en/latest/models/about_model/