Introduction to Keras for Engineers--官网学习
学习Keras,我从一个官方样例Mnist手写数字识别入手,现在着重学习一下为工程师准备的keras介绍。
1. keras训练基本步骤
- 1)准备数据
格式诸如Numpy Arrays 或者 Tensorflow的Dataset样式。
进一步,数据预处理,数据正则归一或者词向量。 - 2)构建模型
- 3)训练模型
- 4)评估模型
- 5)定制训练方式,构建GAN(生成对抗网络) --可选
- 6)GPU加速 --可选
- 7)超参数调试,重定义模型 --可选
2. keras训练步骤 --准备数据
神经网络不直接处理原生数据,比如文本文件、jpg图像文件或者表格csv文件;需要将原生文件处理成矢量化与标准化的格式。例如:
- 文本文件需要以string tensor的方式读取,然后分解成单词,最后索引并转换成整型tensor张量。比如:RNN预测上下文。训练数据需要这样去处理。
- 图像文件需要解码成整型tensor张量去读取,然后转换成浮点型并标准归一化为[0,1]。比如:CNN图像分类。
- CSV文件。需要将数值特征转换为浮点张量,并将分类特征建立索引并转换为整型张量。然后每个特征通常需要概率论均值标准差进行归一标准化。
2.1 数据加载
2.1.1 格式要求等说明
keras模型的输入类型,可以是如下三种:
- Numpy Arrays
- Tensorflow Dataset Objects
- Python生成器generator(keras.utils.Sequence)
训练模型前,请确保训练数据符合如上格式的要求。如果是大型数据集,且使用GPU训练,建议考虑使用第二种Tensorflow Dataset objects格式。因为关键性能细节被监控,比如:
- GPU忙的时候,可以在cpu上异步处理训练数据;同时缓存到一个队列中。
- GPU充分利用。在GPU已经完成前批次batch预处理,GPU内存预取数据是即时生效的。
【备注】:不明白此处关键性能监控的直观作用。后面慢慢体会吧。
Keras有一些工具,供开发者将原生数据转化为可以使用的数据集:
- tf.keras.preprocessing.image_dataset_from_directory
- tf.keras.preprocessing.text_dataset_from_directory
- tf.data.experimental.make_csv_dataset(这个是tensorflow本身拥有的接口)
以上前两个接口是tensorflow 2.x中keras集成的高级接口,1.x中没有此接口。
2.1.2 举例
分别就图片文件和文本文件的处理,做了简单的代码举例。
- 1)图片文件处理
Supposed you have image files sorted by class in different folders, like this:
如果图片文件存放的方式,类似如下:
main_directory/
...class_a/
......a_image_1.jpg
......a_image_2.jpg
...class_b/
......b_image_1.jpg
......b_image_2.jpg
则,可以使用image_dataset_from_directory接口,作如下数据处理:
(这里直接拿MNIST png数据做的实际示例)
from tensorflow import keras
# Create a dataset.
labels_class = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] #如下train目录下的各分类文件夹
dataset = keras.preprocessing.image_dataset_from_directory(
'I:/work/datasets/MNIST_PNG_Data/train', batch_size=64, class_names=labels_class, image_size=(28, 28))
# For demonstration, iterate over the batches yielded by the dataset.
i = 0
for data, labels in dataset:
print("============== ", i)
print(data.shape) # (64, 200, 200, 3)
print(data.dtype) # float32
print(labels.shape) # (64,)
print(labels) # int32
i += 1
此接口中,如果不主动设置class_names参数,则keras按照目录下的文件夹名字字母的排序,作为分类的标识。比如:class_a为0,class_b为1,…
//后面计划用这个接口,使用keras模拟从原始数据-模型训练-测试应用的全过程。前面的一片文章是用keras给的mnist示例下载npz输入数据集。
- 2) 文本文件处理
dataset = keras.preprocessing.text_dataset_from_directory(
'path/to/main_directory', batch_size=64)
# For demonstration, iterate over the batches yielded by the dataset.
for data, labels in dataset:
print(data.shape) # (64,)
print(data.dtype) # string
print(labels.shape) # (64,)
print(labels.dtype) # int32
2.2 Data preprocessing with Keras
在2.1节中将数据处理成string/int/float Numpy arrays或者a Dataset object (or Python generator) ;接下来该是将数据作进一步的预处理了。
- 字符串数据的标记,并且建立单词索引
- 特征值的标准归一化
- 缩放数据到很小的值(通常情况下,一个神经网络的输入值应该非常接近0,特别的我们期望这些数据的均值为0,单位方差;或者数据处于[0,1]区间内)
2.2.1 Using Keras preprocessing layers
在keras中,可以使用proprocessing layers模块进行数据预处理。包括如下:
- TextVectorization layer --向量化文本原生strings
- Normalization layer --特征标准归一
- Rescaling,CenterCrop --图像缩放、裁剪或者图像数据的扩充
Keras preprocessing layers 优势的关键:它们能直接包含在模型中;使得模型可移植性强,无论在训练中还是训练后。
preprocessing layer状态是通过调用layer.adapt(data)接口获得。
2.2.2 preprocessing layers examples
1). turning strings into sequences of integer word indices
import numpy as np
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
# Example training data, of dtype `string`.
training_data = np.array([["This is the 1st sample."], ["And here's the 2nd sample."]])
# Create a TextVectorization layer instance. It can be configured to either
# return integer token indices, or a dense token representation (e.g. multi-hot
# or TF-IDF). The text standardization and text splitting algorithms are fully
# configurable.
vectorizer = TextVectorization(output_mode="int")
# Calling `adapt` on an array or dataset makes the layer generate a vocabulary
# index for the data, which can then be reused when seeing new data.
vectorizer.adapt(training_data)
# After calling adapt, the layer is able to encode any n-gram it has seen before
# in the `adapt()` data. Unknown n-grams are encoded via an "out-of-vocabulary"
# token.
integer_data = vectorizer(training_data)
print(integer_data)
tf.Tensor(
[[4 5 2 9 3]
[7 6 2 8 3]], shape=(2, 5), dtype=int64)
2). turning strings into sequences of one-hot encoded bigrams
这块儿需要看一下
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
# Example training data, of dtype `string`.
training_data = np.array([["This is the 1st sample."], ["And here's the 2nd sample."]])
# Create a TextVectorization layer instance. It can be configured to either
# return integer token indices, or a dense token representation (e.g. multi-hot
# or TF-IDF). The text standardization and text splitting algorithms are fully
# configurable.
vectorizer = TextVectorization(output_mode="binary", ngrams=2)
# Calling `adapt` on an array or dataset makes the layer generate a vocabulary
# index for the data, which can then be reused when seeing new data.
vectorizer.adapt(training_data)
# After calling adapt, the layer is able to encode any n-gram it has seen before
# in the `adapt()` data. Unknown n-grams are encoded via an "out-of-vocabulary"
# token.
integer_data = vectorizer(training_data)
print(integer_data)
tf.Tensor(
[[0. 1. 1. 1. 1. 0. 1. 1. 1. 0. 0. 0. 0. 0. 0. 1. 1.]
[0. 1. 1. 0. 0. 1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 0. 0.]], shape=(2, 17), dtype=float32)
3). normalizing features
from tensorflow.keras.layers.experimental.preprocessing import Normalization
# Example image data, with values in the [0, 255] range
training_data = np.random.randint(0, 256, size=(64, 200, 200, 3)).astype("float32")
normalizer = Normalization(axis=-1)
normalizer.adapt(training_data)
normalized_data = normalizer(training_data)
print("var: %.4f" % np.var(normalized_data))
print("mean: %.4f" % np.mean(normalized_data))
#var: 1.0000
#mean: -0.0000
4). rescaling & center-cropping images
from tensorflow.keras.layers.experimental.preprocessing import CenterCrop
from tensorflow.keras.layers.experimental.preprocessing import Rescaling
# Example image data, with values in the [0, 255] range
training_data = np.random.randint(0, 256, size=(64, 200, 200, 3)).astype("float32")
cropper = CenterCrop(height=150, width=150)
scaler = Rescaling(scale=1.0 / 255)
output_data = scaler(cropper(training_data))
print("shape:", output_data.shape)
print("min:", np.min(output_data))
print("max:", np.max(output_data))
#shape: (64, 150, 150, 3)
#min: 0.0
#max: 1.0
2. keras训练步骤 --Building models
在keras中,一个layer层是一个简单的输入和输出转换。比如下面的一个线性投影,将输入映射到一个16维的特征空间中。
dense = keras.layers.Dense(units=16)
模型是layers的有向无环图。可以将模型作为一个bigger layer,包含多个sublayers,且可通过暴露数据进行训练。
构建keras模型,简单粗暴的方式,就是使用keras高级API。以特定的input shape开始,当然开发者可以将shape设为None。比如,200x200 RGB图像数据,其shape维(200,200,3),但是任意size的RGB 输入图像,其shape也可以为(None,None,3)
# Let's say we expect our inputs to be RGB images of arbitrary size
inputs = keras.Input(shape=(None, None, 3))
定义完毕input后,就可以在input上,进行各种layer层的各种所需转换,直到最后的输出,请看如下示例代码:
- input keras.Input:对输入先裁剪缩放
- transformations keras.layers.Conv2D等:经过二维卷积、最大池化、二维卷积、最大池化、二维卷积、均值池化。
- dense keras.layers.Dense:经过各种layers的转换,通过softmax映射到10维特征空间中。
from tensorflow.keras import layers
# Center-crop images to 150x150
x = CenterCrop(height=150, width=150)(inputs)
# Rescale images to [0, 1]
x = Rescaling(scale=1.0 / 255)(x)
# Apply some convolution and pooling layers
x = layers.Conv2D(filters=32, kernel_size=(3, 3), activation="relu")(x)
x = layers.MaxPooling2D(pool_size=(3, 3))(x)
x = layers.Conv2D(filters=32, kernel_size=(3, 3), activation="relu")(x)
x = layers.MaxPooling2D(pool_size=(3, 3))(x)
x = layers.Conv2D(filters=32, kernel_size=(3, 3), activation="relu")(x)
# Apply global average pooling to get flat feature vectors
x = layers.GlobalAveragePooling2D()(x)
# Add a dense classifier on top
num_classes = 10
outputs = layers.Dense(num_classes, activation="softmax")(x)
- 实例一个模型对象keras.Mode:定义完layers有向无环图后,就可以实例一个模型类对象了;
model = keras.Model(inputs=inputs, outputs=outputs)
data = np.random.randint(0, 256, size=(64, 200, 200, 3)).astype("float32")
processed_data = model(data)
print(processed_data.shape)
#(64, 10)
开发者可以通过 model.summary() 方法打印模型每一步的数据转换细节,对于调试非常有用。
注意:每个layer层的输出shape都包含batch size。
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, None, None, 3)] 0
_________________________________________________________________
center_crop_1 (CenterCrop) (None, 150, 150, 3) 0
_________________________________________________________________
rescaling_1 (Rescaling) (None, 150, 150, 3) 0
_________________________________________________________________
conv2d (Conv2D) (None, 148, 148, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 49, 49, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 47, 47, 32) 9248
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 15, 15, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 13, 13, 32) 9248
_________________________________________________________________
global_average_pooling2d (Gl (None, 32) 0
_________________________________________________________________
dense (Dense) (None, 10) 330
=================================================================
Total params: 19,722
Trainable params: 19,722
Non-trainable params: 0
_________________________________________________________________
3. keras训练步骤 – Training models with fit()
数据准备、构建模型后,接下来就可以训练模型了。Model类提供了一个内置的循环训练 方法接口fit()。当然在调用fit()前,开发者需要指定一个优化器和损失函数。这部分的工作由keras提供的compile()接口执行。
model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.CategoricalCrossentropy())
// or use as follows:
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
compile()后,我们就可以开始fit()。fit()用法例子:
model.fit(numpy_array_of_samples, numpy_array_of_labels,
batch_size=32, epochs=10)
关于fit()的形参几点说明:除了所需的训练数据外,批处理batch_size和迭代次数epochs也需要特别指定。当然如果输入的数据集已经集成batch处理,可以不再指定batch_size。
至此,Training结束。有关训练的进阶,开发者可以研究源码。比如:
- Keeping track of performance metrics
- Using callbacks for checkpointing
- Monitoring training progress with TensorBoard
4. keras训练步骤 – Evaluating models with evaluate()
通过compile、fit训练完模型后,我们就可以通过测试数据评估模型的loss和其他metrics指标了。
在keras中,提供 evaluate() 接口实现上述的功能。
loss, acc = model.evaluate(val_dataset) # returns loss and metrics
print("loss: %.2f" % loss)
print("acc: %.2f" % acc)
# 157/157 [==============================] - 0s 688us/step - loss: 0.1041 - acc: 0.9692
# loss: 0.10
# acc: 0.97
如果开发者想得到预测结果怎么办。别急,Keras也提供了相应的接口predict()。
predictions = model.predict(val_dataset)
print(predictions.shape)
# (10000, 10)
备注:后面的定制化训练、GPU加速和超参数调试。这里就不翻译了。有需要了解的,去官网即可。
后续我用到了,再学习更新。
提示:以上的代码示例,都是基于tensorflow 2.x的。