Introduction to Keras for Engineers--官網學習

duanyuwangyuyan發表於2020-11-11

學習Keras,我從一個官方樣例Mnist手寫數字識別入手,現在著重學習一下為工程師準備的keras介紹。

1. keras訓練基本步驟

  • 1)準備資料
    格式諸如Numpy Arrays 或者 Tensorflow的Dataset樣式。
    進一步,資料預處理,資料正則歸一或者詞向量。
  • 2)構建模型
  • 3)評估模型
  • 4)定製訓練方式,構建GAN(生成對抗網路) --可選
  • 5)GPU加速 --可選
  • 6)超引數除錯,重定義模型 --可選

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()

…未完待續

相關文章