tensorflow學(xué)習(xí)筆記(三十一)構(gòu)建多gpu代碼_第1頁(yè)
tensorflow學(xué)習(xí)筆記(三十一)構(gòu)建多gpu代碼_第2頁(yè)
tensorflow學(xué)習(xí)筆記(三十一)構(gòu)建多gpu代碼_第3頁(yè)
tensorflow學(xué)習(xí)筆記(三十一)構(gòu)建多gpu代碼_第4頁(yè)
tensorflow學(xué)習(xí)筆記(三十一)構(gòu)建多gpu代碼_第5頁(yè)
已閱讀5頁(yè),還剩10頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、tensorflow 學(xué)習(xí)筆記(三十一) :構(gòu)建多 GPU 代碼 構(gòu)建多 GPU 代碼結(jié)構(gòu)先構(gòu)建單 GPU 代碼寫個(gè)函數(shù) multi_gpu_model(num_gpus) 來生成多 GPU 代碼,并將對(duì)象 保存在 collection 中 feed datarun 如何構(gòu)建單 GPU 代碼見之 前博客構(gòu)建 TF 代碼 不要在單 GPU 代碼中創(chuàng)建 optimizer op, 因?yàn)槭?multi gpu ,所以參數(shù)更新的操作是所有的 GPU 計(jì)算 完梯度之后,才進(jìn)行更新的。如何實(shí)現(xiàn) multi_gpu_model 函 數(shù) def multi_gpu_model(num_gpus=1): gra

2、ds = for i in range(num_gpus): with tf.device(/gpu:%d%i): with _scope(tower_%d%i): model = Model(is_training, config, scope) # 放到 collection 中,方便 feed 的時(shí)候取 tf.add_to_collection(train_model, model) grads.append(model.grad) #grad是通過 tf.gradients(loss, vars) 求得 # 以下這些 add_to_collection 可以直接在模型內(nèi)部

3、 完成。 # 將 loss 放到 collection 中, 方便以后操作 tf.add_to_collection(loss,model.loss) # 將 predict 放到 collection 中,方便操作 tf.add_to_collection(predict, model.predict) # 將 summary.merge op 放到 collection 中,方便 操作 tf.add_to_collection(merge_summary, model.merge_summary) # . with tf.device(cpu:0): averaged_gradients

4、= average_gradients(grads)# average_gradients 后面說明 opt = tf.train.GradientDescentOptimizer(learning_rate) train_op=opt.apply_gradients(zip(average_gradients,tf.trai nable_variables() return train_op1234567891011121314151617181920212223123 4567891011121314151617181920212223如何 feed data def generate_f

5、eed_dic(model, feed_dict, batch_generator): x, y = batch_generator.next_batch() feed_dictmodel.x = x feed_dictmodel.y = y 123456123456 如何實(shí)現(xiàn) run_epoch# 這里的 scope 是用來 區(qū)別 train 還是 test def run_epoch(session, data_set, scope, train_op=None, is_training=True): batch_generator = BatchGenerator(data_set, b

6、atch_size) if is_training and train_op is not None: models = tf.get_collection(train_model) # 生成 feed_dict feed_dic = for model in models: generate_feed_dic(model, feed_dic, batch_generator) #生成 fetch_dict losses = tf.get_collection(loss, scope)#保證了在 test 的時(shí)候,不會(huì) fetch train 的 loss 123456789101112131

7、4151612345678910111213141516 main 函數(shù) main 函數(shù)干了以下幾件事: 1. 數(shù)據(jù)處理 2. 建 立多 GPU 訓(xùn)練模型 3. 建立單 /多 GPU 測(cè)試模型 4. 創(chuàng)建 Saver 對(duì)象和 FileWriter 對(duì)象 5. 創(chuàng)建 session 6. run_epochdata_process() with _scope(train) as train_scope: train_op = multi_gpu_model(.) with _scope(test) as test_scope: model = Model(.) sav

8、er = tf.train.Saver() # 建圖完畢,開始執(zhí)行運(yùn)算 with tf.Session() as sess: writer = tf.summary.FileWriter(.) run_epoch(.,train_scope) run_epoch(.,test_scope)12345678910111212345678910 1112 如何編寫 average_gradients 函數(shù) def average_gradients(grads):#grads:grad0, grad1,., grad0,grad1,. averaged_grads = for grads_per_

9、var in zip(*grads): grads = for grad in grads_per_var: expanded_grad = tf.expanded_dim(grad,0) grads.append(expanded_grad) grads = tf.concat_v2(grads, 0) grads = tf.reduce_mean(grads, 0) averaged_grads.append(grads) return averaged_grads1234567891011121234567891011 有一個(gè)版本,但是不 work ,不知為啥 def average_g

10、radients(grads):#grads:grad0, grad1,., grad0,grad1,. averaged_grads = for grads_per_var in zip(*grads): grads = tf.reduce_mean(grads_per_var, 0) averaged_grads.append(grads) return averaged_grads# -*- coding:utf-8 -*- import os.path import re import time import numpy as np import tensorflow as tf im

11、port cifar10batch_size=128 #train_dir=/tmp/cifar10_train# 最大步數(shù) max_steps=1000000#GPU 的數(shù)量 num_gpus=1 #log_device_placement=False# 計(jì)算損失的函數(shù) def tower_loss(scope):# 使用 cifar10.distorted_inputs() 產(chǎn) 生數(shù)據(jù)增強(qiáng)后的 images 和 labels. images, labels = cifar10.distorted_inputs()# 調(diào)用 cifar10.inference 生成卷積網(wǎng)絡(luò) #為每個(gè) GPU

12、生成單獨(dú)的網(wǎng)絡(luò), 這些網(wǎng)絡(luò)的結(jié)構(gòu)完全一樣, 并且共享模型參數(shù)。 logits = cifar10.inference(images)#調(diào)用 cifar.loss 計(jì)算 損失函數(shù)(這里不直接返回 loss, 而是存儲(chǔ)到 collection 中) _ = cifar10.loss(logits, labels)#使用 tf.get_collection(losses, scope) 獲取當(dāng)前這個(gè) GPU 上的 loss #通過 scope 限定了范圍 losses = tf.get_collection(losses, scope) # 再使用 tf.add_n 將所有損失疊加到一起,得到 to

13、tal_loss, total_loss = tf.add_n(losses, name=total_loss)#返回 total_loss 作為函數(shù)結(jié)果 return total_loss# 它負(fù)責(zé)將不同 GPU 計(jì)算出的梯度進(jìn)行 合成 #合成的輸入?yún)?shù) tower_grads 是梯度的雙層列表, # 外層列表是不同 GPU 計(jì)算得到的梯度,內(nèi)存列表是某個(gè) GPU 內(nèi)計(jì)算的不同 Variable 對(duì)應(yīng)的梯度 #最內(nèi)層元素為( grads,variable ) ,即 tower_grads 的基本原 始為二元組(梯度,變量) , #具體形式為: (grad0_gpu0,var0_gpu0),(

14、grad1_gpu0,var1_gpu0),(grad 0_gpu1,var0_gpu1),(grad1_gpu1,var1_gpu1), # #然后用循環(huán)便利這個(gè)雙層列表 def average_gradients(tower_grads): average_grads = # 首先創(chuàng)建平均梯度的列表 average_grads, 它負(fù)責(zé)將梯度 在不同 GPU 間進(jìn)行平均 #zip(*tower_grads) 將這個(gè)雙層列 表轉(zhuǎn)置 ,變成 #(grad0_gpu0,var0_gpu0),(grad0_gpu1,var0_gpu1),(gra d1_gpu0,var1_gpu0),(grad1

15、_gpu1,var1_gpu1), #然后使用循環(huán)遍歷其元素 for grad_and_vars in zip(*tower_grads): # Note that each grad_and_vars looks like the following: # (grad0_gpu0, var0_gpu0), . , (grad0_gpuN, var0_gpuN) grads = for g, _ in grad_and_vars: #每個(gè)循環(huán)獲取的元素 grad_and_vars, 是同一個(gè) Variable 的梯度在不同 GPU 計(jì)算的副本,需要計(jì)算其梯度 的均值 #如果這個(gè)梯度是 N 維的

16、向量,需要在每個(gè)維度上都 進(jìn)行平均。 # Add 0 dimension to the gradients to represent the tower. #先使用 tf.expand_dims 給這些梯度添加一個(gè)冗余的 維度 0, 然后把這些梯度都放到列表 grad 中。 expanded_g = tf.expand_dims(g, 0) # Append on a tower dimension which we will average over below. #然后把這些梯度都放到列表 grad 中。 grads.append(expanded_g) # Average over th

17、e tower dimension. #接著使用 tf.concat 將他們?cè)诰S度 0 合并 grad = tf.concat(grads, 0) #最后使用 tf.reduce_mean 針對(duì)維度 0 上求平均,即將 其他維度全部平均。 grad = tf.reduce_mean(grad, 0)# 最后將平均后的 梯度根 Variable 組合得到原有的二元組 (梯度,變量)格式, 并添加到列表 average_grads v = grad_and_vars01 grad_and_var = (grad, v) average_grads.append(grad_and_var) #當(dāng)所有

18、梯度都求完均值后,返回average_grads return average_gradsdef train():# 先設(shè)置默認(rèn)的計(jì)算設(shè) 備為 CPU ,用來計(jì)算一些簡(jiǎn)單的計(jì)算 with tf.Graph().as_default(), tf.device(/cpu:0): # Create a variable to count the number of train() calls. This equals the # number of batches processed * FLAGS.num_gpus. #然后使用 global_step 記錄全局訓(xùn)練的步數(shù) global_step

19、= tf.get_variable( global_step, , initializer=tf.constant_initializer(0), trainable=False) # Calculate the learning rate schedule. #并計(jì)算一個(gè) epoch 對(duì)應(yīng)的 batch 數(shù), # 以及學(xué)習(xí)速率衰減需要的步數(shù) decay_steps. num_batches_per_epoch = (cifar10.NUM_EXAMPLES_PER_EPOCH_FOR_TRAIN / batch_size) decay_steps = int(num_batches_per_

20、epoch * cifar10.NUM_EPOCHS_PER_DECAY)# Decay the learning rate exponentially based on the number of steps. #使用 tf.train.exponential_decay 創(chuàng)建訓(xùn)練步數(shù)衰減的 學(xué)習(xí)速率, #第一個(gè)參數(shù)為初始學(xué)習(xí)速率 #第二個(gè)參數(shù)為全局訓(xùn)練的步數(shù) #第三個(gè)參數(shù)為每次衰減需要的步數(shù), #第四個(gè)參數(shù):為衰減率 #staircase 設(shè)置為 true ,代表的是階梯是的衰減,lr tf.train.exponential_decay(cifar10.INITIAL_LEARNING_

21、RA TE, global_step, decay_steps, cifar10.LEARNING_RATE_DECAY_FACTOR, staircase=True) # Create an optimizer that performs gradient descent. # 然后設(shè)置優(yōu)化算法為 GradientDescent, 并傳入隨步 數(shù)衰減的學(xué)習(xí)速率 opt = tf.train.GradientDescentOptimizer(lr) # Calculate the gradients for each model tower. #定義存儲(chǔ)個(gè) GPU 計(jì)算結(jié)果的列表 tower_

22、grads tower_grads = #創(chuàng)建一個(gè)循環(huán) ,循環(huán)次數(shù)為 GPU 的數(shù)量 for i in range(num_gpus): #在每一個(gè)循環(huán)內(nèi),使用 tf.device 限定使用第幾個(gè) GPU ,如 gpu0,gpu1, with tf.device(/gpu:%d % i): #然后使用 _scope 將命名空間定義為 tower0,tower1 的形式 with _scope(%s_%d % (cifar10.TOWER_NAME, i) as scope: #對(duì)每一個(gè) GPU ,使用前面定義好的函數(shù) tower_loss 獲取其損失, loss =

23、 tower_loss(scope)# Reuse variables for the next tower. #重用參數(shù) ,讓所有 GPU 共用一個(gè)模型以及完全 相同的參數(shù)。 tf.get_variable_scope().reuse_variables() # Calculate the gradients for the batch of data on this CIFAR tower. #在使用 pute_gradients 計(jì)算單個(gè) GPU 的梯度 grads = pute_gradients(loss) # Keep track of the gradients across a

24、ll towers. #并將求得的梯度添加到梯度列表。 tower_grads.append(grads) # 使用前面寫好 的函數(shù), average_gradients 計(jì)算平均梯度 grads = average_gradients(tower_grads)# 并用 opt.apply_gradients 更新模型參數(shù) apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) #這樣就完成了多 GPU 的同步訓(xùn)練核參數(shù)更新 # Create a saver. #創(chuàng)建模型的保存器 saver. saver

25、= tf.train.Saver(tf.all_variables() # Build an initialization operation to run below. init = tf.global_variables_initializer()# 將 Session 的 allow_soft_placement=True (有些操作在 CPU 上操作,不 使用 allow_soft_placement ,會(huì)報(bào)錯(cuò)) sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=Tr ue) #初始化全部參數(shù) sess.run(init)# Start the queue runners. 準(zhǔn)備號(hào)大 量的數(shù)據(jù)增強(qiáng)后的訓(xùn)練樣本,防止后媽的訓(xùn)練被阻塞在生成 樣本上。 #tf.train.start_queue_runners tf.train.start_queue_runners(sess=sess)# 進(jìn)行訓(xùn) 練的循環(huán),最大迭代次數(shù) max_steps 。 for step in range(max_steps): start_time = time.time() #在每一步中執(zhí)行一次更新梯度

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論