python - TensorFlow 1 की तुलना में TensorFlow 2 बहुत धीमा क्यों है?




keras performance-testing (2)

यह कई उपयोगकर्ताओं द्वारा पाइटोरच पर स्विच करने के कारण के रूप में उद्धृत किया गया है, लेकिन मुझे अभी तक उत्सुक निष्पादन के लिए सबसे महत्वपूर्ण व्यावहारिक गुणवत्ता, गति का त्याग करने का औचित्य / स्पष्टीकरण मिल गया है।

नीचे कोड बेंचमार्किंग प्रदर्शन, TF1 बनाम TF2 - TF1 47% से 276% तेजी से कहीं भी चल रहा है।

मेरा सवाल है: यह ग्राफ या हार्डवेयर स्तर पर ऐसा क्या है, जो इतनी महत्वपूर्ण मंदी देता है?

एक विस्तृत जवाब की तलाश में - मैं पहले से ही व्यापक अवधारणाओं से परिचित हूं। प्रासंगिक गिट

चश्मा : CUDA 10.0.130, cuDNN 7.4.2, पायथन 3.7.4, विंडोज 10, GTX 1070

बेंचमार्क परिणाम :

अद्यतन : नीचे दिए गए कोड के अनुसार ईगर निष्पादन को अक्षम करने से मदद नहीं मिलती है। व्यवहार, हालांकि, असंगत है: कभी-कभी ग्राफ मोड में चलने से काफी मदद मिलती है, अन्य समय यह ईगर के सापेक्ष धीमी गति से चलता है।

जैसा कि टीएफ देव कहीं भी दिखाई नहीं देते हैं, मैं इस मामले की खुद जांच करूंगा - लिंक किए गए गितुब मुद्दे में प्रगति का पालन कर सकता हूं।

अद्यतन 2 : स्पष्टीकरण के साथ साझा करने के लिए प्रयोगात्मक परिणामों के टन; आज किया जाना चाहिए।

बेंचमार्क कोड :

# use tensorflow.keras... to benchmark tf.keras; used GPU for all above benchmarks
from keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from keras.layers import Flatten, Dropout
from keras.models import Model
from keras.optimizers import Adam
import keras.backend as K
import numpy as np
from time import time

batch_shape = (32, 400, 16)
X, y = make_data(batch_shape)

model_small = make_small_model(batch_shape)
model_small.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_small.train_on_batch, 200, X, y)

K.clear_session()  # in my testing, kernel was restarted instead

model_medium = make_medium_model(batch_shape)
model_medium.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_medium.train_on_batch, 10, X, y)

उपयोग किए गए कार्य :

def timeit(func, iterations, *args):
    t0 = time()
    for _ in range(iterations):
        func(*args)
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_small_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 400, strides=4, padding='same')(ipt)
    x     = Flatten()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_medium_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
    x     = LSTM(512, activation='relu', return_sequences=True)(x)
    x     = Conv1D(128, 400, strides=4, padding='same')(x)
    x     = Flatten()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), np.random.randint(0, 2, (batch_shape[0], 1))

VERDICT : यह नहीं है , यदि आप जानते हैं कि आप क्या कर रहे हैं। लेकिन अगर आप नहीं करते हैं , तो यह आपको बहुत खर्च कर सकता है, औसतन कुछ जीपीयू अपग्रेड और कई जीपीयू सबसे खराब स्थिति में।

यह उत्तर : इस मुद्दे का एक उच्च-स्तरीय विवरण, साथ ही आपकी आवश्यकताओं के लिए विशिष्ट प्रशिक्षण कॉन्फ़िगरेशन पर निर्णय लेने के लिए दिशानिर्देश प्रदान करना है। एक विस्तृत, निम्न-स्तरीय विवरण के लिए, जिसमें सभी बेंचमार्किंग परिणाम + कोड का उपयोग किया जाता है, मेरा अन्य उत्तर देखें।

यदि मैं किसी भी संदर्भ को बुकमार्क / "स्टार" कर सकता हूं, तो मैं अपने उत्तर (अपडेट) w / अधिक जानकारी को अपडेट करता रहूंगा।

ISSUE सारांश : जैसा confirmed TensorFlow डेवलपर, Q. स्कॉट झू द्वारा confirmed गई है, TF2 ने Eager एक्जीक्यूशन और टाइट इंटीग्रेशन w / Keras पर ध्यान केंद्रित किया है, जिसमें TF सोर्स में व्यापक बदलाव शामिल हैं - ग्राफ-स्तर पर। लाभ: प्रसंस्करण, वितरण, डिबग, और परिनियोजन क्षमताओं का बहुत विस्तार किया गया। हालांकि, इनमें से कुछ की लागत गति है।

हालांकि, मामला काफी जटिल है। यह सिर्फ TF1 बनाम TF2 नहीं है - ट्रेन की गति में महत्वपूर्ण अंतर उत्पन्न करने वाले कारकों में शामिल हैं:

  1. TF2 बनाम TF1
  2. उत्सुक बनाम ग्राफ मोड
  3. keras बनाम tf.keras
  4. numpy बनाम tf.data.Dataset बनाम ...
  5. train_on_batch() बनाम fit()
  6. GPU बनाम CPU

दुर्भाग्य से, उपरोक्त में से कोई भी दूसरे से स्वतंत्र नहीं है, और प्रत्येक दूसरे के सापेक्ष कम से कम दोहरी निष्पादन समय कर सकता है। सौभाग्य से, आप यह निर्धारित कर सकते हैं कि मैं व्यवस्थित रूप से क्या काम करूंगा, और कुछ शॉर्टकट के साथ - जैसा कि मैं दिखा रहा हूं।

मुझे क्या करना चाहिए? वर्तमान में, एकमात्र तरीका है - आपके विशिष्ट मॉडल, डेटा और हार्डवेयर के लिए प्रयोग। कोई एकल कॉन्फ़िगरेशन हमेशा सबसे अच्छा काम नहीं करेगा - लेकिन आपकी खोज को सरल बनाने के लिए क्या करें और क्या न करें:

>> DO:

  • train_on_batch() + numpy + tf.keras + TF1 + Eager / Graph
  • train_on_batch() + numpy + tf.keras + TF2 + ग्राफ़
  • fit() + numpy + tf.keras + TF1 / TF2 + ग्राफ़ + बड़े मॉडल और डेटा

>> नहीं:

  • fit() + छोटे और मध्यम मॉडल और डेटा के लिए + numpy + keras
  • fit() + numpy + tf.keras + TF1 / TF2 + Eager
  • train_on_batch() + numpy + keras + TF1 + Eager

  • [प्रमुख] tf.python.keras ; यह 10-100x धीमी गति से चल सकता है, और w / काफी कीड़े; और जानकारी

    • इसमें layers , models , optimizers , और संबंधित "आउट-ऑफ-बॉक्स" उपयोग आयात शामिल हैं; ऑप्स, यूटिल्स, और संबंधित 'निजी' आयात ठीक हैं - लेकिन यह सुनिश्चित करने के लिए, tf.keras जांच करें, और क्या वे tf.keras में उपयोग किए tf.keras

उदाहरण बेंचमार्किंग सेटअप के लिए मेरे अन्य उत्तर के नीचे कोड का संदर्भ लें। उपरोक्त सूची मुख्य रूप से अन्य जवाब में "बेंचमार्क" तालिकाओं पर आधारित है।

उपरोक्त DO & DON'T की सीमाएँ :

  • इस सवाल का शीर्षक "टीएफ 1 की तुलना में टीएफ 2 बहुत धीमा क्यों है?", और जब इसके शरीर को स्पष्ट रूप से प्रशिक्षण की चिंता होती है, तो मामला इसके लिए सीमित नहीं है; अनुमान , भी, एक ही TF संस्करण, आयात, डेटा प्रारूप, आदि के भीतर भी प्रमुख गति अंतर के अधीन है - इस उत्तर को देखें।
  • RNN के डेटा ग्रिड को अन्य उत्तर में उल्लेखनीय रूप से बदलने की संभावना है, क्योंकि वे TF2 में सुधार किए गए हैं
  • मॉडल में मुख्य रूप से Conv1D और Conv1D उपयोग किया जाता है - कोई RNN, स्पार्स डेटा / लक्ष्य, 4 / 5D इनपुट, और अन्य स्रोत
  • इनपुट डेटा को सीमित करने के लिए numpy और tf.data.Dataset , जबकि कई अन्य प्रारूप मौजूद हैं; अन्य उत्तर देखें
  • GPU का उपयोग किया गया था; सीपीयू पर परिणाम अलग-अलग होंगे । वास्तव में, जब मैंने सवाल पूछा, तो मेरा CUDA ठीक से कॉन्फ़िगर नहीं किया गया था, और कुछ परिणाम सीपीयू-आधारित थे।

उत्सुक निष्पादन के लिए TF2 ने सबसे व्यावहारिक गुणवत्ता, गति का त्याग क्यों किया? यह स्पष्ट रूप से नहीं है - ग्राफ अभी भी उपलब्ध है। लेकिन अगर सवाल "आखिर क्यों उत्सुक हो":

  • सुपीरियर डिबगिंग : आप संभवतः "मैं कैसे मध्यवर्ती परत आउटपुट प्राप्त करूं" या "मैं वेट का निरीक्षण कैसे करूं" पूछने वाले प्रश्नों के बहुरूपियों में आ गया हूं; उत्सुकता के साथ, यह (लगभग) उतना ही सरल है।। ग्राफ, इसके विपरीत, विशेष बैकेंड कार्यों के साथ परिचितता की आवश्यकता होती है - डिबगिंग और आत्मनिरीक्षण की पूरी प्रक्रिया को जटिल करना।
  • तेजी से प्रोटोटाइप : ऊपर के समान विचारों के अनुसार; तेजी से समझ = वास्तविक डीएल के लिए अधिक समय बचा है।

कैसे सक्षम / अक्षम करने के लिए?

tf.enable_eager_execution()  # TF1; must be done before any model/tensor creation
tf.compat.v1.disable_eager_execution() # TF2; above holds

अतिरिक्त जानकारी :

  • TF2 में _on_batch() विधियों के साथ सावधान; टीएफ देव के अनुसार, वे अभी भी धीमी गति से कार्यान्वयन का उपयोग करते हैं, लेकिन जानबूझकर नहीं - यानी यह तय किया जाना है। विवरण के लिए अन्य उत्तर देखें।

दसियों डेविल्स की आवश्यकताएं :

  1. कृपया train_on_batch() , और कॉलिंग fit() के प्रदर्शन पहलू को ठीक करें; कस्टम ट्रेन लूप कई के लिए महत्वपूर्ण हैं, खासकर मेरे लिए।
  2. उपयोगकर्ताओं के ज्ञान के लिए इन प्रदर्शन अंतरों के प्रलेखन / डॉकस्ट्रिंग का उल्लेख करें।
  3. Pytorch को hopping से peeps रखने के लिए सामान्य निष्पादन की गति में सुधार।

ACKNOWLEDGMENTS : धन्यवाद

  • Q. स्कॉट झू, टेन्सरफ्लो डेवलपर, ने इस मामले पर अपने confirmed लिए।
  • पी। एंड्री उपयोगी परीक्षण और चर्चा साझा करने के लिए।

इस उत्तर : TF2 बनाम TF1 ट्रेन लूप, इनपुट डेटा प्रोसेसर, और Eager बनाम ग्राफ मोड निष्पादन सहित - इस मुद्दे का एक विस्तृत, ग्राफ / हार्डवेयर-स्तरीय विवरण प्रदान करना है। एक समस्या सारांश और संकल्प दिशानिर्देशों के लिए, मेरे अन्य उत्तर देखें।

निष्पादन VERDICT : कभी-कभी एक तेजी से होता है, कभी-कभी दूसरा, कॉन्फ़िगरेशन पर निर्भर करता है। जहाँ तक TF2 बनाम TF1 जाता है, वे औसतन बराबर हैं, लेकिन महत्वपूर्ण कॉन्फ़िगरेशन-आधारित अंतर मौजूद हैं, और TF1 TF2 को अक्सर इसके विपरीत से अधिक ट्रम्प करता है। नीचे "बेंचमार्किंग" देखें।

EAGER वी.एस. GRAPH : कुछ के लिए इस पूरे उत्तर का मांस: TF2 की उत्सुकता मेरे परीक्षण के अनुसार, TF1 की तुलना में धीमी है। विवरण नीचे दिया गया है।

दोनों के बीच मूलभूत अंतर है: ग्राफ एक कम्प्यूटेशनल नेटवर्क को लगातार सेट करता है, और निष्पादित करता है जब 'को बताया' - जबकि एगर निर्माण पर सब कुछ निष्पादित करता है। लेकिन कहानी केवल यहाँ से शुरू होती है:

  • उत्सुक ग्राफ से रहित नहीं है , और वास्तव में ज्यादातर ग्राफ हो सकता है, अपेक्षा के विपरीत। यह काफी हद तक है, ग्राफ़ निष्पादित किया गया है - इसमें मॉडल और ऑप्टिमाइज़र वेट शामिल हैं, जिसमें ग्राफ़ का एक बड़ा हिस्सा शामिल है।

  • एगर निष्पादन में खुद के ग्राफ के हिस्से का पुनर्निर्माण करता है ; ग्राफ़ का प्रत्यक्ष परिणाम पूरी तरह से निर्मित नहीं हो रहा है - प्रोफाइलर परिणाम देखें। यह एक कम्प्यूटेशनल उपरि है।

  • उत्सुक धीमी w / Numpy आदानों है ; इस Git टिप्पणी और कोड के अनुसार, Eager में Numpy इनपुट में CPU से GPU तक दसियों को कॉपी करने की ओवरहेड लागत शामिल है। स्रोत कोड के माध्यम से कदम, डेटा हैंडलिंग अंतर स्पष्ट हैं; ईगर सीधे नेम्पी से गुजरता है, जबकि ग्राफ टेंसर्स से गुजरता है जो फिर नेम्पी का मूल्यांकन करता है; सटीक प्रक्रिया की अनिश्चितता, लेकिन बाद में GPU- स्तर के अनुकूलन शामिल होने चाहिए

  • TF2 Eager, TF1 Eager की तुलना में धीमा है - यह अप्रत्याशित है। नीचे दिए गए बेंचमार्किंग परिणाम देखें। मतभेद नगण्य से महत्वपूर्ण तक फैले हैं, लेकिन सुसंगत हैं। यह सुनिश्चित करें कि यह मामला क्यों है - यदि कोई टीएफ देव स्पष्ट करता है, तो उत्तर को अपडेट करेगा।

TF2 बनाम TF1 : एक TF देव के प्रासंगिक अंशों को उद्धृत करते हुए, Q. स्कॉट झू का, confirmed - w / bit of my जोर & rew रिकॉर्डिंग:

उत्सुकता में, रनटाइम को ऑप्स को निष्पादित करने और अजगर कोड की प्रत्येक पंक्ति के लिए संख्यात्मक मान वापस करने की आवश्यकता होती है। एकल चरण निष्पादन की प्रकृति के कारण यह धीमा हो जाता है

TF2 में, Keras प्रशिक्षण, eval और भविष्यवाणी के लिए अपना ग्राफ बनाने के लिए tf.function का उपयोग करता है। हम उन्हें मॉडल के लिए "निष्पादन फ़ंक्शन" कहते हैं। TF1 में, "निष्पादन फ़ंक्शन" एक फ़ंक्ग्राफ़ था, जिसने कुछ सामान्य घटक को TF फ़ंक्शन के रूप में साझा किया था, लेकिन इसका एक अलग कार्यान्वयन है।

प्रक्रिया के दौरान, हमने किसी तरह train_on_batch (), test_on_batch () और predict_on_batch () के लिए गलत कार्यान्वयन छोड़ दिया। वे अभी भी संख्यात्मक रूप से सही हैं , लेकिन x_on_batch के लिए निष्पादन फ़ंक्शन tf.function लिपटे अजगर फ़ंक्शन के बजाय एक शुद्ध पायथन फ़ंक्शन है। यह सुस्ती का कारण होगा

TF2 में, हम सभी इनपुट डेटा को एक tf.data.Dataset में परिवर्तित करते हैं, जिसके द्वारा हम एकल प्रकार के इनपुट को संभालने के लिए अपने निष्पादन फ़ंक्शन को एकजुट कर सकते हैं। डेटासेट रूपांतरण में कुछ ओवरहेड हो सकता है, और मुझे लगता है कि यह एक बार का ओवरहेड है, बजाय एक प्रति बैच लागत के

ऊपर अंतिम पैराग्राफ के अंतिम वाक्य के साथ, और नीचे पैराग्राफ के अंतिम खंड:

उत्सुक मोड में सुस्ती को दूर करने के लिए, हमारे पास @ tf.function है, जो एक अजगर फ़ंक्शन को एक ग्राफ़ में बदल देगा। जब एनपी सरणी की तरह संख्यात्मक मान फ़ीड करते हैं, तो tf.function का शरीर स्थिर ग्राफ़ में परिवर्तित हो जाता है, अनुकूलित किया जा रहा है, और अंतिम मान लौटाता है, जो तेज़ है और TF1 ग्राफ़ मोड के समान प्रदर्शन होना चाहिए।

मैं असहमत हूं - मेरे प्रोफाइलिंग परिणामों के अनुसार, जो एगर के इनपुट डेटा प्रोसेसिंग को ग्राफ के मुकाबले काफी धीमा दिखाते हैं। इसके अलावा, विशेष रूप से tf.data.Dataset बारे में अनिश्चित, लेकिन ईगर बार-बार एक ही डेटा रूपांतरण विधियों - प्रोफाइलर के कई बार कॉल करता है।

अंत में, देव की लिंक्ड कमिट: केरस v2 लूप्स का समर्थन करने के लिए परिवर्तनों की महत्वपूर्ण संख्या

ट्रेन लूप : (1) ईगर बनाम ग्राफ पर निर्भर करता है; (2) इनपुट डेटा प्रारूप, प्रशिक्षण एक अलग ट्रेन लूप के साथ आगे बढ़ेगा - TF2, _select_training_loop() , training.py , one of:

training_v2.Loop()
training_distributed.DistributionMultiWorkerTrainingLoop(
              training_v2.Loop()) # multi-worker mode
# Case 1: distribution strategy
training_distributed.DistributionMultiWorkerTrainingLoop(
            training_distributed.DistributionSingleWorkerTrainingLoop())
# Case 2: generator-like. Input is Python generator, or Sequence object,
# or a non-distributed Dataset or iterator in eager execution.
training_generator.GeneratorOrSequenceTrainingLoop()
training_generator.EagerDatasetOrIteratorTrainingLoop()
# Case 3: Symbolic tensors or Numpy array-like. This includes Datasets and iterators 
# in graph mode (since they generate symbolic tensors).
training_generator.GeneratorLikeTrainingLoop() # Eager
training_arrays.ArrayLikeTrainingLoop() # Graph

प्रत्येक संसाधन संसाधन आवंटन को अलग तरीके से संभालता है, और प्रदर्शन और क्षमता पर परिणाम को सहन करता है।

ट्रेन लूप: fit बनाम train_on_batch , keras बनाम tf.keras : चार में से प्रत्येक अलग ट्रेन लूप का उपयोग करता है, हालांकि शायद हर संभव संयोजन में नहीं। उदाहरण के लिए, keras ' fit , जैसे fit_loop एक रूप का उपयोग करता है, उदाहरण के लिए training_arrays.fit_loop() , और इसका train_on_batch K.function() उपयोग कर सकता है। tf.keras पास पिछले अनुभाग में भाग में वर्णित एक अधिक परिष्कृत पदानुक्रम है।

ट्रेन लूप्स: प्रलेखन - विभिन्न निष्पादन विधियों में से कुछ पर प्रासंगिक स्रोत :

अन्य TensorFlow संचालन के विपरीत, हम अजगर संख्यात्मक इनपुट को दहाई में नहीं बदलते हैं। इसके अलावा, प्रत्येक अलग अजगर संख्यात्मक मूल्य के लिए एक नया ग्राफ उत्पन्न होता है

function इनपुट आकृतियों और डेटाटिप्स के हर अनूठे सेट के लिए एक अलग ग्राफ को इंस्टेंट करता है

एक एकल tf.function ऑब्जेक्ट को हुड के तहत कई कम्प्यूटेशन ग्राफ़ पर मैप करने की आवश्यकता हो सकती है। इसे केवल प्रदर्शन के रूप में देखा जाना चाहिए (अनुरेखण रेखांकन में एक गैर-कम्प्यूटेशनल और मेमोरी लागत है )

इनपुट डेटा प्रोसेसर : ऊपर के समान, रनटाइम कॉन्फ़िगरेशन (निष्पादन मोड, डेटा प्रारूप, वितरण रणनीति) के अनुसार आंतरिक झंडे के आधार पर प्रोसेसर को केस-बाय-केस चुना जाता है। Eager के साथ सबसे सरल मामला, जो सीधे w / Numpy सरणियों का काम करता है। कुछ विशिष्ट उदाहरणों के लिए, इस उत्तर को देखें।

मॉडल आकार, डेटा आकार:

  • निर्णायक है; किसी भी एकल कॉन्फ़िगरेशन ने सभी मॉडल और डेटा आकार के साथ ताज पहनाया।
  • मॉडल आकार के सापेक्ष डेटा आकार महत्वपूर्ण है; छोटे डेटा और मॉडल के लिए, डेटा ट्रांसफर (जैसे CPU से GPU) ओवरहेड हावी हो सकता है। इसी तरह, छोटे ओवरहेड प्रोसेसर प्रति डेटा रूपांतरण समय पर बड़े डेटा पर धीमी गति से चल सकते हैं ("PROFILER" में convert_to_tensor देखें)
  • स्पीड प्रति ट्रेन लूप में भिन्न होती है और इनपुट डेटा प्रोसेसर 'संसाधनों से निपटने के साधन अलग होते हैं।

बेंचमार्क : पीस मांस। - वर्ड डॉक्यूमेंट - एक्सेल स्प्रेडशीट

शब्दावली :

  • %-रहित संख्याएँ सभी सेकंड हैं
  • % के रूप में गणना की गई (1 - longer_time / shorter_time)*100 ; औचित्य: हम इस बात में रुचि रखते हैं कि कौन सा कारक दूसरे की तुलना में तेज़ है; shorter / longer वास्तव में एक गैर-रैखिक संबंध है, प्रत्यक्ष तुलना के लिए उपयोगी नहीं है
  • % संकेत निर्धारण:
    • TF2 बनाम TF1: + यदि TF2 तेज है
    • जीवीई (ग्राफ बनाम ईगर): + अगर ग्राफ तेज है
  • TF2 = TensorFlow 2.0.0 + केरस 2.3.1; टीएफ 1 = टेन्सरफ्लो 1.14.0 + केरस 2.2.5

PROFILER :

PROFILER - स्पष्टीकरण : स्पाइडर 3.3.6 आईडीई प्रोफाइलर।

  • कुछ कार्यों को दूसरों के घोंसले में दोहराया जाता है; इसलिए, "डेटा प्रोसेसिंग" और "प्रशिक्षण" कार्यों के बीच सटीक पृथक्करण को ट्रैक करना मुश्किल है, इसलिए कुछ ओवरलैप होंगे - जैसा कि बहुत अंतिम परिणाम में स्पष्ट किया गया है।

  • % आंकड़े कम्प्यूटेशनल रनटाइम माइनस समय का निर्माण करते हैं

  • सभी (अद्वितीय) रनटाइम को जोड़कर गणना किए गए समय का निर्माण करें जिसे 1 या 2 बार कहा गया था
  • ट्रेन के समय को सभी (अद्वितीय) रनटाइम से जोड़कर गणना की जाती है, जो इसे # पुनरावृत्तियों के # समान रूप से कहते हैं, और उनके कुछ घोंसले के रनटाइम
  • फ़ंक्शंस उनके मूल नामों के अनुसार प्रोफाइल किए जाते हैं, दुर्भाग्यवश (यानी _func = func प्रोफाइल _func = func रूप में), जो बिल्ड समय में मिश्रण करता है - इसलिए इसे बाहर करने की आवश्यकता है

परीक्षण पर्यावरण :

  • नीचे w / न्यूनतम पृष्ठभूमि कार्यों में निष्पादित कोड चल रहा है
  • GPU इस समय में पुनरावृत्तियों से पहले w / कुछ पुनरावृत्तियों को "वार्म अप" किया गया था, जैसा कि इस पोस्ट में बताया गया है
  • CUDA 10.0.130, cuDNN 7.6.0, TensorFlow 1.14.0, और TensorFlow 2.0.0 स्रोत से निर्मित, प्लस एनाकोंडा
  • पायथन 3.7.4, स्पाइडर 3.3.6 आईडीई
  • GTX 1070, विंडोज 10, 24GB DDR4 2.4-MHz RAM, i7-7700HQ 2.8-GHz CPU

विधि :

  • बेंचमार्क 'छोटा', ​​'मध्यम', और 'बड़े' मॉडल और डेटा आकार
  • प्रत्येक मॉडल आकार के लिए मापदंडों के # फिक्स, इनपुट डेटा आकार से स्वतंत्र
  • "बड़े" मॉडल में अधिक पैरामीटर और परतें हैं
  • "बड़े" डेटा में एक लंबा अनुक्रम होता है, लेकिन समान num_channels और num_channels
  • मॉडल केवल Conv1D , Dense 'सीखने योग्य' परतों का उपयोग करते हैं; आरएनएन प्रति टीएफ-संस्करण के प्रतिरूप से बचते हैं। मतभेद
  • मॉडल और ऑप्टिमाइज़र ग्राफ़ बिल्डिंग को छोड़ने के लिए बेंचमार्किंग लूप के बाहर हमेशा एक ट्रेन फिट की जाती है
  • विरल डेटा का उपयोग नहीं (जैसे layers.Embedding() ) या विरल लक्ष्य (जैसे स्पार्स SparseCategoricalCrossEntropy()

सीमाएं : एक "पूर्ण" उत्तर हर संभव ट्रेन लूप और पुनरावृत्त को समझाएगा, लेकिन यह निश्चित रूप से मेरे समय की क्षमता, कोई नहीं, पेचेक या सामान्य आवश्यकता से परे है। परिणाम केवल पद्धति के रूप में अच्छे हैं - एक खुले दिमाग के साथ व्याख्या।

कोड :

import numpy as np
import tensorflow as tf
import random
from termcolor import cprint
from time import time

from tensorflow.keras.layers import Input, Dense, Conv1D
from tensorflow.keras.layers import Dropout, GlobalAveragePooling1D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras.backend as K
#from keras.layers import Input, Dense, Conv1D
#from keras.layers import Dropout, GlobalAveragePooling1D
#from keras.models import Model 
#from keras.optimizers import Adam
#import keras.backend as K

#tf.compat.v1.disable_eager_execution()
#tf.enable_eager_execution()

def reset_seeds(reset_graph_with_backend=None, verbose=1):
    if reset_graph_with_backend is not None:
        K = reset_graph_with_backend
        K.clear_session()
        tf.compat.v1.reset_default_graph()
        if verbose:
            print("KERAS AND TENSORFLOW GRAPHS RESET")

    np.random.seed(1)
    random.seed(2)
    if tf.__version__[0] == '2':
        tf.random.set_seed(3)
    else:
        tf.set_random_seed(3)
    if verbose:
        print("RANDOM SEEDS RESET")

print("TF version: {}".format(tf.__version__))
reset_seeds()

def timeit(func, iterations, *args, _verbose=0, **kwargs):
    t0 = time()
    for _ in range(iterations):
        func(*args, **kwargs)
        print(end='.'*int(_verbose))
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_model_small(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 40, strides=4, padding='same')(ipt)
    x     = GlobalAveragePooling1D()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_medium(batch_shape):
    ipt = Input(batch_shape=batch_shape)
    x = ipt
    for filters in [64, 128, 256, 256, 128, 64]:
        x  = Conv1D(filters, 20, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_large(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(64,  400, strides=4, padding='valid')(ipt)
    x     = Conv1D(128, 200, strides=1, padding='valid')(x)
    for _ in range(40):
        x = Conv1D(256,  12, strides=1, padding='same')(x)
    x     = Conv1D(512,  20, strides=2, padding='valid')(x)
    x     = Conv1D(1028, 10, strides=2, padding='valid')(x)
    x     = Conv1D(256,   1, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)    
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), \
           np.random.randint(0, 2, (batch_shape[0], 1))

def make_data_tf(batch_shape, n_batches, iters):
    data = np.random.randn(n_batches, *batch_shape),
    trgt = np.random.randint(0, 2, (n_batches, batch_shape[0], 1))
    return tf.data.Dataset.from_tensor_slices((data, trgt))#.repeat(iters)

batch_shape_small  = (32, 140,   30)
batch_shape_medium = (32, 1400,  30)
batch_shape_large  = (32, 14000, 30)

batch_shapes = batch_shape_small, batch_shape_medium, batch_shape_large
make_model_fns = make_model_small, make_model_medium, make_model_large
iterations = [200, 100, 50]
shape_names = ["Small data",  "Medium data",  "Large data"]
model_names = ["Small model", "Medium model", "Large model"]

def test_all(fit=False, tf_dataset=False):
    for model_fn, model_name, iters in zip(make_model_fns, model_names, iterations):
        for batch_shape, shape_name in zip(batch_shapes, shape_names):
            if (model_fn is make_model_large) and (batch_shape is batch_shape_small):
                continue
            reset_seeds(reset_graph_with_backend=K)
            if tf_dataset:
                data = make_data_tf(batch_shape, iters, iters)
            else:
                data = make_data(batch_shape)
            model = model_fn(batch_shape)

            if fit:
                if tf_dataset:
                    model.train_on_batch(data.take(1))
                    t0 = time()
                    model.fit(data, steps_per_epoch=iters)
                    print("Time/iter: %.4f sec" % ((time() - t0) / iters))
                else:
                    model.train_on_batch(*data)
                    timeit(model.fit, iters, *data, _verbose=1, verbose=0)
            else:
                model.train_on_batch(*data)
                timeit(model.train_on_batch, iters, *data, _verbose=1)
            cprint(">> {}, {} done <<\n".format(model_name, shape_name), 'blue')
            del model

test_all(fit=True, tf_dataset=False)




tensorflow2.0