跳轉到主要內容
工程的博客

(不)如何規模深度學習在6簡單的步驟

2019年8月15日, 數據科學和毫升

分享這篇文章

在磚試試這個筆記本

簡介:這個問題

深度學習有時似乎是巫術。其最先進的應用程序令人愉快的有時令人不安的。的工具,實現這些結果,令人驚訝的是,主要是開放源碼的,可以充分發揮他們的創造力在強大的硬件可以按小時租在雲中。

難怪公司急於申請深度學習更多的業務問題更喜歡生產預測,形象管理,聊天機器人,時間序列分析和更多。僅僅因為是現成的工具並不意味著它們易於使用。甚至選擇合適的體係結構中,層和激活更像是一門藝術而不是科學。

這個博客不會研究如何調整精度的深度學習建築。然而,這個過程確實需要培訓大量的模型試驗和錯誤的過程。這將導致一個更直接的問題:擴大性能深度學習培訓。

深度學習培訓工作不像調ETL工作。它需要大量的計算從專門的硬件,和每個人都最終發現深度學習培訓“太慢”。太頻繁,用戶達成解決方案,可能會過度,昂貴的而不是更快,當試圖擴大規模,而忽略一些基本錯誤,影響性能。

這個博客將穿過基本步驟避免在訓練中常見的性能缺陷,然後正確的步驟,以正確的順序,擴大運用更複雜的工具和更多的硬件。希望,你會發現你的建模工作可以立即沿著速度遠遠沒有達到額外的gpu集群。

一個簡單的分類任務

因為這裏的焦點不是在學習問題本身,下麵的例子將開發一個簡單的數據集和問題解決:分類加州理工學院256數據集257年大約30000個圖像到一個類別(是的,257年)。

數據包括JPEG文件。這些需要調整大小以常見的維度,299×299,下麵描述的pre-trained基礎層。圖片然後寫拚花與標簽文件,便於大規模培訓,稍後描述。可以實現這一目標的“二進製”文件數據源在Apache火花。看到完整源代碼的附帶的筆記本,但這些都是亮點:

img_size =299年defscale_image(image_bytes):形象=形象。開放(io.BytesIO (image_bytes)) .convert (“RGB”)的形象。縮略圖((Image.ANTIALIAS img_size img_size))x, y = image.sizewith_bg = Image.new (“RGB”(img_size img_size), (255年,255年,255年))with_bg。粘貼(圖片,盒子= ((img_size - x) / /2(img_size - y) / /2))返回with_bg.tobytes ()
              raw_image_df = spark.read。格式(“binaryFile”)。\選項(“pathGlobFilter”,“* . jpg”).option (“recursiveFileLookup”,“真正的”)。\負載(caltech_256_path) .repartition (64年)image_df = raw_image_df.select (file_to_label_udf (“路徑”).alias (“標簽”),scale_image_udf (“內容”).alias (“圖像”).cache ()(train_image_df test_image_df) = image_df.randomSplit ([0.9,0.1),種子=42)
              train_image_df.write。格式(“δ”)。年代ave(table_path_base +“訓練”)test_image_df.write。格式(“δ”)。年代ave(table_path_base +“測試”)

也可以使用火花的內置的圖像數據源類型閱讀這些。

Keras流行的Tensorflow高級前端,可以描述一個簡單的深度學習模型對圖像進行分類。所以可以PyTorch——下麵相同的觀點也同樣適用,盡管他們的執行會有點不同。沒有必要從頭構建一個圖像分類器。相反,這個例子中重用pretrainedXception模型內置Keras和添加一個致密層分類。(注意,這個例子使用Keras作為附帶Tensorflow 2.5.0, Tensorflow。keras,而不是獨立的keras)。pretrained層本身不會進一步訓練。邁出這一步# 0:使用學習和pretrained轉移模型在處理圖像時!

步驟# 1:使用GPU

幾乎唯一的情況是有意義的培訓深入學習模型在一個CPU當沒有可用的gpu。在使用雲計算時,磚等平台,簡單提供一台機器與GPU的所有驅動程序Beplay体育安卓版本和庫已經準備好了。而GPU顯得昂貴,速度提高通常使他們更劃算(和磚的成本實際上是貼現GPU實例)。這個例子將直接跳轉到訓練該模型在單一T4 NVIDIA Tesla GPU。

第一遍隻會加載一個10%的樣本數據從三角洲熊貓DataFrame重塑圖像數據,在記憶和訓練樣本的90%。,培訓運行60時代小批量的大小。小提示:當使用pretrained網絡,這是至關重要的正常圖像值網絡預計範圍。在這裏,這是[1],Keras提供preprocess_input函數來做到這一點。

(注意:在磚上運行這個示例,選擇8.4毫升運行時或者之後在GPU的支持下,並選擇一個節點的集群類型與一個單一的GPU實例類型。)

(注意:在磚上運行這個示例,選擇8.4毫升運行時或者之後在GPU的支持下,並選擇一個節點的集群類型與一個單一的GPU實例類型。)

df_pd = spark.read。格式(“δ”).load (“…”)采樣(0.1種子=42).toPandas ()X_raw = df_pd [“圖像”). valuesX = np.array ([preprocess_input (np.frombuffer (X_raw[我],dtype = np.uint8) .reshape (img_size img_size,3)))範圍(len(X_raw))))y = df_pd [“標簽”). values- - - - - -1# 1,因為基於標簽的X_train X_test, y_train y_test = \train_test_split (X, y, test_size =0.1random_state =42)
              defbuild_model(輟學=沒有一個):模型=順序()xception = xception (include_top =,input_shape = (img_size img_size,3),池=“平均”)xception.layers:層。可訓練的=model.add (xception)如果輟學:model.add(輟學(輟學))model.add(密度(257年激活=“softmax”))返回模型
              模型= build_model ()模型。編譯(優化器=納丹(lr =0.001),損失=“sparse_categorical_crossentropy”指標= (“準確性”])模型。適合(X_train y_train batch_size =2時代=60verbose =2)模型。評估(X_test y_test)
              時代59/601211年/1211年- 20 s -損失:6.2584 e-08準確性:1.0000時代60/601211年/1211年- 20 s -損失:7.2973 e-08準確性:1.0000(1.3378633260726929,0.7851851582527161]

結果看起來不錯——100%的準確率約20分鍾後!然而,有一個很重要的缺陷。最後評價了10%驗證數據顯示,真正的精度是78.5%。實際上,模式已經overfit。這是不好的,但更糟的是,它意味著訓練花了大部分的時間使它有點糟糕。它應該已經結束當精度驗證數據停止減少。不僅會留下一個更好的模型,它將會完成

第二步:使用早期停止

Keras(和其他這樣的框架PyTorch閃電)內置支持停止進一步訓練似乎讓模型更糟。在Keras,EarlyStopping回調。使用它意味著通過驗證數據的訓練過程評價每一個時代。培訓後將停止幾個時代過去了沒有改善。restore_best_weights = True確保最終模型的權重是最好的時代,而不是最後一個。這應該是你違約。

early_stopping=EarlyStopping(耐心=3、監控=“val_accuracy”,restore_best_weights=真正的,詳細=1)模型。適合(X_train y_train batch_size=2,時代=60,詳細=2,validation_data=(X_test y_test),回調=[early_stopping])模型。評估(X_test y_test)
              時代11/601211年/1211年- - - - - -21年代- - - - - -失:0.0023- - - - - -準確性:0.9992- - - - - -val_loss:1.0048- - - - - -val_accuracy:0.7815恢複模型權重結束最好的時代。時代00011年:早期停止(1.0000447034835815,0.7851851582527161]

現在,訓練停止在11世紀,不是60,僅僅4分鍾。每個時代稍微長了(21歲、18歲)的評估驗證數據。精度在78.5%相似。

早期停止,請注意時代傳遞給合適的數量(隻)作為一個重要限製運行時期的最大數量。它可以被設置為一個較大的值。這是第一對的觀測表明,同一件事:時代不作為一個單元的培訓非常重要。他們隻是一些批次的數據構成整個訓練的輸入。但訓練意味著經過批次的數據反複,直到模型訓練不夠。有多少代表沒有直接重要的時代。一個時代仍然是有用的作為時間點比較火車每的數據量。

第三步:馬克斯批尺寸較大的GPU

在磚,集群指標通過Ganglia-based公開UI。這表明利用GPU在訓練。監控利用率是很重要的調優,它同時也意味著瓶頸。在這裏,很好使用GPU在85%左右:

(不)如何規模深度學習在6簡單步驟(更新)

100%比85%冷卻器。2批大小的小,不夠讓GPU忙在處理。增加批量大小會增加利用率。的目標不僅僅是讓GPU忙,但受益於額外的工作。更大的批量改善多好每一批更新模型(一個點)更準確的梯度。這反過來可以允許訓練使用更高的學習速率,和更快的達到停止改進的模型。

或者,用額外的能力,可以增加網絡體係結構本身的複雜性來利用。這個例子不打算探索優化架構,但會增加一些輟學減少這個網絡overfit的傾向。

模型= build_model(輟學=0.5)模型。編譯(優化器=納丹(lr =0.004),損失=“sparse_categorical_crossentropy”指標= (“準確性”])模型。適合(X_train y_train batch_size =16時代=30.verbose =2,validation_data = (X_test y_test),回調= [early_stopping])
              時代7/30.152年/152年- 18 s -損失:0.0259準確性:0.9963- val_loss:0.9538- val_accuracy:0.7704時代8/30.152年/152年- 18 s -損失:0.0224準確性:0.9946- val_loss:0.9844- val_accuracy:0.7667恢複模型權重最好的時代的結束。00008年時代:早期停止(0.977917492389679,0.7814815044403076]

16大的批量大小,而不是2,和學習速率為0.004,而不是0.001,GPU仰臥起坐通過時代在18歲以下的年代,而不是21歲。模型達到相同的精度(78.1%)僅在8世紀。總培訓時間僅為2.6分鍾,比20。

太容易提高學習速率過大,在這種情況下,訓練精度將貧窮和貧窮。批處理大小增加8 x時,增加學習速率通常是明智的最多8 x。一些研究表明,當批大小增加N,學習速度可以擴展了sqrt (N)。

注意,有一些固有的隨機性在培訓過程中,作為輸入被Keras打亂。精度波動主要上但有時下隨著時間的推移,加上早期停止,培訓可能終止前或後根據訂單遇到的數據。即便如此,“耐心”的EarlyStopping可以增加額外的培訓成本。

第四步:使用Petastorm訪問大量數據

培訓高於10%使用隻是一個樣本的數據,和上麵的提示幫助降低訓練時間采用一些最佳實踐。當然,下一步是訓練的所有數據。這應該有助於實現更高的精度,但也意味著更多的數據必須被處理。完整的數據集許多g,這仍然可以裝入內存,但為了在這裏,讓我們假裝它不會。需要有效的塊加載到內存數據用不同的方法在訓練。

幸運的是,Petastorm圖書館從超級設計提要Parquet-based數據Tensorflow (Keras或者PyTorch)以這種方式訓練。它可以通過調整預處理和培訓應用代碼創建Tensorflow數據集,而不是熊貓DataFrames進行訓練。數據集在這裏像無限迭代器的數據,這意味著steps_per_epoch現在定義指定有多少批次時代。這表明一個“時代”是有點武斷。

在引擎蓋下,Petastorm火花的集成接受一個火花DataFrame數據(圖像)和序列化它們鑲花文件,然後流到培訓過程的數據集。

spark.conf。(SparkDatasetConverter.PARENT_CACHE_DIR_URL_CONF \“文件:/ / / dbfs / tmp /……”)converter_train = make_spark_converter (spark.read。格式(“δ”).load (“…”))converter_test = make_spark_converter (spark.read。格式(“δ”).load (“…”))img_size =299年deftransform_reader(數據集):deftransform_input(x):img_bytes = tf.reshape (decode_raw (x。形象,tf.uint8), (-1img_size img_size,3))輸入= preprocess_input (tf。鑄造(img_bytes tf.float32))輸出= x。標簽-1返回(輸入、輸出)返回數據集。地圖(transform_input)

拚花臨時文件存儲在一個路徑DBFS文件係統(磚),這隻是一個墊片,使分布式存儲看起來像本地文件,和在某些情況下使更快的訪問。這是一個好主意來緩存/ dbfs路徑上;這是檢查點文件(在本例中沒有顯示)。

上麵的方法重新實現的一些預處理代碼Tensorflow的早些時候轉換api。

batch_size =16converter_train.make_tf_dataset (batch_size = batch_size)作為train_dataset, \converter_test.make_tf_dataset (batch_size = batch_size)作為test_dataset:
              train_dataset = transform_reader (train_dataset)test_dataset = transform_reader (test_dataset)模型= build_model(輟學=0.5)model.compile(優化器=納丹(lr =0.004),損失=“sparse_categorical_crossentropy”指標= (“準確性”])early_stopping = EarlyStopping(耐心=3、監控=“val_accuracy”,restore_best_weights = True,冗長的=1)模型。適合(train_dataset時代=30.steps_per_epoch = (train_size/ / batch_size),validation_data = test_dataset validation_steps = (test_size/ / batch_size),verbose =2回調函數= [early_stopping])

現在運行:

1722/1722 - 208 s -損失:0.3708 -準確性:0.9172 - val_loss: 1.2649 - val_accuracy: 0.8362時代10/301722/1722 - 212 s -損失:0.3294 -準確性:0.9268 - val_loss: 1.3533 - val_accuracy: 0.8316時代11/301722/1722 - 210 s -損失:0.3394 -準確性:0.9268 - val_loss: 1.3192 - val_accuracy: 0.8359時代12/301722/1722 - 207 s -損失:0.3175 -準確性:0.9317 - val_loss: 1.5006 - val_accuracy: 0.8359

紀元時報/ 11 x長(208 vs 18年代),但現在回想一下,一個時代是一個完整的通過訓練數據時,沒有10%的樣本。額外的開銷來自於I / O讀取數據的雲存儲。利用GPU圖形體現在“的”利用GPU:

(不)如何規模深度學習在6簡單步驟(更新)

上行嗎?精度更好的為83.6%。成本是更長的訓練時間:42分鍾而不是4。對於許多應用程序,這可能是值得的準確性增加7%。

第五步:使用多個gpu

仍然想去更快,有預算嗎?在某種程度上,擴大意味著多個gpu。實例,例如,雲中的四個T4 gpu是現成的。Tensorflow提供了一個簡單的工具稱為MirroredStrategy可以跨多個gpu並行化培訓。(PyTorch的模擬DataParallel)。它隻是一個兩行代碼更改:

策略= MirroredStrategy ()strategy.scope ():模型= build_model(輟學=0.5)

(注意:運行這個示例中,選擇一個單節點集群類型4 gpu實例。)

修改很容易,但要開門見山,沒有重複的訓練輸出:精度相似,per-epoch時間變成了68,而不是208年代。那不是快4倍,甚至快3倍。每個4 gpu隻是每一批的處理1/4th 16輸入,所以每個有效處理每批僅為4。如上所述,可以增加4倍賠償的批量大小,到64年,進一步提高學習速率為0.008。完整的代碼清單(參見附帶的筆記本。)

它表明,訓練速度更快,在61年代的時代。加速效果更好,但仍然沒有4 x。準確性是穩定在84.4%左右(更好),所以這仍然進展更快的訓練。Tensorflow實現很簡單,但不是最優的。GPU利用率仍然的,因為GPU空閑時結合局部梯度簡單但緩慢的方式。

Horovod是另一個項目從規模超級幫助深度學習培訓不僅跨多個gpu在一台機器上,但gpu在許多機器,並以極大的效率。雖然常與培訓跨多台機器,那不是真正的下一步擴大。它可以幫助當前multi-GPU設置。一切平等,它會更高效的利用4 gpu連接到同一個VM比在網絡上傳播。

它需要一個不同的修改代碼,使用HorovodRunner實用程序從磚集成Horovod火花:

batch_size=16num_gpus=4
              def train_hvd ():進口tensorflow作為特遣部隊hvd.init ()gpu=tf.config.experimental.list_physical_devices (“圖形”)gpugpu:tf.config.experimental.set_memory_growth (gpu,真正的)如果gpu:tf.config.experimental.set_visible_devices (gpu [hvd.local_rank ()),“圖形”)converter_train.make_tf_dataset (batch_size=batch_size, cur_shard=hvd。排名(),shard_count=hvd.size ())作為train_dataset, \converter_test.make_tf_dataset (batch_size=batch_size, cur_shard=hvd。排名(),shard_count=hvd.size ())作為test_dataset:train_dataset=transform_reader (train_dataset)test_dataset=transform_reader (test_dataset)模型=build_model(輟學=0.5)優化器=hvd.DistributedOptimizer(納丹(lr=0.008))model.compile(優化器=優化器,\損失=“sparse_categorical_crossentropy”、指標=(“準確性”])回調=(hvd.callbacks.BroadcastGlobalVariablesCallback (0),hvd.callbacks.MetricAverageCallback (),EarlyStopping(耐心=3、監控=“val_accuracy”,restore_best_weights=真正的,詳細=(1如果hvd。排名()==0其他的0))]
              模型。fit (train_dataset時代=30.,steps_per_epoch=(train_size//(batch_size*num_gpus)),validation_data=test_dataset,validation_steps=(test_size//(batch_size*num_gpus)),詳細的=(2如果hvd。排名()==0其他的0),回調=回調函數)人力資源=HorovodRunner (np=- - - - - -num_gpus)hr.run (train_hvd)

幾注:

  • 注意make_tf_dataset cur_shard和shard_count參數需要理解哪些子集的數據加載(例如,當前的過程是2的4)
  • 使用hvd.callbacks。MetricAverageCallback平均正確驗證指標
  • 設置HorovodRunner的np - =參數使用gpu的數量,當當地
  • 每GPU批大小是現在,而不是整體。注意不同的計算在steps_per_epoch

的輸出訓練,嘈雜的,所以不會被複製。時代時代已經來臨下降到52年代,從208年代,這是令人滿意的接近最大可能4 x加速!精度仍然是大約84.4%。總運行時現在隻有7.3分鍾,而不是42。

第六步:使用Horovod跨多個機器

有時,8或16 gpu是不夠的,這是最你今天可以在一台機器上。或者,有時它可以跨許多較小的機器便宜提供gpu利用雲中的不同價格每台機器的類型。

同一Horovod上麵的例子可以在集群上運行的八個1-GPU機器而不是一個4-GPU機器隻有一行改變。事實證明,在一個雲在撰寫本文時,這些8 gpu成本隻有6%每小時比一個4-GPU機器。雖然分布在機器介紹更多的開銷,額外的吞吐量可能會使這個選項更便宜,越來越快。

HorovodRunner管理的分布式工作Horovod集群使用火花的火花障模式支持。

num_gpus = 8hr = HorovodRunner (np = num_gpus)

(注:運行這個例子,提供集群與8個工人,每個1 GPU)。

唯一必要的改變是指定8,而不是8,選擇8 gpu集群而不是司機。然而與8 gpu,有效批大小增加了一倍,所以它可能是有用的提高學習速率0.012在上麵的代碼片段。

GPU利用率而完整的跨8台機器的GPU。空閑一個是司機,不參加培訓:

(不)如何規模深度學習在6簡單步驟(更新)

精度提高一點,到85.6%。總運行時間約為5.7分鍾,而不是7.3,這並不是近2 x加速。這在一定程度上反映出跨機器協調gpu的開銷。

中等大小的問題,它可能不會有可能有效地利用更多的GPU資源。讓他們忙將意味著更大的學習速度和學習速率可能已經盡可能高。這個網絡,幾個T4 gpu可以正確的最大數量的資源部署。當然,還有更大的網絡和數據集!

結論

深度學習強大的魔法,但我們總是想要更快。但它鱗片以不同的方式。有新的最佳實踐和陷阱,知道什麼時候出發訓練模型。其中一些幫助小圖像分類問題達到相同的精度,同時減少78.5%運行時/ 7 x。第一步擴展沒有更多的資源,但尋找簡單的優化:

  1. 盡可能使用pre-trained基礎層
  2. 使用GPU,幾乎總是
  3. 使用早期停止
  4. 馬克斯GPU利用率更大的批量大小,和學習

擴展訓練在整個大數據集在雲中需要一些新的工具,但不一定更gpu。小心使用Petastorm, 10 x數據幫助達到83.6%的準確率約10倍的時間在相同的硬件上。

  1. 使用Petastorm培訓期間有效地處理大型數據集

下一步的擴大意味著利用多個gpu Horovod之類的工具,但並不一定意味著集群的機器,不像在集群的ETL作業的機器是一種常態。一個4 GPU實例允許訓練完成快4倍,達到84.4%的準確率。隻有最大的問題是多個GPU實例有必要,但Horovod可以進一步幫助規模沒有多少開銷,進一步提高精度。

  1. 規模與Horovod多個gpu在一台機器上
  2. 規模無法與Horovod gpu集群分布在機器

訓練快樂!

免費試著磚
看到所有數據科學和毫升的帖子
Baidu
map