具体请查看官方文档keras官方文档
1.基本概述
neural layers(神经层), cost functions(损失函数), optimizers(优化器), initialization schemes(初始化方案), activation functions(激活函数), regularization(正则化项)在keras中都是独立的模块,可以自由组合。
keras的核心是一个模型,用来阻止各个网络层次结构。最简单的是Sequential模型,即序贯模型,是一个个网络层的线性叠加。对于更复杂的结构,应该使用keras提供的function API(功能API)。function API允许构建任何的网络结构。
2. 构建简单的Sequential模型
from keras.models import Sequential
model = Sequential()
使用add()方法来添加网络层
from keras.layers import Dense, Activation
model.add(Dense(units=64, input_dim=100))
model.add(Activation("relu"))
model.add(Dense(units=10))
model.add(Activation("softmax"))
模型构建完成之后,使用compile()方法来配置模型(相当于翻译成backend框架的代码)
model.compile(loss="categorial_crossentropy", optimiizer="sgd", metrics=["accuracy"])
如果有需要,可以继续配置模型,或者修改模型的配置
model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizer.SGD(lr=0.01, momentum=0.9, nesterov=True))
编译完成之后,开始以batch为单位训练模型
# X_train, y_train都是numpy array类型,就像scikit-learn当中一样
model.fit(X_train, y_train, epochs=5, batch_size=32)
还可以手动只在batch上训练
model.train_on_batch(x_batch, y_batch)
评价模型
loss_and_metrics = model.evaluate(X_valid, y_valid, batch_size=128)
在新数据上进行预测
classes = model.predict(X_test, batch_size=128)
3. 安装
3.1 先安装backend
3.2 保存模型的插件的安装
- HDF5和h5py的安装:可以将keras模型保存到磁盘上。
- graphviz和pydot,可以用来可视化模型。
3.3 修改backend
在home目录下的~/.keras/keras.json文件中保存中backend的配置文件。如果没有这个文件可以自己新建。默认的配置为:
{
"image_data_format": "channels_last",
"epsilon": 1e-07,
"floatx": "float32",
"backend": "tensorflow"
}
只需要将backend字段改为:”theano”、”tensorflow”或者”cntk”就可以了。另外一种方法是在环境变量中添加:
KERAS_BACKEND=tensorflow python -c "from keras import backend"
Using TensorFlow backend
字段说明:
- image_data_format
theano是channel是channel_first,TensorFlow是channel_last。
- 2D数据: channel_last就是(rows, cols, channels),channel_last就是(channels, rows, cols)。
- 3D数据:channel_last就是(conv_dim1, conv_dim2, conv_dim3, channels),channel_first就是(channels, conv_dim1, conv_dim2, conv_dim3)。
- epsilon:一个浮点数,用来避免某些情况下的除0操作。
- floatX:”float16”、”float32”或者”float64”,默认的浮点数类型。
- backend: “tensorflow”, “theano”或者”cntk”。
4. 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")])
也可以通过add()方法添加
model = Sequential() model.add(Dense(32, input_dim=784)) model.add(Activation("relu"))
- 指定模型的输入维度
模型需要知道输入的维度。Sequential的第一层(只有第一层,后面的层会自动匹配)需要知道输入的shape。有3种方法指定:
- 在第一层加入一个input_shape参数,input_shape应该是一个shape的tuple数据类型。input_shape是一系列整数的tuple,某些位置可为None。input_shape中不用指明batch_size的数目。
- 某些2D的网络层,如Dense,允许在层的构造函数的input_dim中指定输入的维度。对于某些3D时间层,可以在构造函数中指定input_dim和input_length来实现。
- 对于某些RNN,可以指定batch_size。这样后面的输入必须是(batch_size, input_shape)的输入。
例如:
model = Seqnential()
model.add(Dense(32, input_shape=(784, )))
或者
model = Sequential()
model.add(Dense(32, input_dim=784))
5. 编译
训练模型之前,需要先配置模型的学习过程。通过使用compile()函数实现,compile()函数有3个参数:
- optimizer: string类型,优化器的类型
- loss: 模型需要减小的对象,即损失函数。
- metrics: 评价指标的list集合。可以是自定义的metric。
例如:
# 多分类
model.compile(optimizer="rmsprop", loss="categorical_crossentropy", metrics=["accuracy"])
# 二分类
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
# 对于均方差回归模型
model.compile(optimizer='rmsprop', loss='mse')
自定义metrics:
import keras.backend as K
def mean_perd(y_true, y_pred):
return K.mean(y_pred)
model.compile(optimizer="rmsprop", loss='binary_crossentropy', metrics=['accuracy', mean_pred])
6. 训练
keras模型训练的输入数据是numy array类型,使用fit方法:
2分类
model = Sequential()
model.add(Dense(32, activation="relu", input_dim=100))
model.add(Dense(1, activation="sigmoid))
model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["accuracy"])
# 生成dummy data
import numpy as np
data = np.random.random((1000, 100))
labels = np.random.random((1000,1))
#训练模型,使用32的batch来训练
model.fit(data, labels, epochs=10, batch_size=32)
多分类
# For a single-input model with 10 classes (categorical classification):
model = Sequential()
model.add(Dense(32, activation='relu', input_dim=100))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# Generate dummy data
import numpy as np
data = np.random.random((1000, 100))
labels = np.random.randint(10, size=(1000, 1))
# Convert labels to categorical one-hot encoding
one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)
# Train the model, iterating on the data in batches of 32 samples
model.fit(data, one_hot_labels, epochs=10, batch_size=32)
更多关于keras的简单例子见:keras例子
7. keras的functional API(功能API)
keras的functional API可以用来定义复杂的模型,如多输出模型,有向无环图或具有共享图层的模型。
functional API的调用过程:
- 首先在一个tensor上调用该图层实例,并返回一个tensor
- 使用input tensor和output tensor来定义一个Model
- 用类似Sequential的方式来训练模型
from keras.layers import Input, Dense
from keras.models import Model
# 返回一个tensor
inputs = Input(shape=(784,))
# 在tensor上调用一个layer实例,并返回一个tensor
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
# 定义一个model,该model包含输入层和3个全连接层
model = Model(inputs=inputs, outputs=predictions)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels) # starts training
模型的重用,可以直接将模型当作一个层来使用
x = Input(shape=(784, ))
y = model(x) # 返回一个包含10个元素的数组
将传统的图像分类模型用作视频分类
from keras.layers import TimeDistributed
input_seq = Input(shape=(784, 20)) #输入是一个20帧的视频
processed_sequences = TimeDistributed(model)(input_seq) # 输出是一个20×10的矩阵
7.1 多输入和多输出模型
functional API使得可以方便的处理交织的数据流。
例如,实现如下的网络结构
其中main_input是一个词的序列,每个词用(0, 10000)之间的整数代替,词的长度是100。
from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model
main_input = Input(shape=(100,), dtype="int32", name="main_input") #可以给层命名
x = Embedding(output_dim = 512, input_dim=10000, input_length = 100)(main_input)
lstm_out = LSTM(32)(x)
auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
auxiliary_input = Input(shape=(5,), name='aux_input')
x = keras.layers.concatenate([lstm_out, auxiliary_input])
# We stack a deep densely-connected network on top
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
# And finally we add the main logistic regression layer
main_output = Dense(1, activation='sigmoid', name='main_output')(x)
model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])
model.compile(optimizer='rmsprop', loss='binary_crossentropy', loss_weights=[1., 0.2])
model.compile(optimizer='rmsprop',
loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
loss_weights={'main_output': 1., 'aux_output': 0.2})
# And trained it via:
model.fit({'main_input': headline_data, 'aux_input': additional_data},
{'main_output': labels, 'aux_output': labels},
使用layer.input/output和layer.input_shape/output_shape来获取输入输出tensor。
x = Dense(units=32)(x)
x.output
8. 保存和加载模型
保存模型的结构、权重和优化器状态,不推荐cPickle来保存。可以使用model.save(filepath)来将模型保存为一个HDF5文件。该文件中包含:
- 模型的结构,允许重构
- 模型的权重
- 巡礼啊配置(包含loss, optimizer等)
- optimizer的状态,允许在上次中断的地方继续训练
8.1 保存/加载整个模型
使用keras.models.load_model(filepath)来加载模型。load_model也会加载训练的配置(loss, optimizer等)。
from keras.models import load_model
model.save("my_model.hdf5") #创建一个文件my_model.hdf5
del model #删除模型
#返回一个已经编译过的模型,和之前的模型一模一样
model = load_model("my_model.hdf5")
8.2 只保存/加载模型的结构(只有网络结构,没有权重和配置)
#保存为json
json_str = model.to_json()
#保存为yaml
yanm_str = model.to_yaml()
保存下来的JSON/YAML是可阅读的文本,可以被编辑,通过以下方式加载:
from keras.models import model_from_json
model = model_from_json(json_string)
from keras.models import model_from_yaml
model = model_fram_yaml(yaml_str)
8.3 只保存/加载权重
使用hdf5来只加载权重(需要先安装HDF5和h5py)
model.save_weights("my_model_weights.h5")
定义好模型之后,加载权重
model.load_weights("my_model_weights.h5")
如果想加载权重到不同的网络结构,网络只有某些层相同,例如transfer learning和fine tuning,可以使用name属性实现:
"""
Assuming the original model looks like this:
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1'))
model.add(Dense(3, name='dense_2'))
...
model.save_weights(fname)
"""
# new model
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1')) # will be loaded
model.add(Dense(10, name='new_dense')) # will not be loaded
# load weights from first model; will only affect the first layer, dense_1.
model.load_weights(fname, by_name=True) #通过制定by_name为True来实现
8.4 获取中间层的输出
要获取中间层的输出,最好的办法是新建一个模型
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]
8.5 使用history函数来记录每一个epoch的training/validation 的loss/accuracy。
model.fit()会返回一个History对象。该对象有一个history属性,记录着loss和metrics的信息
hist = model.fit(x, y, validation_split=0.2)
print(hist.history)
8.5 固定某些layer
在fine-tuning中要保持某些layer的权重weight不变,可以使用trainable参数实现
frozen_layer = Dense(32, trainable=False)
还可以使用trainable属性来指定某些层的系数是否可以改变,但要改变trainable属性,需要重新调用compile方法:
x = Input(shape=(32,))
layer = Dense(32)
layer.trainable = False
y = layer(x)
frozen_model = Model(x, y)
#下面的模型参数不变
frozen_model.compile(optimizer="rmsprop", loss="mse")
layer.trainable = True
trainable_model = Model(x, y)
#训练的时候,权重会改变,因此也会影响froze_model
trainable_model.compile(optimizer="rmsprop", loss="mse")
frozen_model.fit(data, labels) #不会改变权重
trainable_model.fit(data, labels) #会改变权重
8.6 使用pop方法来删除最后一层
model = Sequential()
model.add(Dense(32, activation="relu", input_dim=784))
model.add(Dense(32, activation="relu"))
print(len(model.layers)) #输出2
model.pop()
print(len(model.layers)) #输出1
8.7 使用预训练的模型
通过keras.applications来使用预训练的模型
from keras.applications.xception import Xception
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19
from keras.applications.resnet50 import ResNet50
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_resnet_v2 import InceptionResNetV2
from keras.applications.mobilenet import MobileNet
model = VGG16(weights='imagenet', include_top=True)
9. Keras的models
有两种model, Sequential model和functional API model,两种模型有以下的方法:
model.summary(): 打印model的信息
model.get_config() 返回一个dict,包含模型的配置信息。可以通过以下的方法来加载该配置
config = model.get_config()
model = Model.from_config(config)
#或者
model = Sequential.from_config(config)
model.get_weights():以numpy.array的形式返回所有weight的list列表。
model.set_weights(weights):从numpy.array里面给模型设置参数。list里面的参数应该和model.get_weights()的结构相同。
model.to_json():返回一个描述模型的json字符串。这些字符串不包含权重信息,只有结构。可以通过以下方法加载这些模型:
from models import model_from_json
json_str = model.to_json()
model = model_from_json(json_str)
model.to_yaml():和json类似
model.save_weights(filapath):将模型的权重存到一个hdf5文件中。
model.load_weights(filepath, by_name=False):将save_weights存储的权重加载进来。通常结构不变。如果结构不同,而只想加载某些特殊层的权重,可以使用by_name=True来加载哪些名称相同的层的权重。
10. Sequential模型
model.layers:模型中一些列layer的list集合。
常用的方法:
10.1 compile
compile(self, optimizer, loss, metrics=None, sample_weitght_mode=None, weightd_metrics=None)来配置学习过程。参数:
- optimizer: 优化器
- loss: 损失函数
- metrics:训练过程中的评价函数的list集合。通常使用metrics=[“accuracy”]
- sample_weight_mode:是否需要做时间的取样
- weighted_metrics:不同的metrics的权重
例子:
model = Sequential()
model.add(Dense(32, input_shape=(500,)))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy',metrics=['accuracy'])
fit方法:
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)
在模型上进行epochs次的训练。参数如下:
- x: 输入,numpy.array类型或者array的list集合(此时对应有多个输入)
- y: 标签,numpy.array类型
- batch_size: 整数,每次梯度迭代更新使用的样本数目。
- epochs: 迭代的总次数。
- verbose: 0代表没有日志输出,, 1代表用进度条输出日志, 2代表每个epoch打印一行日志。
- callbacks: keras.callbacks.Callback的list列表,在训练过程中会被调用。
- validation_split: (0,1)之间的浮点数,用来将数据分一部分作为验证集合。
- validation_data: 一个元组类型(tuple(x_val, y_val)或者(x_val, y_val, val_sample_weights)),作为验证集,会覆盖掉validation_split。
- shuffle: boolean,每个epoch是否会将数据打乱。
- class_weight: dictionary mapping classes to a weight value。
- sample_weight: Numpy array of weights for the training samples。
- initial_epoch: 哪一个epoch开始训练,通常对于之前已经训练了的model有用。
返回:
History对象。其history方法能够记录训练过程中的loss和metrics value的值。
evaluate方法:
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
在某些input data上一个个batch的计算总的loss。
返回:
一个loss的标量或者loss的列表(如果有多个metrics)。
predict方法:
predict(self, x, batch_size=32, verbose=0)
针对input输出对应的predict值,通过batch一个一个batch的计算。
返回: numpy.array类型。
train_on_batch方法:
train_on_batch(self, x, y, class_weight=None, sample_weight=None)
对于某个batch上的数据进行梯度迭代更新。
参数:
- x: numpy.array或者numpy.array的list列表(多个输入)。
- y: numpy.array
返回:
scala或者scala的list列表。
test_on_batch:
test_on_batch(self, x, y, sample_weight=None)
对于一个batch的数据进行评估。
返回:
scala或者scala的list列表。
predict_on_batch方法:
predict_on_batch(self, x)
x: numpy.array或者numpy.array的list列表。
返回:
numpy.array的预测值。
fit_generator方法:
fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_queue_size=10, workers=1, use_multiprocessing=False, initial_epoch=0)
对通过python的generator产生的数据一个一个batch的进行训练。generator并行地在模型上运行来提升效率。这样可以同时在CPU上做图像的augmentation和GPU上的训练。
参数:
generator: 生成器,输出必须为以下两种中的一种:
- tuple类型。(inputs, targets)
- tuple类型。(inputs, targets, sample_weights)。
generator会在数据上不断地进行循环。一个epoch完成的标志是: steps_per_epoch个batch都已经训练完成了。
- steps_per_epoch:每个epoch完成,generator会运行多少次。也就是batch的数目,通常为1+(len(train_data) // batch_size)
- epochs:迭代的次数
- verbose:打印日志的方式,0,1或2
- callbacks: callbacks的列表,训练期间每个epoch完成时会调用会调用。
- validation_data: 验证集,可以是以下几种:
- validation data的生成器
- 元组, tuple(inputs, targets)或者(tuple, targets, sample_weights)
- validation_steps:只有当validation_data是一个generator的时候有用。每次epoch完成时generator会运行多少次,通常为1+(len(validation_data) // batch_size)
- class_weight: dict类型
- max_queue_size: generator队列的最大容量
- workers: 进程的最大数目
- use_multiprocessing:是否使用多线程
- initial_epoch: 哪一个epoch开始训练,对于恢复前面训练的模型有用
返回:
History对象。
例子:
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
x, y = process_line(line)
yield (x, y)
f.close()
model.fit_generator(generate_arrays_from_file('/my_file.txt'),
steps_per_epoch=1000, epochs=10)
evaluate_generator方法:
在一个data generator上评估模型,返回的数据类型和test_on_batch一样。
evaluate_generator(self, generator, steps, max_queue_size=10, workers=1, use_multiprocessing=False)
- generator: generator生成的numpy元组(inputs, targets)或(inputs, targets, sample_weights)
- steps: batch的数目。
返回:scala或者scala的列表。
predict_generator方法:
predict_generator(self, generator, steps, max_queue_size=10, workers=1, use_multiprocessing=False, verbose=0)
通过对generator产生的数据来生成输出。返回类型和predict_on_batch一样。
参数:
- generator:生成一批input样本的生成器
- steps: batch的数量
返回:
numpy.array的预测值。
get_layer方法:
get_layer(self, name=None, index=None)
获取模型中的一层。通过名称或者索引来获取层。索引是自下而上的顺序。
参数:
- name: str类型,layer的名称
- index: int,layer的序号
返回:
一个layer的实例。
11. functional API
在function API当中,通过给定一个输入input tensor和一个输出output tensor,可以构建一个模型:
from keras.models import Model
from keras.layers import Input, Dense
a = Input(shape=(32,)) #a是一个tensor
b = Dense(32)(a) #b也是一个tensor
model = Model(inputs=a, outputs=b)
该模型会包含所有计算b所需要的图层。
对于多输入和多输出,使用list来给定:
model = Model(inputs=[a1, a2], outputs=[b1, b2, b3])
常用的属性:
- model.layers: layer的list列表
- model.inputs: input tensor的集合
- model.outputs: output tensor的集合
常用的方法和上面相同。
12 keras的layers
12.1 Merge层
有两种方法来实现层的merge:
- 使用merge函数
from keras.layeres import merge #注意:merge函数用来对functional API进行整合,Merge类用来对Sequential来进行整合
12.1.2
Add()类:输入一些列tensor(shape必须相同),输入一个tensor(同shape)。返回这些tensor的逐元素和的tensor,shape不变。
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)
added = keras.layers.Add()([x1, x2]) # equivalent to added = keras.layers.add([x1, x2]),shape为(8,)
out = keras.layers.Dense(4)(added)
model = keras.models.Model(inputs=[input1, input2], outputs=out)
12.1.2
Multiply()类,该层接收一个列表的同shape张量,并返回它们的逐元素积的张量,shape不变。
keras.layers.merge.Multiply()和Add类似。
12.1.3
Average()类,该层接收一个列表的同shape张量,并返回它们的逐元素的均值的tensor,shape不变。与Add和Multiply类似。
12.1.4
Maximun()类,该层接收一个列表的同shape张量,并返回它们的逐元素积的最大值的tensor,shape不变。
12.1.5
Concatenate():该层接收一个列表的同shape张量,并返回它们的按照给定轴相接构成的向量。
12.1.6
Dot(axes, normalize=False):计算两个tensor中样本的张量乘积。例如,如果两个张量a和b的shape都为(batch_size, n),则输出为形如(batch_size,1)的张量,结果张量每个batch的数据都是a[i,:]和b[i,:]的矩阵(向量)点积。
13 keras图像预处理
使用函数keras.preprocessing.image.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_filp=False,
rescale=None,
preprocessing_function=None,
data_format=K.image_data_format())
)
参数如下:
- 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”
返回值
keras.preprocessing.image.ImageDataGenerator
方法:
fit(x, y)
参数:- x: 数据,维度必须为4,第一维是样本数量
- y: labels,也是矩阵,一般2维
- batch_size: default 32
- seed: int
- save_to_dir: None或者str,将图片保存到哪个路径下
- save_prefix: default ” “,保存图片的前缀
- save_format: png, jpg。
返回值
(x, y): x是一个numpy.ndarray的image,而y是对应的numpy.ndarray的标签。如果只有x,则不会返回y
必须使用keras 2.0.0以上版本
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.utils.np_utils import to_categorical
img = load_img("../input/lena.jpg") # return type: PIL.JpegImagePlugin.JpegImageFile
x = img_to_array(img) # return type: numpy.ndarray
x = x.reshape((1,) + x.shape) # 输入数据必须为(num_samples, height, width, channels)
datagen = ImageDataGenerator(
rotation_range=30,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
#将变换的图片保存下来
datagen.fit(x)
y = to_categorical([1])
for i, (x_batch, y_batch) in enumerate(datagen.flow(x, y, batch_size, save_to_dir=my_path, save_prefix="lena", save_format="jpg")):
# 此处必须设置停止次数,否则会一直进行下去
if i > times:
break
#如果只有图片,可以不指定y
for i, x_batch in enumerate(datagen.flow(x, batch_size, save_to_dir=my_path, save_prefix="lena", save_format="jpg")):
# 此处必须设置停止次数,否则会一直进行下去
if i > times:
break
使用ImageDataGenerator来训练数据
datagen = ImageDataGenerator(
featurewise_center=False, # set input mean to 0 over the dataset
samplewise_center=False, # set each sample mean to 0
featurewise_std_normalization=False, # divide inputs by std of the dataset
samplewise_std_normalization=False, # divide each input by its std
zca_whitening=False, # apply ZCA whitening
rotation_range=0, # randomly rotate images in the range (degrees, 0 to 180)
width_shift_range=0.1, # randomly shift images horizontally (fraction of total width)
height_shift_range=0.1, # randomly shift images vertically (fraction of total height)
horizontal_flip=True, # randomly flip images
vertical_flip=False) # randomly flip images
datagen.fit(x_train)
model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size),
steps_per_epoch=x_train.shape[0] // batch_size, epochs=epochs, validation_data=(x_test, y_test),
workers=4)
datagenerator的工作过程:每次一个epoch取数据的时候,将图片进行随机变化然后输入进模型。与传统的未进行过变化的区别是:未进行过变化的模型每个epoch看到的图片都是一模一样的原图。而进过datagenerator变化过后,每个epoch看到的都是经过变化后的图片,甚至从来都不会看到原图。
flow_from_directory(directory)
参数:
- directory:存放图片的文件夹名称。通常在不同的类下面,再建立子文件夹,该方法会自动根据子文件夹的名称来设置类标签。
- target_size:最终训练时将图片的大小设置为多少,默认(256,256)
- color_mode: 灰度图为,”grayscale”, 彩色图为,”rbg”. 默认: “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”。
- follow_links:是否访问子文件夹中的软链接。
返回值:
ImageDataGenerator
例子:
for i, (x_batch, y_batch) in enumerate(datagen.flow_from_directory(directory="valid",save_to_dir="E:/a", save_prefix="lena", save_format="jpg", shuffle=False, target_size=(512,512))):
print(y_batch)
if i > 20:
break;
注意在使用flow_from_directory方法的时候,要将数据分成train和valid两个文件夹,然后每个文件夹下面根据不同的标签再建立子文件夹,然后每个子文件夹下再防止相应类的图片。在predict_genertor的时候要将shuffle设置为False,否则标签和相应的图像对不上。
当使用model.fit_generator训练的时候,使用如下方法:
model.fit_generator(datagen.flow(x_train, y_train, batch_size=32),
steps_per_epoch=len(x_train), epochs=epochs))
或者
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)
注意,一般valid_generator和test_generator不需要做图像变换,而只在train_generator当中做图像变换。即:
valid_gen = ImageDataGeneraotr() #不放任何参数
test_gen = ImageDataGenerator() #不放任何参数
使用 predict_generator p r e d i c t _ g e n e r a t o r 来预测标签,注意最终的输出顺序按照文件夹和文件的顺序来,linux文件夹和文件的排序方式和windows不同。最后使用 test_gen.filenames t e s t _ g e n . f i l e n a m e s 来获取标签对应的文件:
#注意要把shuffle设置为False, class_model设置为False表示不产生标签
test_gen = ImageDataGeneraotr().flow_from_directory(test_path, shuffle=False, class_model=None, target_size=target_size, batch_size=batch_size)
result = model.predict_generator(generator=test_gen, ...)
filenames = test_gen.filenames #这时,对应的文件名的顺序和result的预测结果对应的顺序对应
14. 定义top-K准确率
一般的时候,可以直接使用内置的准确率:
from keras import metrics
model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=[metrics.mae, metrics.categorical_accuracy, metrics.top_k_categorical_accuracy]) #k默认5
自定义top-K准确率:
def top_3_accuracy(y_true, y_pred):
return top_k_categorical_accuracy(y_true, y_pred, k=3)
model.compile(..........., metrics=[top_3_accuracy])
15. transfer learning和fine tuning
通常先将前面的卷积层固定,先用Adam Optimizer训练全连接层。带基本收敛(通常2~3个epoch),然后开始全部训练,全部训练时,用SGD Optimizer比较好。
for layer in base_model.layers[:25]:
layer.trainable = False
sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])