keras学习笔记

具体请查看官方文档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

TensorFlow安装
Theano安装
CNTK安装

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模型的使用

  1. 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"))
  2. 指定模型的输入维度
    模型需要知道输入的维度。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'])

你可能感兴趣的:(神经网络框架)