使用 Keras, Tensorflow 進行分散式訓練初探
王建凱 JianKai Wang
2019/03/20
https://github.com/jiankaiwang
https://www.linkedin.com/in/wangjiankai/
從設計架構到實作方式,進入高效模型訓練
內容與資源 AI x Cloud
● 本份文件:
https://ppt.cc/fl8Qex
● 原始碼:
https://github.com/jiankaiwang/distributed_training
● AI、機器學習與深度學習
● 雲端、終端與 AI
● Keras 與 Tensorflow
● 架構與實作概念
Keras
Tensorflow
Deep Learning
Machine Learning
Medical
Commerce
Industry 4.0
2
通用型 AI 開發流程 AI x Cloud x Edge
資料準備
與前處理
(含標註)
資料格式
與存取解
決方式
模型組
態、訓練
與建立
推論、應
用與整合
了解需求
精確命題
應用場域
...
持續性演進
3
Cloud、Edge 皆可
先來看看目前遇到的問題 AI x Cloud
4
問題
要訓練一個可以辨識 201 類圖片的深度神經網路模型,資料集使用 ImageNet,篩
選後大約有 130 萬張圖片 (~ 1.2 TB)。
資源 有一張 NV 1080 Ti (11 GB) 顯卡,有一顆 intel i7 處理器,及 32 GB DRAM。
結果 初估跑完 1000 epochs,需要超過 1 週。
改進 有沒有辦法提升訓練速度及增加訓練資源?
方法 透過平行化、叢集式訓練方式來解決 (當然還有其他,如 Transfer Learning ...等)
為什麼需要平行化、分散式訓練? 縮短訓練時間
- Tensorflow Benchmarks (2019)
5
為什麼需要平行化、分散式訓練? 指數級數據,以圖片為例
- cocodataset.org (2019) - Open Images Dataset V4 (2019)
6
為什麼需要平行化、分散式訓練? 模型的演進
- Minsoo Rhu et al. (2016)
7
那我需要甚麼資源
8
硬體成本
數張高階顯卡
至少一台高階主機
時間成本
作業系統
需要訓練執行環境
人力成本 維運工程師
金錢 預算是否足夠
... ...
若是中小企業、工作室、AI 是加值內容 … 等
自我服務、可擴
增性、按時間計
費、不必擔心硬
體維運 ...那就用 Cloud 吧 !
(當然有例外!
如資料敏感性 ...)
圖像辨識 要解決的問題,監督式學習
推論
訓練機器辨識
這張圖是"卡車"
預期看到這張圖
辨識為"卡車"
訓練
卡車
卡車
訓練資料
測試資料
(圖像 + 標註)
(僅有圖像)
辨識模型
- Photo by Quinn Buffing, Colby Ray on Unsplash (2019) 9
看看使用的資料 CIFAR-10
訓練資料 50000
測試資料 10000
圖像大小 32x32x3
標示分類 10
全資料壓縮大小 ~170 MB
二元檔案集數目 5(訓練) + 1(測試)
相關資料集 CIFAR-100
- https://www.cs.toronto.edu/~kriz/cifar.html (2019)
10
在 Keras 中訓練辨識模型 基礎流程
import keras
class DataGenerator(keras.utils.Sequence):
pass
training_generator = DataGenerator(...)
validation_generator = DataGenerator(...)
num_class = 10
...
dropout = 0.25
model = Sequential()
model.add(...)
model.compile(loss, optimizer, metrics)
model.fit_generator(generator=training_generator,
validation_data=validation_generator, ...)
save_model(model, "cifar10_keras.h5")
# 資料準備工具
#,準備批次訓練及測試資料
# 參數與超參數
# 建立神經網路,可以透過
# summary() 來確認網路
# 建立訓練方式,包含損失函數
#,優化函式與開始訓練網路
# 儲存網路到本地端 11
在 Tensorflow 中訓練辨識模型 基礎流程
IMAGE_SIZE = 32
...
with tf.Graph().as_default():
with tf.variable_scope("cifar10") as scope:
training_data_iter = _train_data_generator()
...
logits = inference(x, kp)
...
summary = tf.summary.merge_all()
saver = tf.train.Saver()
with tf.Session() as sess:
...
for e in range(training_epochs):
for s in range(step_per_epoch):
...
if e % display_step == 0:
...
# TF 是計算圖基礎的框架,訓練
# 與推論都在圖計算底下
# 參數與超參數
# 資料準備工具與建立隨機批次
# 圖、標註等 Tensor 變數
# 建立訓練方式,包含損失函數
#,優化函式等
# 建立訓練記錄 (Tensorboard)、
# 與建立檢核點記錄器 (.ckpt)
# TF 訓練與推論都在 sess 執行
# 開始訓練模型,訓練每達到某一
# 期間,便將目前模型進行儲存
# 並寫入訓練記錄中 12
梯度
深度學習訓練架構
13
架構一 單機單卡 架構二 單機多卡 架構三 多機多卡
子網路
計算子網路 1 計算子網路 2
網路疊合
GPU:0 GPU:1
梯度平均
更新變數
CPU
損失
GPU:0
模型
梯度
損失
GPU:1
模型
資料平行架構
(同步與不同步機制)工作/模型平行
Keras 實現平行訓練方式 目前僅支援 Tensorflow
num_gpus = 2
batch_size = 100
...
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
...
with tf.device('/cpu:0'):
model = Sequential()
model.add(...)
model.add(Activation('softmax'))
parallel_model = multi_gpu_model(model, gpus=num_gpus,
cpu_merge=True)
parallel_model.compile(...)
parallel_model.fit(x_train, y_train, batch_size, ...)
model.save(os.path.join(save_dir, model_name))
● 在 CPU 建構模型
● 模型複製到各 GPU 中
● 在 CPU 對變數梯度進行平均
● 將批次資料平均分配成多份
● 每個 GPU 對子資料進行訓練
● 訓練的變數則傳回 CPU 計算
● 優/缺點 ?
設計架構
14
Tensorflow 實現平行訓練方式
● global_step 為訓練指標
● 透過 queue 及 prefetch 操作資料
● 透過執行緒進行資料預擷取
● 變數儲存主要於 CPU
● 於 GPU 計算損失與梯度
● 於 CPU 彙整並計算平均梯度
● 於 CPU 計算更新後變數值
● 於 CPU 將變數值傳回給不同 GPU
● 優/缺點 ?
設計架構def train():
with tf.Graph().as_default(), tf.device("/cpu:0"):
global_step = tf.get_variable('global_step', ...)
opt = tf.train.GradientDescentOptimizer(lr)
batch_queue = tf.contrib.slim.prefetch_queue.prefetch_queue(...)
with tf.variable_scope(tf.get_variable_scope()):
for i in range(FLAGS.num_gpus):
with tf.device('/gpu:{}'.format(i)):
with tf.name_scope("{}_{}".format(cifar10.TOWER_NAME, i)):
image_batch, label_batch = batch_queue.dequeue()
loss = tower_loss(scope, image_batch, label_batch)
grads = opt.compute_gradients(loss)
...
grads = average_gradients(tower_grads)
apply_gradient_opt = opt.apply_gradients(grads, ...)
variable_averages = tf.train.ExponentialMovingAverage(...)
...
with tf.Session(config=default_conf) as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for step in range(FLAGS.max_steps):
... 15
進階環境配置
16
架構一 單機單卡 架構二 單機多卡 架構三 多機多卡
客戶端
(主處理程序)
主節點 / 參數節點
(部分處理程序)
工作節點
(處理程序 1)
GPU:0 GPU:1
CPU:0 CPU:1
工作節點
(處理程序 2)
GPU:0 GPU:1
CPU:0 CPU:1
工作節點
(處理程序 3)
GPU:0 GPU:1
CPU:0 CPU:1
參數節點
模型設計為主軸
(硬體容錯與效能)
/job:ps/task:0
192.168.0.2:2222
/job:worker/task:0
192.168.0.3:2222
/job:worker/task:1
192.168.0.4:2222
/job:worker/task:2
192.168.0.4:2223
gRPC
分散式訓練
17
架構三 多機多卡 分散式 資料平行
客戶端
(主處理程序)
主節點 / 參數節點
(部分處理程序)
工作節點
(處理程序 1)
工作節點
(處理程序 2)
/job:ps/task:0
192.168.0.2:2222
/job:worker/task:0
192.168.0.3:2222
/job:worker/task:1
192.168.0.4:2222
GPU:1
梯度
損失
模型
GPU:1
梯度
損失
模型
gRPC
Tensorflow 的實現方式
def main(unused_argv):
cluster = tf.train.ClusterSpec({"ps": ps_spec, "worker": worker_spec})
with tf.device(tf.train.replica_device_setter(
worker_device, ps_device="/job:ps/cpu:0", cluster=cluster)):
global_step = tf.Variable(...)
y = _inception_v3(x)
opt = tf.train.AdamOptimizer(FLAGS.learning_rate)
if FLAGS.sync_replicas:
opt = tf.train.SyncReplicasOptimizer(opt, num_workers, ...)
train_step = opt.minimize(cross_entropy, global_step)
...
sv = tf.train.Supervisor(..., init_op, local_init_op, global_step)
sess = sv.prepare_or_wait_for_session(...)
if FLAGS.sync_replicas and is_chief:
sess.run(sync_init_op)
sv.start_queue_runners(sess, [chief_queue_runner])
while True:
_, step = sess.run([train_step, global_step])
...
● global_step 為訓練指標
● 透過 queue 及 prefetch 操作資料
● 資料於各工作節點分別讀取
● 透過執行緒進行資料預擷取
● 須清楚定義參數與工作節點
● 透過 gRPC 傳遞更新參數與梯度
● 參數伺服器建立於單 CPU 節點
● 工作節點建立於多 GPU 節點
● 參數儲存會分配於參數伺服器
● 計算操作子優先分配 GPU 節點
● 參數由第一個工作節點初始化
● session 由第一個工作節點開始
● 透過同步優化器增加容錯
設計架構
18
開源碼執行指令範例 以 bash script 為範例
19
基礎流程
Keras $ python cifar10_training.py
Tensorflow $ python tf_cifar10_training.py
平行化訓練
Keras $ python keras_cifar10_multiple_gpus.py --num_gpus=2 --num_epochs=20
Tensorflow $ python tf_cifar10_multiple_gpus.py --num_gpus=2 --max_steps=10000
叢集式訓練
(Tensorflow)
Parameter
$ python cifar10_replica.py --job_name="ps" --task_index=0 --num_gpus=0 
--ps_hosts=192.168.0.2:2222
--worker_hosts=192.168.0.3:2222,192.168.0.4:2222
Worker 1
$ python cifar10_replica.py --job_name="worker" --task_index=0
--num_gpus=1 --ps_hosts=192.168.0.2:2222
--worker_hosts=192.168.0.3:2222,192.168.0.4:2222
Worker 2
$ python cifar10_replica.py --job_name="worker" --task_index=1
--num_gpus=1 --ps_hosts=192.168.0.2:2222
--worker_hosts=192.168.0.3:2222,192.168.0.4:2222
轉移訓練 智慧轉移,加速訓練的基石
20
任務一
已學習過辨識某
一類圖像資料庫
圖像資料集 2
任務二
辨識模型
圖像資料集 1
轉移智慧
(部分模型)
對新一類資料
進行相似任務
- CIFAR (2019), Tsung-Yi Lin (2015)
結論
● 平行化、叢集式訓練於未來需求更大
● 成本導向訓練模式
● 雲端架構提供深度學習彈性訓練模式
21
王建凱 JianKai Wang
https://jiankaiwang.no-ip.biz/
https://github.com/jiankaiwang
https://www.linkedin.com/in/wangjiankai/

使用 Keras, Tensorflow 進行分散式訓練初探 (Distributed Training in Keras and Tensorflow)

  • 1.
    使用 Keras, Tensorflow進行分散式訓練初探 王建凱 JianKai Wang 2019/03/20 https://github.com/jiankaiwang https://www.linkedin.com/in/wangjiankai/ 從設計架構到實作方式,進入高效模型訓練
  • 2.
    內容與資源 AI xCloud ● 本份文件: https://ppt.cc/fl8Qex ● 原始碼: https://github.com/jiankaiwang/distributed_training ● AI、機器學習與深度學習 ● 雲端、終端與 AI ● Keras 與 Tensorflow ● 架構與實作概念 Keras Tensorflow Deep Learning Machine Learning Medical Commerce Industry 4.0 2
  • 3.
    通用型 AI 開發流程AI x Cloud x Edge 資料準備 與前處理 (含標註) 資料格式 與存取解 決方式 模型組 態、訓練 與建立 推論、應 用與整合 了解需求 精確命題 應用場域 ... 持續性演進 3 Cloud、Edge 皆可
  • 4.
    先來看看目前遇到的問題 AI xCloud 4 問題 要訓練一個可以辨識 201 類圖片的深度神經網路模型,資料集使用 ImageNet,篩 選後大約有 130 萬張圖片 (~ 1.2 TB)。 資源 有一張 NV 1080 Ti (11 GB) 顯卡,有一顆 intel i7 處理器,及 32 GB DRAM。 結果 初估跑完 1000 epochs,需要超過 1 週。 改進 有沒有辦法提升訓練速度及增加訓練資源? 方法 透過平行化、叢集式訓練方式來解決 (當然還有其他,如 Transfer Learning ...等)
  • 5.
  • 6.
  • 7.
  • 8.
    那我需要甚麼資源 8 硬體成本 數張高階顯卡 至少一台高階主機 時間成本 作業系統 需要訓練執行環境 人力成本 維運工程師 金錢 預算是否足夠 ...... 若是中小企業、工作室、AI 是加值內容 … 等 自我服務、可擴 增性、按時間計 費、不必擔心硬 體維運 ...那就用 Cloud 吧 ! (當然有例外! 如資料敏感性 ...)
  • 9.
  • 10.
    看看使用的資料 CIFAR-10 訓練資料 50000 測試資料10000 圖像大小 32x32x3 標示分類 10 全資料壓縮大小 ~170 MB 二元檔案集數目 5(訓練) + 1(測試) 相關資料集 CIFAR-100 - https://www.cs.toronto.edu/~kriz/cifar.html (2019) 10
  • 11.
    在 Keras 中訓練辨識模型基礎流程 import keras class DataGenerator(keras.utils.Sequence): pass training_generator = DataGenerator(...) validation_generator = DataGenerator(...) num_class = 10 ... dropout = 0.25 model = Sequential() model.add(...) model.compile(loss, optimizer, metrics) model.fit_generator(generator=training_generator, validation_data=validation_generator, ...) save_model(model, "cifar10_keras.h5") # 資料準備工具 #,準備批次訓練及測試資料 # 參數與超參數 # 建立神經網路,可以透過 # summary() 來確認網路 # 建立訓練方式,包含損失函數 #,優化函式與開始訓練網路 # 儲存網路到本地端 11
  • 12.
    在 Tensorflow 中訓練辨識模型基礎流程 IMAGE_SIZE = 32 ... with tf.Graph().as_default(): with tf.variable_scope("cifar10") as scope: training_data_iter = _train_data_generator() ... logits = inference(x, kp) ... summary = tf.summary.merge_all() saver = tf.train.Saver() with tf.Session() as sess: ... for e in range(training_epochs): for s in range(step_per_epoch): ... if e % display_step == 0: ... # TF 是計算圖基礎的框架,訓練 # 與推論都在圖計算底下 # 參數與超參數 # 資料準備工具與建立隨機批次 # 圖、標註等 Tensor 變數 # 建立訓練方式,包含損失函數 #,優化函式等 # 建立訓練記錄 (Tensorboard)、 # 與建立檢核點記錄器 (.ckpt) # TF 訓練與推論都在 sess 執行 # 開始訓練模型,訓練每達到某一 # 期間,便將目前模型進行儲存 # 並寫入訓練記錄中 12
  • 13.
    梯度 深度學習訓練架構 13 架構一 單機單卡 架構二單機多卡 架構三 多機多卡 子網路 計算子網路 1 計算子網路 2 網路疊合 GPU:0 GPU:1 梯度平均 更新變數 CPU 損失 GPU:0 模型 梯度 損失 GPU:1 模型 資料平行架構 (同步與不同步機制)工作/模型平行
  • 14.
    Keras 實現平行訓練方式 目前僅支援Tensorflow num_gpus = 2 batch_size = 100 ... (x_train, y_train), (x_test, y_test) = cifar10.load_data() ... with tf.device('/cpu:0'): model = Sequential() model.add(...) model.add(Activation('softmax')) parallel_model = multi_gpu_model(model, gpus=num_gpus, cpu_merge=True) parallel_model.compile(...) parallel_model.fit(x_train, y_train, batch_size, ...) model.save(os.path.join(save_dir, model_name)) ● 在 CPU 建構模型 ● 模型複製到各 GPU 中 ● 在 CPU 對變數梯度進行平均 ● 將批次資料平均分配成多份 ● 每個 GPU 對子資料進行訓練 ● 訓練的變數則傳回 CPU 計算 ● 優/缺點 ? 設計架構 14
  • 15.
    Tensorflow 實現平行訓練方式 ● global_step為訓練指標 ● 透過 queue 及 prefetch 操作資料 ● 透過執行緒進行資料預擷取 ● 變數儲存主要於 CPU ● 於 GPU 計算損失與梯度 ● 於 CPU 彙整並計算平均梯度 ● 於 CPU 計算更新後變數值 ● 於 CPU 將變數值傳回給不同 GPU ● 優/缺點 ? 設計架構def train(): with tf.Graph().as_default(), tf.device("/cpu:0"): global_step = tf.get_variable('global_step', ...) opt = tf.train.GradientDescentOptimizer(lr) batch_queue = tf.contrib.slim.prefetch_queue.prefetch_queue(...) with tf.variable_scope(tf.get_variable_scope()): for i in range(FLAGS.num_gpus): with tf.device('/gpu:{}'.format(i)): with tf.name_scope("{}_{}".format(cifar10.TOWER_NAME, i)): image_batch, label_batch = batch_queue.dequeue() loss = tower_loss(scope, image_batch, label_batch) grads = opt.compute_gradients(loss) ... grads = average_gradients(tower_grads) apply_gradient_opt = opt.apply_gradients(grads, ...) variable_averages = tf.train.ExponentialMovingAverage(...) ... with tf.Session(config=default_conf) as sess: coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(coord=coord) for step in range(FLAGS.max_steps): ... 15
  • 16.
    進階環境配置 16 架構一 單機單卡 架構二單機多卡 架構三 多機多卡 客戶端 (主處理程序) 主節點 / 參數節點 (部分處理程序) 工作節點 (處理程序 1) GPU:0 GPU:1 CPU:0 CPU:1 工作節點 (處理程序 2) GPU:0 GPU:1 CPU:0 CPU:1 工作節點 (處理程序 3) GPU:0 GPU:1 CPU:0 CPU:1 參數節點 模型設計為主軸 (硬體容錯與效能) /job:ps/task:0 192.168.0.2:2222 /job:worker/task:0 192.168.0.3:2222 /job:worker/task:1 192.168.0.4:2222 /job:worker/task:2 192.168.0.4:2223 gRPC
  • 17.
    分散式訓練 17 架構三 多機多卡 分散式資料平行 客戶端 (主處理程序) 主節點 / 參數節點 (部分處理程序) 工作節點 (處理程序 1) 工作節點 (處理程序 2) /job:ps/task:0 192.168.0.2:2222 /job:worker/task:0 192.168.0.3:2222 /job:worker/task:1 192.168.0.4:2222 GPU:1 梯度 損失 模型 GPU:1 梯度 損失 模型 gRPC
  • 18.
    Tensorflow 的實現方式 def main(unused_argv): cluster= tf.train.ClusterSpec({"ps": ps_spec, "worker": worker_spec}) with tf.device(tf.train.replica_device_setter( worker_device, ps_device="/job:ps/cpu:0", cluster=cluster)): global_step = tf.Variable(...) y = _inception_v3(x) opt = tf.train.AdamOptimizer(FLAGS.learning_rate) if FLAGS.sync_replicas: opt = tf.train.SyncReplicasOptimizer(opt, num_workers, ...) train_step = opt.minimize(cross_entropy, global_step) ... sv = tf.train.Supervisor(..., init_op, local_init_op, global_step) sess = sv.prepare_or_wait_for_session(...) if FLAGS.sync_replicas and is_chief: sess.run(sync_init_op) sv.start_queue_runners(sess, [chief_queue_runner]) while True: _, step = sess.run([train_step, global_step]) ... ● global_step 為訓練指標 ● 透過 queue 及 prefetch 操作資料 ● 資料於各工作節點分別讀取 ● 透過執行緒進行資料預擷取 ● 須清楚定義參數與工作節點 ● 透過 gRPC 傳遞更新參數與梯度 ● 參數伺服器建立於單 CPU 節點 ● 工作節點建立於多 GPU 節點 ● 參數儲存會分配於參數伺服器 ● 計算操作子優先分配 GPU 節點 ● 參數由第一個工作節點初始化 ● session 由第一個工作節點開始 ● 透過同步優化器增加容錯 設計架構 18
  • 19.
    開源碼執行指令範例 以 bashscript 為範例 19 基礎流程 Keras $ python cifar10_training.py Tensorflow $ python tf_cifar10_training.py 平行化訓練 Keras $ python keras_cifar10_multiple_gpus.py --num_gpus=2 --num_epochs=20 Tensorflow $ python tf_cifar10_multiple_gpus.py --num_gpus=2 --max_steps=10000 叢集式訓練 (Tensorflow) Parameter $ python cifar10_replica.py --job_name="ps" --task_index=0 --num_gpus=0 --ps_hosts=192.168.0.2:2222 --worker_hosts=192.168.0.3:2222,192.168.0.4:2222 Worker 1 $ python cifar10_replica.py --job_name="worker" --task_index=0 --num_gpus=1 --ps_hosts=192.168.0.2:2222 --worker_hosts=192.168.0.3:2222,192.168.0.4:2222 Worker 2 $ python cifar10_replica.py --job_name="worker" --task_index=1 --num_gpus=1 --ps_hosts=192.168.0.2:2222 --worker_hosts=192.168.0.3:2222,192.168.0.4:2222
  • 20.
  • 21.
    結論 ● 平行化、叢集式訓練於未來需求更大 ● 成本導向訓練模式 ●雲端架構提供深度學習彈性訓練模式 21 王建凱 JianKai Wang https://jiankaiwang.no-ip.biz/ https://github.com/jiankaiwang https://www.linkedin.com/in/wangjiankai/