iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
0
AI & Data

深度學習裡的冰與火之歌 : Tensorflow vs PyTorch系列 第 22

Day 22: Tensorflow 2.0: 再造訪 `tf.estimator` 和 `tf.data`

  • 分享至 

  • xImage
  •  

致讀者:目前你所看到的是鐵人賽搶先版。 陸續還有更新。

tf.estimator

tf.estimator 也是一個 High-level API,作用與 tf.keras 相同,都是為了提供一個簡單的深度學習建模介面。該介面提供了一些已經包裝好程式碼的 tf.estimator.Estimator 類別,但也容許使用者提供客製化的模型建立函式作為 model_fn 的引數,建立相等的 tf.estimator.Estimator
有些人可能想要問,既然和 tf.keras 差不多,那麼 tf.estimator.Estimator 有什麼特別呢?
tf.estimator.Estimator 具有以下特性是 tf.keras 缺乏或還在開發中的特徵:

  1. 可以使用 Parameter Sever 的方式訓練
  2. 與 TensorFlow Extended(TFX) 無縫整合:TFX 是一個端對端的平台,開發者可以將 production-ready 的機械學習模型配置到該平台上。

關於如何建制一個 tf.Estimator,我們就來介紹例子:

預先封裝好的 tf.Estimator

預先封裝好的(pre-made)tf.Estimator 都把模型的邏輯撰寫完畢,使用者只要提供資料餵送的設計即可。而在tf.Estimator 官方文件中,則提供了程式撰寫的流程:

  1. 撰寫一或多個資料輸入的函式:這個部分就需要使用 tf.data.Dataset (見下文)去包覆未處理過的資料,將之依照需要處理,最後以批次的方式來完成 mini-batch 的訓練。
  2. 定義特徵欄位:這個部分則是使用 tf.feature_column 來定義已封裝好的 tf.Estimator 使用的特徵,是什麼樣的資料型態,若是非數值特徵又是如何編碼。
  3. 實例化相關的 tf.Estimator類別:欲實例化 tf.Estimator 類別產生物件,通常需要提供 Step 2 所建立的 tf.feature_column物件們。
  4. 呼叫 training, evaluation, 或 inference 方法來進行訓練和模型驗證.

目前在 tf.estimator下的預先封裝好的 tf.Estimator有:

  1. Linear[Classifier|Estimator|Regressor]:模型為線性
  2. DNN[Classifier|Estimator|Regressor]:模型為一個 MLP,也就是每一層都是一個全連階層的類神經網路
  3. DNNLinearCombined[Classifier|Estimator|Regressor]:該篇為 wide-n-deep 的實作。
  4. BoostedTrees[Classifier|Estimator|Regressor]:Gradient boosting 的 Tensorflow 實作
  5. Baseline[Classifier|Estimator|Regressor]

使用預先封裝好的 tf.Estimator有兩個優點:那就是如何配置運算元的程式邏輯都已封裝在類別裡,使用者無須擔心。除此之外,呼叫 tf.summary 等所撰寫的訓練記錄檔的程式邏輯也已封裝在類別裡,使用者也無撰寫任何有可能傷害模型效率的原始碼。

客製化的 tf.Estimator

如果要客製化 tf.Estimator,方法也很簡單,只要提供 model_fn即可。這個model_fn是一個函式主要提供模型建構的邏輯。

若你是用 tf.keras 來建模,卻也希望能轉換成 tf.Estimator ,已獲得tf.Estimator 的好處,那麼你可以這麼做:呼叫 tf.keras.estimator.model_to_estimator 函式。下面的程式碼,先用 tf.keras 的 Sequential API 建立了一個很簡單的模型,最後用上述的轉換函式來轉成 tf.Estimator

estimator_model = tf.keras.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(1, activation='softmax')
])

# Compile 模型,這一定要在呼叫 model_to_estimator 前執行
estimator_model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metric='accuracy')
    
est_mobilenet_v2 = tf.keras.estimator.model_to_estimator(keras_model=estimator_model)

tf.data

我們在已封裝的 tf.Estimator中,提到準備一到多個 tf.data.Dataset輸入函式來做訓練輸入,現在就來看看該怎麼利用 tf.data.Dataset 來準備我們的輸入資料供訓練,驗證和預測用。首先,我們要來看看創建資料集的方法:

  1. 是仰賴資料來源,這個資料來源可以是在記憶體或是在硬碟以一個或多個檔案的方式存在
  2. 呼叫資料處理函式對 tf.data.Dataset 進行轉換:這裏的轉換可以看作是 data pipeline 的其中一個步驟,該步驟執行後會保證輸出為 tf.data.Dataset

tf.data.Dataset 可以使用於 tf.Estimatortf.keras 的模型建制 API,在進入 tf.data 的詳盡內容前,先來看看如何利用 tf.data.Dataset 來餵送資料給 tf.keras.Modeltf.Estimator

tf.keras.Model

tf.keras.Model 能夠使用的資料型態為在記憶體中的 numpy.ndarray,所以我們可以用 tf.data.Dataset.from_tensor_slices 來建立 tf.data.Datasettf.data.Dataset.from_tensor_slices 的使用也很簡單,必須鎚入一個兩個元素的 tuple 物件,第一個元素為特徵,第二個則是標注。兩個元素都是 numpy.ndarray 物件。由此法建立的 tf.data.Dataset 還可以藉著應用上 tf.data 模組下的資料轉換類別,建立資料修改的 pipeline。常見的轉換包括了 shufflebatch。另外,有鑒於訓練時需要多次餵送所有的訓練資料(被稱為一個 epoch),所以使用 repeat方法保證餵送所有的 tf.data.Dataset長度是無限大或無限次從頭餵送。
接下來,我們就來看一個程式範例,在這個範例中我們會先用 tf.keras 裡的 dataset 模組下載fashion_mnist 這組資料並載入在記憶體中。這組資料及在記憶體中會是以 numpy.ndarray 的方式儲存。然後,將做完正規化的影像和標注傳入tf.data.Dataset.from_tensor_slices 方法慘生 tf.data.Dataset 物件,最後用此物件來做訓練,驗證和預測。

train, test = tf.keras.datasets.fashion_mnist.load_data()

images, labels = train
images = images/255.0  #做正規劃,使影像值在 0 - 1 之殲
labels = labels.astype(np.int32)   #本來為 uint8 轉為 int32

fmnist_train_ds = tf.data.Dataset.from_tensor_slices((images, labels))
fmnist_train_ds = fmnist_train_ds.shuffle(5000).batch(32) # data pipeline

#...建立 tf.keras.Model 模型使用 Sequential API,然後 compile(省略)

model.fit(fmnist_train_ds, epochs=2) # 沒有使用 repeat() 時,會跑 epochs*len(images)/batch_size 而 batch_size = 32 
model.fit(fmnist_train_ds.repeat(), epochs=2, steps_per_epoch=20) # 使用 repeat() 時,會跑 epochs*steps_per_epoch
 
loss, accuracy = model.evaluate(fmnist_train_ds) # 不使用 repeat()
loss, accuracy = model.evaluate(fmnist_train_ds.repeat(), steps=10) #使用 repeat(),用 step 參數控制要多少的資料被評估

# 建立測試資料集,其中標注不可得
predict_ds = tf.data.Dataset.from_tensor_slices(images).batch(32)
result = model.predict(predict_ds , steps = 10)

在上面的程式範例中,我們可以看到 repeat()的行為可以透過參數,如 fit 方法的 steps_per_epochevaluate 方法中的 step 來控制。筆者可以想到使用 repeat 的場景便是和 shuffle結合,讓 shuffle 產生無限多個訓練資料序列(因為訓練例子通常很多,所以可以假設 shuffle 的空間是指數成長的序列個數)。
至於 shuffle 所需要使用者提供的引數為 buffer_sizeshuffle 演算法的實踐邏輯則是從資料原本的排列從頭取出 buffer_size的元素來做任意排列。這個引數主要是防止巨量的訓練資料,而造成記憶體不足的現象,如果是小量的訓練資料,則可以將buffer_size設為訓練資料的長度。另外,shuffle 還有一個參數為 reshuffle_each_iteration,這個參數只接受布林值,若設為 True(預設),則在每次疊代就做一次任意排列的動作,若為 False,則不會。

tf.Estimator

tf.estimator.Estimator 使用 tf.data.Dataset 的方法與 tf.keras.Model 很相像,都是在呼叫tf.estimator.Estimatortraining, evaluateinferenceinput_fn 方式傳入。不一樣的是 tf.estimator.Estimator不可以直接以 tf.data.Dataset 的方式傳入,而是必須以 python function 來傳入。
除此之外,tf.estimator.Estimator 能夠接受較廣的資料集,而非只有從記憶體載入。下面的程式碼則是建立一個資料集,該資料集會從硬碟做 csv 檔案解析,最後載入資料到記憶體中。

import tensorflow_datasets as tfds

def train_input_fn():
  # 需要將資料集用函式包裝,方可傳入`tf.estimator.Estimator`的方法 
  titanic = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=32, # titanic_file,檔案名稱
    label_name="survived")
  titanic_batches = (
      titanic.cache().repeat().shuffle(500)
      .prefetch(tf.data.experimental.AUTOTUNE))
  return titanic_batches
  
# ...建立 feature_column 後傳入 tf.estimator.Estimator 建構子,最後生成物件(省略)

model = model.train(input_fn=train_input_fn, steps=100)

上面的程式碼可以看到先由 tf.data.experimental.make_csv_dataset 來解析 titanic_file 所指導的csv 檔案名稱。titanic_file 在多檔案的情況下,可以是檔案名稱的共同樣式,最後可以呼叫 glob 將依據樣式找到的檔案讀入,也可以是一個 python list of strings,在 python list 的每一個字串,都是一個儲存訓練資料的檔案名稱。
程式碼中的資料管線則是和 tf.keras.Model 的程式碼相似,但是先呼叫 cache方法,提取在 tf.data.Dataset cache 在記憶體的訓練資料,若 cache 的 filename 引數有指定,則會 cache 到所指定的檔案。將訓練資料先 cache起來,在處理檔案的資料集上特別有用。另外一個則是 prefetch 則是預先將訓練例子載入到記憶體中。prefetch 需要一個必要的參數為 buffer_size,這裏的 buffer_size 指的是必須先行載入到記憶體的元素個數。這理解的是元素個數,是為了和訓練個數作區別。這裏的元素個數會因為 tf.data.Dataset 目前提取資料的方式而改變,若 tf.data.Dataset 最後做了 batch 轉換,那麼 prefetch 先行提取的元素個數則為 batch_size * 元素個數。若沒有做 batch 轉換,則prefetch 先行提取的元素個數 則為訓練個數。


上一篇
Day 21: Tensorflow 2.0: 再造訪 Model Persistence
下一篇
Day 23: Tensorflow 2.0: 再造訪 Distribute Strategy API
系列文
深度學習裡的冰與火之歌 : Tensorflow vs PyTorch31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言