返回文章列表

TensorFlow資料預處理與增強技術實踐

本文探討 TensorFlow 中的資料預處理與增強技術,包含使用 tf.data 和 Keras 層的策略比較、TensorFlow Transform (tf.transform) 的應用,以及影像資料增強的實作細節。文章涵蓋了自定義預處理層、色彩失真、空間變換等技巧,並以 Mixup

機器學習 深度學習

在機器學習模型訓練流程中,資料預處理和增強對於模型效能至關重要。本文將探討 TensorFlow 生態系中資料處理的最佳實踐,包含 tf.data 與 Keras 預處理層的選用策略、TensorFlow Transform (tf.transform) 的應用,以及多種資料增強技巧。藉由調整影像大小、色彩、空間變換等方式,搭配 Mixup 等進階增強方法,有效提升模型的泛化能力和魯棒性,避免訓練與服務階段的偏差,並實踐於影像分類別任務中。程式碼範例涵蓋自定義 Keras 層的建立、tf.transform 的 Beam pipeline 撰寫,以及 Mixup 的實作細節,提供讀者在 TensorFlow 中進行資料預處理和增強的完整參考。

資料預處理的策略與實作

在機器學習的流程中,資料預處理是一個至關重要的環節。適當的預處理可以提高模型的效能和準確性。本文將探討在 TensorFlow 中進行資料預處理的不同策略,以及如何根據具體需求選擇適合的方法。

預處理的位置:tf.data 還是 Keras 層?

在 TensorFlow 中,資料預處理可以透過 tf.data 管道或 Keras 層來實作。兩種方法各有其優缺點,選擇時需要考慮多個因素。

效率

如果某些預處理操作是固定的,並且總是需要的,那麼將其放在 tf.data 管道中可以提高效率。因為預處理的結果可以被快取,避免在每次訓練迭代中重複執行。

實驗靈活性

將預處理操作實作為 Keras 層可以提供更大的靈活性。例如,可以輕易地修改裁剪比例或嘗試不同的預處理策略,而無需更改資料讀取邏輯。

可維護性

使用 Keras 層進行預處理可以減少錯誤,因為相同的預處理邏輯會自動應用於訓練和推斷階段。

靈活性與加速

對於需要在訓練和推斷階段表現不同的操作(如資料增強),使用 Keras 層會更方便。此外,將操作放在模型函式中可以利用 GPU 加速。

tf.transform 的應用

為了避免訓練和服務階段的偏差(training-serving skew),可以使用 TensorFlow Transform(tf.transform)。tf.transform 允許將預處理操作儲存並在服務階段自動應用。

寫作 Beam 管道

首先,需要寫一個 Apache Beam 管道來分析訓練資料並應用預處理。這包括讀取原始資料、計算必要的統計資料(如用於標準化的均值和方差),以及應用預處理操作。

RAW_DATA_SCHEMA = schema_utils.schema_from_feature_spec({
    'filename': tf.io.FixedLenFeature([], tf.string),
    'label': tf.io.FixedLenFeature([], tf.string),
})

csv_tfxio = tfxio.CsvTFXIO(
    file_pattern='gs://.../all_data.csv',
    column_names=['filename', 'label'],
    schema=RAW_DATA_SCHEMA
)

img_records = (p
               | 'read_csv' >> csv_tfxio.BeamSource(batch_size=1)
               | 'img_record' >> beam.Map(lambda x: create_input_record(x[0], x[1]))
               )

轉換資料

使用 tft_preprocess 函式對資料進行轉換,該函式包含了調整影像大小等預處理操作。

raw_dataset = (img_records, IMG_BYTES_METADATA)
transformed_dataset, transform_fn = (
    raw_dataset | 'tft_img' >>
    tft_beam.AnalyzeAndTransformDataset(tft_preprocess)
)

儲存轉換函式

將轉換函式與模型一起儲存,以便在服務階段應用相同的預處理。

資料預處理與增強在機器學習中的重要性

在機器學習領域,資料預處理和資料增強是兩個至關重要的步驟,它們直接影響模型的效能和泛化能力。本文將探討使用TensorFlow Transform(TFT)進行資料預處理的過程,以及如何透過資料增強技術來提高模型的準確性和魯棒性。

使用TensorFlow Transform進行資料預處理

TensorFlow Transform是一個強大的工具,用於對資料進行預處理。它允許使用者在訓練資料集上定義一系列的轉換操作,並將這些操作儲存為一個模型工件(model artifact),以便在服務(serving)階段能夠重用這些操作,從而避免訓練-服務偏差(training-serving skew)。

資料預處理流程

  1. 定義預處理函式:首先,需要定義一個預處理函式,該函式對輸入的原始資料進行必要的轉換,如影像解碼、縮放和調整大小等。
def tft_preprocess(img_record):
    img = tf.map_fn(decode_image, img_record['img_bytes'], fn_output_signature=tf.uint8)
    img = tf.image.convert_image_dtype(img, tf.float32)
    img = tf.image.resize_with_pad(img, IMG_HEIGHT, IMG_WIDTH)
    return {
        'image': img,
        'label': img_record['label'],
        'label_int': img_record['label_int']
    }
  1. 儲存轉換函式:將定義好的預處理函式應用於資料集,並將轉換後的資料儲存。同時,使用tft_beam.WriteTransformFn將轉換函式儲存到指定的路徑。
transform_fn | 'write_tft' >> tft_beam.WriteTransformFn(os.path.join(OUTPUT_DIR, 'tft'))
  1. 讀取預處理後的資料:在訓練階段,可以透過tf.data.experimental.make_batched_features_dataset讀取預處理後的資料。
def create_dataset(pattern, batch_size):
    return tf.data.experimental.make_batched_features_dataset(
        pattern,
        batch_size=batch_size,
        features={
            'image': tf.io.FixedLenFeature([IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS], tf.float32),
            'label': tf.io.FixedLenFeature([], tf.string),
            'label_int': tf.io.FixedLenFeature([], tf.int64)
        }
    ).map(lambda x: (x['image'], x['label_int']))
  1. 在服務階段應用預處理:在服務階段,可以透過載入儲存的轉換函式模型工件,對輸入的資料進行相同的預處理操作。
preproc = tf.keras.models.load_model('.../tft/transform_fn').signatures['transform_signature']
preprocessed = preproc(img_bytes=tf.convert_to_tensor(img_bytes)...)
pred_label_index = tf.math.argmax(model.predict(preprocessed))

內容解密:

  1. tft_preprocess函式:此函式負責對輸入的影像資料進行預處理,包括解碼、縮放和調整大小等操作。這些操作對於確保模型能夠正確處理輸入資料至關重要。
  2. 儲存轉換函式:透過儲存轉換函式,能夠在服務階段重用相同的預處理邏輯,避免了訓練和服務階段之間的偏差。
  3. 讀取預處理後的資料:利用TensorFlow的資料API,可以高效地讀取預處理後的資料,並將其用於模型的訓練。
  4. 服務階段的預處理:在服務階段,透過載入儲存的轉換函式,能夠對新的輸入資料進行相同的預處理操作,確保模型能夠正確地進行預測。

資料增強技術

資料增強是另一種提高模型效能和泛化能力的重要技術。它透過對訓練資料進行各種隨機變換(如旋轉、縮放、翻轉等),生成新的訓練樣本,從而增加訓練資料的多樣性。

空間變換

空間變換是資料增強的一種常見方法,包括旋轉、縮放、翻轉等操作。這些操作可以增加訓練資料的多樣性,使模型能夠更好地泛化到新的未見資料。

顏色扭曲

顏色扭曲是另一種資料增強技術,透過改變影像的亮度、色調等屬性,生成新的訓練樣本。

資訊丟棄

資訊丟棄技術,如隨機遮擋或擦除影像的不同部分,也可以增加訓練資料的多樣性。

資料增強在機器學習中的應用

在機器學習領域,資料增強是一種透過對原始資料進行多種變換,從而增加訓練資料量、提高模型泛化能力的方法。適當的資料增強可以使模型更好地應對不同的輸入資料,從而提高其在實際應用中的表現。

影像資料增強的必要性

影像是機器學習中常見的資料型別之一。在影像分類別任務中,模型的表現往往取決於訓練資料的多樣性。圖6-9展示了一些對拖拉機影像進行的幾何變換,包括翻轉、旋轉等。這些變換可以增加訓練資料的多樣性,但必須確保變換後的影像仍然具有代表性。

Keras中的資料增強層

Keras提供了多種資料增強層,包括RandomFlipRandomRotationRandomZoom等。這些層可以在訓練過程中對輸入資料進行隨機變換,從而增加訓練資料的多樣性。例如,RandomFlip層可以隨機地對影像進行水平翻轉或保持原樣。

tf.keras.layers.experimental.preprocessing.RandomFlip(
    mode='horizontal',
    name='random_lr_flip/none'
)

內容解密:

  • mode='horizontal':指定翻轉模式為水平翻轉,即左右翻轉。
  • name='random_lr_flip/none':為該層命名,便於在模型中識別。

結合多種資料增強技術

除了單一的資料增強技術外,還可以結合多種技術來進一步提高模型的表現。例如,可以同時使用RandomCropRandomFlip來增加訓練資料的多樣性。

layers = [
    tf.keras.layers.experimental.preprocessing.RandomCrop(
        height=IMG_HEIGHT//2, width=IMG_WIDTH//2,
        input_shape=(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS),
        name='random/center_crop'
    ),
    tf.keras.layers.experimental.preprocessing.RandomFlip(
        mode='horizontal',
        name='random_lr_flip/none'
    ),
    # ... 其他層
]

內容解密:

  • RandomCrop層:隨機裁剪輸入影像,以增加訓練資料的多樣性。
  • 結合多種資料增強技術:透過堆積疊不同的資料增強層,可以實作更豐富的資料變換。

自定義資料增強層

雖然Keras提供了多種內建的資料增強層,但有時仍需要自定義資料增強層來滿足特定需求。例如,可以建立一個RandomColorDistortion層來隨機調整影像的對比度和亮度。

class RandomColorDistortion(tf.keras.layers.Layer):
    def __init__(self, contrast_range=[0.5, 1.5], brightness_delta=[-0.2, 0.2], **kwargs):
        super(RandomColorDistortion, self).__init__(**kwargs)
        self.contrast_range = contrast_range
        self.brightness_delta = brightness_delta

    def call(self, images, training=False):
        if not training:
            return images
        contrast = np.random.uniform(self.contrast_range[0], self.contrast_range[1])
        brightness = np.random.uniform(self.brightness_delta[0], self.brightness_delta[1])
        images = tf.image.adjust_contrast(images, contrast)
        images = tf.image.adjust_brightness(images, brightness)
        images = tf.clip_by_value(images, 0, 1)
        return images

內容解密:

  • __init__方法:初始化對比度和亮度的調整範圍。
  • call方法:在訓練模式下,隨機調整影像的對比度和亮度;在非訓練模式下,保持影像原樣。
  • tf.image.adjust_contrasttf.image.adjust_brightness:用於調整影像對比度和亮度的方法。

資料增強的效果

透過引入資料增強技術,可以顯著提高模型的泛化能力和表現。如圖6-10所示,使用資料增強後,模型的訓練和驗證損失曲線更加平滑,準確率也得到了提高。

資料增強技術在深度學習中的應用與實踐

在深度學習領域,資料增強(Data Augmentation)是一種透過對訓練資料進行多樣化轉換,以擴充訓練資料集規模和多樣性的技術。適當的資料增強策略能夠有效提升模型的泛化能力,減少過擬合的風險。本篇文章將探討資料增強的技術細節、實作方法及其在影像分類別任務中的應用。

自定義影像增強層的實作

要實作自定義的影像增強層,必須使用 TensorFlow 的函式,以確保這些操作能夠在 GPU 上高效執行。以下是一個自定義色彩失真層的範例:

class RandomColorDistortion(tf.keras.layers.Layer):
    def __init__(self, name=None, **kwargs):
        super(RandomColorDistortion, self).__init__(name=name, **kwargs)

    def call(self, inputs, training=None):
        if training:
            # 隨機調整對比度和亮度
            inputs = tf.image.random_contrast(inputs, 0.2, 1.8)
            inputs = tf.image.random_brightness(inputs, 0.2)
        return inputs

內容解密:

  1. RandomColorDistortion類別繼承自tf.keras.layers.Layer,以建立自定義層。
  2. call方法中,根據是否在訓練階段(training=True)來決定是否應用隨機色彩失真。
  3. 使用tf.image.random_contrasttf.image.random_brightness來隨機調整輸入影像的對比度和亮度。

將此層插入模型中,可以增加資料的多樣性,範例如下:

layers = [
    ...
    tf.keras.layers.experimental.preprocessing.RandomFlip(
        mode='horizontal',
        name='random_lr_flip/none'
    ),
    RandomColorDistortion(name='random_contrast_brightness/none'),
    hub.KerasLayer(...)
]

內容解密:

  1. RandomFlip層與自定義的RandomColorDistortion層結合使用,以實作多樣化的資料增強策略。
  2. hub.KerasLayer用於載入預訓練模型,如 MobileNet,用於特徵提取。

資料增強的效果與模型結構

應用上述資料增強策略後,模型的結構如下:

Model: "flower_classification"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
random/center_crop (RandomCr (None, 224, 224, 3) 0
_________________________________________________________________
random_lr_flip/none (RandomF (None, 224, 224, 3) 0
_________________________________________________________________
random_contrast_brightness/n (None, 224, 224, 3) 0
_________________________________________________________________
mobilenet_embedding (KerasLa (None, 1280) 2257984
_________________________________________________________________
dense_hidden (Dense) (None, 16) 20496
_________________________________________________________________
flower_prob (Dense) (None, 5) 85
=================================================================
Total params: 2,278,565
Trainable params: 20,581
Non-trainable params: 2,257,984

內容解密:

  1. 資料增強層(如RandomFlipRandomColorDistortion)不包含可訓練引數,因此引數數量為0。
  2. mobilenet_embedding層使用預訓練的 MobileNet 模型,具有大量的不可訓練引數。

資訊丟棄技術

近年來,研究者提出了一些新的資料增強技術,透過丟棄部分影像資訊來提升模型的魯棒性,例如:

  1. Cutout:隨機遮蔽輸入影像的方形區域,以迫使模型關注影像的重要特徵。
  2. Mixup:線性插值兩張訓練影像及其標籤,以創造新的訓練樣本。
  3. CutMix:結合 Cutout 和 Mixup,從不同影像中剪下區域並混合標籤。
  4. GridMask:刪除均勻分佈的方形區域,同時控制刪除區域的密度和大小。

Mixup 的實作

Mixup 的實作需要對一批影像及其標籤進行操作,因此無法直接在 Keras 自定義層中完成。以下是一個實作範例:

def augment_mixup(img, label):
    fracn = np.rint(MIXUP_FRAC * len(img)).astype(np.int32)
    wt = np.random.uniform(0.5, 0.8)
    
    img1, label1 = img[:fracn], label[:fracn]
    img2, label2 = img[1:fracn+1], label[1:fracn+1]
    
    interp_img = _interpolate(img1, img2, wt)
    interp_label = _interpolate(label1, label2, wt)
    
    return interp_img, interp_label

def _interpolate(b1, b2, wt):
    return wt*b1 + (1-wt)*b2

內容解密:

  1. augment_mixup函式根據指定的比例(MIXUP_FRAC)對一批影像及其標籤進行 Mixup 操作。
  2. _interpolate函式用於線性插值兩張影像及其標籤。

Mixup 操作後的結果如圖所示,第一行的原始影像經過 Mixup 後,部分影像被混合,而標籤也相應地進行了插值。