1. 程式人生 > >基於tensorflow的深度學習MultiGPU訓練實戰

基於tensorflow的深度學習MultiGPU訓練實戰

更多深度學習NLP方面應用的經典論文、實踐經驗和最新訊息,歡迎關注微信公眾號深度學習與NLP” 或掃描頭像二維碼新增關注。

進行深度學習模型訓練的時候,一般使用GPU來進行加速,當訓練樣本只有百萬級別的時候,單卡GPU通常就能滿足我們的需求,但是當訓練樣本量達到上千萬,上億級別之後,單卡訓練耗時很長,這個時候通常需要採用多機多卡加速。深度學習多卡訓練常見有兩種方式,一種是資料並行化(data parallelism),另外一種是模型並行化(model parallelism)。

資料並行化:每個GPU上面跑一個模型,模型與模型之間結構引數相同,只是訓練的資料不一樣,每個模型通過最後的

loss計算得到梯度之後,再把梯度傳到一個parameter serverPS)上進行引數平均average gradient,然後再根據average gradient更新模型的引數。

       資料並行化分為梯度的更新分為同步和非同步兩種模式。

同步模式:等到所有的資料分片都完成了梯度計算並把梯度傳到PS之後統一的更新每個模型的引數。優點是訓練穩定,訓練出來的模型得到精度比較高;缺點是訓練的時間取決於分片中最慢的那個片,所以同步模式適用於GPU之間效能差異不大情況下。

模型並行化:當一個模型非常複雜,非常大,達到單機的記憶體根本沒法容納的時候,模型並行化就是一個好的選擇。直觀說就多多個

GPU訓練,每個GPU分別持有模型的一個片。它的優點很明顯,大模型訓練,缺點就是模型分片之間的通訊和資料傳輸很耗時,所以不能簡單說,模型並行就一定比資料並行要快。


 還有資料並行和模型並行的混合模型:


資料並行適用於資料量比較小時快速訓練模型,模型並行適用於大資料、大模型場景下。這裡只是簡單介紹,想要深入瞭解細節可以找其他資料學習一下。下面主要基於tensorflow講一個數據並行化的例項。

1、單機多卡訓練:給個例子,比如一臺機器上裝有4GPU卡,以cpu做為PSmaster),主要儲存一下引數和變數,進行梯度平均。其餘4GPU訓練模型(worker),進行一些計算量比加大的操作。

    1)本地對資料切分為一個一個batch

    2)把資料分別放到送到4GPU進行模型訓練,每個GPU拿到資料不一樣;

    3)四個GPU訓練,求loss得到梯度,並把梯度送回到CPU進行模型平均。

    4)cpu接收4gpu傳來的梯度,進行梯度平均。

    5)四個GPU跟新引數

    6)重複2~5知道模型收斂。

2、分散式的多久多卡:當是在一個多臺機器的叢集上訓練的時候採用這種方式,在tensorflow中需要明確指定psworker的地址,這種方式相容單機多卡,只是把psworker的地址設為local就可以了。

下面簡要介紹下tensorflow中支援多卡訓練和引數更新的幾個API,具體介紹可以參考這篇文章(Distributedtensorflow實現原理http://blog.csdn.net/lqfarmer/article/details/70214026

Tensorflow進行重複性訓練有In-graph replicationBetween-graphreplication兩種方式,In-graph replication就是資料並行化模式,Between-graphreplication就是資料並行化模式。梯度更新有非同步Asynchronous training和同步Synchronous training兩種模式。

Tensorflow官網也給了一個cifar10_multi_gpu_train.py 的例子,在單機多卡上執行,這裡我給一個自己做的單機多卡訓練的簡單例子供參考,自己在搭建這個結構過程中也栽了很多坑,還在繼續探索中,僅有訓練部分。

程式主要分為五個部分:

Main函式:定義主要執行邏輯;

Run_epoch函式:定義主要訓練邏輯;

Generate_feed_dic函式:產生訓練需要的batch樣本;

Multi_gpu_model函式:定義多個tower,每個tower對應一個gpu

Average_gradients函式:梯度平均計算。

一下是完整程式碼:

#critital class define

#getaverage gradient

defaverage_gradients(tower_grads):

  average_grads = []

  for grad_and_vars in zip(*tower_grads):

    grads = []

    for g, _ in grad_and_vars:

      expanded_g = tf.expand_dims(g, 0)

      grads.append(expanded_g)

    grad = tf.concat(axis=0, values=grads)

    grad = tf.reduce_mean(grad, 0)

    v = grad_and_vars[0][1]

    grad_and_var = (grad, v)

    average_grads.append(grad_and_var)

  return average_grads

#setupmultiple gpu tower            

defmulti_gpu_model(num_gpus=4, word_embeddings = None):

    grads = []

    global_step = tf.Variable(0,name="global_step", trainable=False)

    optimizer = tf.train.AdamOptimizer(1e-3)

    withtf.variable_scope(tf.get_variable_scope()) as initScope:

        for i in range(num_gpus):

            withtf.device("/gpu:%d"%i):

              withtf.name_scope("tower_%d"%i):

                siameseModel = SiameseLSTM(

                                sequence_length=FLAGS.max_document_length,

                               embedding_size=FLAGS.embedding_dim,

                               hidden_units=FLAGS.hidden_units,

                               l2_reg_lambda=FLAGS.l2_reg_lambda,

                                batch_size=FLAGS.batch_size,

                               word_embeddings=word_embeddings)

               tf.get_variable_scope().reuse_variables()

               tf.add_to_collection("train_model", siameseModel)

                grad_and_var =optimizer.compute_gradients(siameseModel.loss)

                grads.append(grad_and_var)

               tf.add_to_collection("loss",siameseModel.loss)

               tf.add_to_collection("accuracy",siameseModel.accuracy)

                tf.add_to_collection("distance",siameseModel.distance)                 

    with tf.device("cpu:0"):

        averaged_gradients =average_gradients(grads)

        train_op =optimizer.apply_gradients(averaged_gradients, global_step=global_step)

    return train_op,global_step

#generating training data      

defgenerate_feed_dic(sess, batch_generator,feed_dict,train_op):

    SMS =tf.get_collection("train_model")

    for siameseModel in SMS:

        x1_batch, x2_batch, y_batch =batch_generator.next()

        if random()>0.5:

            feed_dict[siameseModel.input_x1] =x1_batch

            feed_dict[siameseModel.input_x2] =x2_batch

            feed_dict[siameseModel.input_y] =y_batch

            feed_dict[siameseModel.dropout_keep_prob]= FLAGS.dropout_keep_prob

        else:

            feed_dict[siameseModel.input_x1] =x2_batch

            feed_dict[siameseModel.input_x2] =x1_batch

            feed_dict[siameseModel.input_y] =y_batch

            feed_dict[siameseModel.dropout_keep_prob]= FLAGS.dropout_keep_prob

    return feed_dict           

#define main trainingprocess

def run_epoch(sess,train_x1_idsList,train_x2_idsList,train_y,scope,global_step,train_op=None,is_training=False):

    if is_training:

        epoches = len(train_x1_idsList) //FLAGS.batch_size

        batch_generator =datatool.data_iterator(train_x1_idsList, train_x2_idsList,train_y,FLAGS.batch_size,FLAGS.max_document_length)

#         siameseModels =tf.get_collection("train_model")

        while epoches > 0:

            feed_dict = {}

            epoches -= 1

            feed_dict =generate_feed_dic(sess,batch_generator,feed_dict,train_op)

            i = FLAGS.num_iteration

            while i > 0:

                i = i - 1

                losses =tf.get_collection("loss")

                accuracy =tf.get_collection("accuracy")

                distance =tf.get_collection("distance")

                total_accuracy =tf.add_n(losses, name='total_accu')

                total_distance = tf.add_n(losses,name='total_distance')

                total_loss = tf.add_n(losses,name='total_loss')

                avg_losses = total_loss / 4

                avg_accu = total_accuracy / 4

                avg_dist = total_distance / 4

                time_str =datetime.datetime.now().isoformat()

               _,step,avg_losses,avg_accu,avg_dist =sess.run([train_op,global_step,total_loss,avg_accu,avg_dist],feed_dict)

                                     #輸出訓練精度

                print("TRAIN {}: step {},avg_loss {:g}, avg_dist {:g}, avg_acc {:g}".format(time_str, step,avg_losses, avg_dist, avg_accu))

 #whole training process      

defmain(argv=None):

    print("\nParameters:")

    for attr, value insorted(FLAGS.__flags.items()):

        print("{}={}".format(attr.upper(),value))

    print("")

    #載入詞向量

    word2id, word_embeddings =datatool.load_word2vec("your dir for word2vec")

    print("load train data")

    (train_x1_idsList,train_x2_idsList,train_y),(valid_x1_idsList, valid_x2_lList,valid_y) =datatool.get_data_for_siamese(word2id, FLAGS.data_path)

    print("starting graph def")

    gpu_options =tf.GPUOptions(per_process_gpu_memory_fraction=0.8)

    withtf.Graph().as_default():#,tf.device('/cpu:0')

        session_conf = tf.ConfigProto(

           allow_soft_placement=FLAGS.allow_soft_placement,

           log_device_placement=FLAGS.log_device_placement,

            gpu_options=gpu_options)

        sess = tf.Session(config=session_conf)

        print("started session")

        print ("build multiplemodel")

        with tf.name_scope("train")as train_scope:

            print("define multiple gpumodel and init the training operation")

            train_op,global_step =multi_gpu_model(FLAGS.num_gpus,word_embeddings)

            print ("init allvariable")

           sess.run(tf.global_variables_initializer())

            print ("run epochestage")

           run_epoch(sess,train_x1_idsList,train_x2_idsList,train_y,train_scope,global_step,train_op,True)

        # Checkpoint directory. Tensorflowassumes this directory already exists so we need to create it

        timestamp = str(int(time.time()))

        checkpoint_dir =os.path.abspath(os.path.join(out_dir, "checkpoints"))

        checkpoint_prefix =os.path.join(checkpoint_dir, "model")

        if not os.path.exists(checkpoint_dir):

            os.makedirs(checkpoint_dir)

        out_dir =os.path.abspath(os.path.join(os.path.curdir, "runs", timestamp))

        print("Writing to {}\n".format(out_dir))

        saver =tf.train.Saver(tf.global_variables(), max_to_keep=100)

注意:我用的是已經訓練好的詞向量,這裡只需要載入進來就可以了。

相關推薦

基於tensorflow深度學習MultiGPU訓練實戰

更多深度學習在NLP方面應用的經典論文、實踐經驗和最新訊息,歡迎關注微信公眾號“深度學習與NLP” 或掃描頭像二維碼新增關注。 進行深度學習模型訓練的時候,一般使用GPU來進行加速,當訓練樣本只有百萬級別的時候,單卡GPU通常就能滿足我們的需求,但是當訓練樣本量達到上千

深度學習分散式訓練實戰(一)

本系列部落格主要介紹使用Pytorch和TF進行分散式訓練,本篇重點介紹相關理論,分析為什麼要進行分散式訓練。後續會從程式碼層面逐一介紹實際程式設計過程中如何實現分散式訓練。 常見的訓練方式 單機單卡(單GPU) 這種訓練方式一般就是在自己筆記本上,窮學生專

深度學習分散式訓練實戰(二)——TF

本篇部落格主要介紹TF的分散式訓練,重點從程式碼層面進行講解。理論部分可以參考深度學習分散式訓練實戰(一) TF的分散式實現方式 TF的分散式有兩種實現方式,一種是圖內分散式(In-graph replication);一種是圖間分散式(Between-gra

[TensorFlow深度學習深入]實戰一·使用embedding_lookup模組對Word2Vec訓練儲存與簡單使用

[TensorFlow深度學習深入]實戰一·使用embedding_lookup模組對Word2Vec訓練儲存與簡單使用 Word2Vec簡介 One hot representation用來表示詞向量非常簡單,但是卻有很多問題。最大的問題是我們的詞彙表一般都非常大,比

tensorflow深度學習實戰筆記(三):使用tensorflow lite把訓練好的模型移植到手機端,編譯成apk檔案

目錄 tensorflow深度學習實戰筆記(二):把訓練好的模型進行固化,講解了如何固化模型以及把pb模型轉換為tflite模型,現在講解如何用官方的demo把生成的ttlite模型移植到手機端。 一、準備工作 1.1模型訓練 1.

TensorFlow深度學習實戰---MNIST數字識別問題

驗證 ali 結構 shadow -m spa 直接 訓練數據 叠代 1.滑動平均模型: 用途:用於控制變量的更新幅度,使得模型在訓練初期參數更新較快,在接近最優值處參數更新較慢,幅度較小 方式:主要通過不斷更新衰減率來控制變量的更新幅度。 衰減率計算公式 :

TensorFlow深度學習實戰---圖像識別與卷積神經網絡

實戰 都是 循環 特征 結構 分析 神經網絡 圖片 網絡 全連接層網絡結構:神經網絡每兩層之間的所有結點都是有邊相連的。 卷積神經網絡:1.輸入層 2.卷積層:將神經網絡中的每一個小塊進行更加深入地分析從而得到抽象程度更高的特征。

[TensorFlow深度學習入門]實戰四·邏輯迴歸鳶尾花進行分類(對比均方根誤差與softmax交叉熵誤差區別)

[TensorFlow深度學習入門]實戰四·邏輯迴歸鳶尾花進行分類 問題描述 資料集 鳶尾花資料集下載地址 鳶尾花資料集包含四個特徵和一個標籤。這四個特徵確定了單株鳶尾花的下列植物學特徵: 1、花萼長度 2、花萼寬度 3、花瓣長度 4、花瓣寬度 該標籤確定了鳶尾花品種,

[TensorFlow深度學習入門]實戰十一·用雙向BiRNN(LSTM)做手寫數字識別準確率99%+

[TensorFlow深度學習入門]實戰十一·用雙向BiRNN(LSTM)做手寫數字識別準確率99%+ 此博文是我們在完成實戰五·用RNN(LSTM)做手寫數字識別的基礎上使用BiRNN(LSTM)結構,進一步提升模型的準確率,1000steps準確率達到99%。 首先我們先

TensorFlow深度學習實戰(一):AlexNet對MNIST資料集進行分類

概要 進來一段時間在看深度學習中經典的CNN模型相關論文。同時,為了督促自己學習TensorFlow,通讀論文之後開始,利用TensorFlow實現各個模型,復現相關實驗。這是第一篇論文講解的是AlexNet,論文下載網址為:ImageNet Classific

[TensorFlow深度學習深入]實戰三·分別使用DNN,CNN與RNN(LSTM)做文字情感分析(機器如何讀懂人心)

[TensorFlow深度學習深入]實戰三·使用Word2Vec與RNN(LSTM)做文字情感分析(機器如何讀懂人心) 用到了 DNN CNN Word2Vec RNN(LSTM) 不太清楚的可以回顧我們之前的博文。 使用了全連線,卷積神經網路與迴

[TensorFlow深度學習深入]實戰二·使用CNN網路識別破解數字驗證碼

[TensorFlow深度學習深入]實戰二·使用CNN網路識別破解數字驗證碼 參考部落格。 在此基礎上做了小修改。 其中CNN網路部分仿照我們入門實戰六的內容,如果不太清楚CNN可以再去回顧一下。 本博文資料集。 程式碼部分 import os os.environ["KMP_D

[TensorFlow深度學習入門]實戰十二·使用DNN網路實現自動編碼器

[TensorFlow深度學習入門]實戰十二·使用DNN網路實現自動編碼器 測試程式碼 import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" import tensorflow as tf from tensorflow

[TensorFlow深度學習入門]實戰十·用RNN(LSTM)做時間序列預測(曲線擬合)

[TensorFlow深度學習入門]實戰十·用RNN(LSTM)做時間序列預測(曲線擬合) %matplotlib inline import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" import numpy as np import

[TensorFlow深度學習入門]實戰九·用CNN做科賽網TibetanMNIST藏文手寫數字資料集準確率98%+

[TensorFlow深度學習入門]實戰九·用CNN做科賽網TibetanMNIST藏文手寫數字資料集準確率98.8%+ 我們在博文,使用CNN做Kaggle比賽手寫數字識別準確率99%+,在此基礎之上,我們進行對科賽網TibetanMNIST藏文手寫數字資料集訓練,來驗證網路的正確性。

[TensorFlow深度學習入門]實戰八·簡便方法實現TensorFlow模型引數儲存與載入(pb方式)

[TensorFlow深度學習入門]實戰八·簡便方法實現TensorFlow模型引數儲存與載入(pb方式) 在上篇博文中,我們探索了TensorFlow模型引數儲存與載入實現方法採用的是儲存ckpt的方式。這篇博文我們會使用儲存為pd格式檔案來實現。 首先,我會在上篇博文基礎上,實現由c

[TensorFlow深度學習入門]實戰七·簡便方法實現TensorFlow模型引數儲存與載入(ckpt方式)

[TensorFlow深度學習入門]實戰七·簡便方法實現TensorFlow模型引數儲存與載入(ckpt方式) TensorFlow模型訓練的好網路引數如果想重複高效利用,模型引數儲存與載入是必須掌握的模組。本文提供一種簡單容易理解的方式來實現上述功能。參考部落格地址 備註: 本文采用的

[TensorFlow深度學習入門]實戰六·用CNN做Kaggle比賽手寫數字識別準確率99%+

[TensorFlow深度學習入門]實戰六·用CNN做Kaggle比賽手寫數字識別準確率99%+ 參考部落格地址 本部落格採用Lenet5實現,也包含TensorFlow模型引數儲存與載入參考我的博文,實用性比較好。在訓練集準確率99.85%,測試訓練集準確率99%+。 訓練

[TensorFlow深度學習入門]實戰五·用RNN(LSTM)做手寫數字識別準確率98%+

參考部落格地址,修復了一個小Bug,收斂速度和準確率都略微提升。使用此模型在Kaggle比賽準確率98%+ import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" import time import tensorflow as tf im

深度學習Deeplearning4j 入門實戰(5):基於多層感知機的Mnist壓縮以及在Spark實現

在上一篇部落格中,我們用基於RBM的的Deep AutoEncoder對Mnist資料集進行壓縮,應該說取得了不錯的效果。這裡,我們將神經網路這塊替換成傳統的全連線的前饋神經網路對Mnist資料集進行壓縮,看看兩者的效果有什麼異同。整個程式碼依然是利用Deeplearnin