केर असंगत भविष्यवाणी समय


17

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

import time
import numpy as np
from sklearn.datasets import make_classification
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten

# Make a dummy classification problem
X, y = make_classification()

# Make a dummy model
model = Sequential()
model.add(Dense(10, activation='relu',name='input',input_shape=(X.shape[1],)))
model.add(Dense(2, activation='softmax',name='predictions'))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

model.fit(X, y, verbose=0, batch_size=20, epochs=100)

for i in range(1000):
    # Pick a random sample
    sample = np.expand_dims(X[np.random.randint(99), :], axis=0)
    # Record the prediction time 10x and then take the average
    start = time.time()
    for j in range(10):
        y_pred = model.predict_classes(sample)
    end = time.time()
    print('%d, %0.7f' % (i, (end-start)/10))

समय नमूने पर निर्भर नहीं करता है (इसे यादृच्छिक रूप से उठाया जा रहा है)। यदि परीक्षण दोहराया जाता है, तो लूप के लिए सूचकांक जहां भविष्यवाणी में अधिक समय लगता है, वही फिर से होने वाला है (लगभग)।

यहाँ छवि विवरण दर्ज करें

मैं उपयोग कर रहा हूँ:

tensorflow 2.0.0
python 3.7.4

मेरे आवेदन के लिए मुझे एक निश्चित समय में निष्पादन की गारंटी देने की आवश्यकता है। हालाँकि उस व्यवहार को देखते हुए यह असंभव है। क्या गलत हो रहा है? क्या यह केरस में एक बग या टेनसफ़्लो बैकएंड में एक बग है?

संपादित करें: predict_on_batchएक ही व्यवहार दिखाता है, हालांकि, अधिक विरल: यहाँ छवि विवरण दर्ज करें

y_pred = model(sample, training=False).numpy() कुछ भारी आउटलेर्स को भी दिखाता है, हालांकि, वे नहीं बढ़ रहे हैं। यहाँ छवि विवरण दर्ज करें

EDIT 2: मैंने नवीनतम टेंसोरफ़्लो 1 संस्करण (1.15) को डाउनग्रेड किया। न केवल समस्या अस्तित्व में नहीं है, बल्कि "सामान्य" भविष्यवाणी समय में भी काफी सुधार हुआ है! मैं दो स्पाइक्स को समस्याग्रस्त नहीं देखता, क्योंकि जब मैंने परीक्षण दोहराया (कम से कम एक ही सूचकांक और रैखिक रूप से नहीं बढ़ रहा था) तो वे दिखाई नहीं दिए और पहले प्लॉट में जितने बड़े हैं उतने बड़े नहीं हैं। यहाँ छवि विवरण दर्ज करें

हम इस प्रकार यह निष्कर्ष निकाल सकते हैं कि यह एक समस्या है जो टेंसरफ़्लो 2.0 में निहित है, जो अन्य स्थितियों में @OverLordGoldDragon उल्लेखों के समान व्यवहार दिखाता है।


यह व्यवहार अनुमानित लगता है .... वृद्धि रैखिक की तरह है। यदि आप अपने समय की गणना में इस व्यवहार को शामिल करते हैं, तो क्या यह नहीं जाएगा? --- मुझे नहीं पता कि वहां क्या हो रहा है .... लेकिन अगर आप predict_on_batchइसके बजाय कोशिश करते हैं तो क्या होगा ?
डेनियल मोलर

एक और प्रयास, क्या y_pred = model(sample).numpy()और किसके साथ होता है y_pred = model(sample, training=False).numpy()?
डेनियल मोलर

मैंने अपने निष्कर्ष जोड़े। संख्यात्मक संस्करण व्यवहार को दिखाने के लिए प्रतीत नहीं होते हैं।
1897 को

लेकिन predict_classesअभी भी सबसे तेज है .... ऐसा लगता है। क्या बस के बारे में predict?
डैनियल मोलर

1
मुझे लगता है कि यह कुछ प्रकार की स्मृति सफाई हो सकती है ....
डैनियल मोलर

जवाबों:


10

TF2 आम तौर पर खराब और बग-जैसे स्मृति प्रबंधन को कई उदाहरणों में प्रदर्शित करता है जो मैंने सामना किया है - यहां और यहां संक्षिप्त विवरण । विशेष रूप से भविष्यवाणी के साथ, सबसे अधिक खिला विधि model(x)सीधे के माध्यम से है - यहां देखें , और इसके जुड़े विचार-विमर्श।

संक्षेप में: model(x)अपने अपने माध्यम से कार्य करता है __call__विधि (जो इसे से विरासत base_layer.Layer), जबकि predict(), predict_classes()आदि के माध्यम से एक समर्पित पाश समारोह को शामिल _select_training_loop(); प्रत्येक अलग-अलग उपयोग-मामलों के लिए उपयुक्त विभिन्न डेटा पूर्व और बाद के प्रसंस्करण विधियों का उपयोग करते हैं, औरmodel(x) 2.1 में विशेष रूप से सबसे छोटे मॉडल / छोटे-बैच (और शायद किसी भी आकार) के प्रदर्शन (और अभी भी सबसे तेजी से 2.0 में) का उत्पादन करने के लिए डिज़ाइन किया गया था।

जुड़े हुए चर्चाओं से एक TensorFlow देव का उद्धरण :

आप मॉडल कॉल का उपयोग करके आउटपुट का अनुमान लगा सकते हैं, मॉडल की भविष्यवाणी का नहीं, अर्थात, कॉल model(x)करने से यह बहुत तेज़ हो जाएगा क्योंकि "डेटासेट में कोई रूपांतरण नहीं" भाग है, और यह भी सीधे कैश्ड कॉलिंग है tf.function

नोट : यह 2.1 में एक समस्या से कम होना चाहिए, और विशेष रूप से 2.2 - लेकिन वैसे भी प्रत्येक विधि का परीक्षण करें। इसके अलावा मुझे एहसास है कि यह सीधे समय पर अपने सवाल का जवाब नहीं देता है; मुझे संदेह है कि यह ईगर कैशिंग तंत्र से संबंधित है, लेकिन निर्धारित करने का सबसे सुरक्षित तरीका है TF Profiler, जो 2.1 में टूट गया है।


अद्यतन : बढ़ती स्पाइक्स के बारे में , संभव जीपीओ थ्रॉटलिंग; आपने ~ 1000 इटर्स किए हैं, इसके बजाय 10,000 की कोशिश करें - अंततः, बढ़ते हुए बंद हो जाना चाहिए। जैसा कि आपने अपनी टिप्पणियों में उल्लेख किया है, ऐसा नहीं होता है model(x); समझ में आता है कि एक कम GPU कदम शामिल है ("डाटासेट में रूपांतरण")।

अपडेट 2 : यदि आप इस मुद्दे का सामना करते हैं, तो आप इसके बारे में देवों को यहाँ बग कर सकते हैं ; यह ज्यादातर मुझे वहाँ गा रहा है


यह एक अच्छा जवाब है कि क्यों एक विधि धीमी है, लेकिन यह कई रन से अधिक रन समय की व्याख्या नहीं करता है।
LLSv2.0

1
@ LLSv2.0 पूरी तरह से अपने आप पर यकीन नहीं है, लेकिन अद्यतन जवाब - मैं अभी भी
देवों की

1
@ Ga97dil हाँ, फिर मैं स्पष्टीकरणों से बाहर हूँ - जीथब पर पूछने का प्रयास करें, हालांकि आप लंबी प्रतिक्रिया समय का सामना कर सकते हैं।
OverLordGoldDragon

1
@ Ga97dil वास्तव में, TF1 TF2 की तुलना में बहुत तेज हो सकता है - हालांकि TF 2.1 छोटे मॉडल और डेटासेट के लिए प्रयास करने लायक है, क्योंकि यह मेरे बेंचमार्क में प्रशिक्षण में सबसे तेज है (भविष्यवाणी नहीं करते हैं)। इससे भी महत्वपूर्ण बात, अगर आप कभी भी TF2 का उपयोग करते हैं, तो मैं आपको दृढ़ता से ग्राफ़ बनाम ईगर में प्रतिलिपि प्रस्तुत करने योग्यता का परीक्षण करने का सुझाव देता हूं ; परिणाम TF 2.1 में बहुत भिन्न हो सकते हैं ।
ओवरलॉर्डगोल्डड्रैगन

1
मैंने आपके पोस्ट को Git थ्रेड में जोड़ा है , और मेरी TF2 बनाम TF1 पोस्ट। मुझे सूचित करने के लिए धन्यवाद कि समस्या TF 1. में गायब हो गई है
OverLordGoldDragon

2

जब मैं निष्पादन समय में विसंगतियों की व्याख्या नहीं कर सकता, तो मैं सुझाव दे सकता हूं कि आप एकल मॉडल रिकॉर्ड या छोटे बैचों पर भविष्यवाणियों को तेज करने के लिए अपने मॉडल को TensorFlow Lite में बदलने की कोशिश करें।

मैंने इस मॉडल पर एक बेंचमार्क चलाया:

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(384, activation='elu', input_shape=(256,)),
    tf.keras.layers.Dense(384, activation='elu'),
    tf.keras.layers.Dense(256, activation='elu'),
    tf.keras.layers.Dense(128, activation='elu'),
    tf.keras.layers.Dense(32, activation='tanh')
])

एकल रिकॉर्ड के लिए भविष्यवाणी समय थे:

  1. model.predict(input): 18 मी
  2. model(input): 1.3ms
  3. मॉडल को TensorFlow Lite में परिवर्तित किया गया: 43us

मॉडल को बदलने का समय 2 सेकंड था।

नीचे दिए गए वर्ग से पता चलता है कि मॉडल को कैसे रूपांतरित करना और उपयोग करना है और predictकैरस मॉडल जैसी विधि प्रदान करता है । ध्यान दें कि इसे उन मॉडलों के साथ उपयोग करने के लिए संशोधित करने की आवश्यकता है जिनके पास केवल एक 1-D इनपुट और एक 1-D आउटपुट नहीं है।

class LiteModel:

    @classmethod
    def from_file(cls, model_path):
        return LiteModel(tf.lite.Interpreter(model_path=model_path))

    @classmethod
    def from_keras_model(cls, kmodel):
        converter = tf.lite.TFLiteConverter.from_keras_model(kmodel)
        tflite_model = converter.convert()
        return LiteModel(tf.lite.Interpreter(model_content=tflite_model))

    def __init__(self, interpreter):
        self.interpreter = interpreter
        self.interpreter.allocate_tensors()
        input_det = self.interpreter.get_input_details()[0]
        output_det = self.interpreter.get_output_details()[0]
        self.input_index = input_det["index"]
        self.output_index = output_det["index"]
        self.input_shape = input_det["shape"]
        self.output_shape = output_det["shape"]
        self.input_dtype = input_det["dtype"]
        self.output_dtype = output_det["dtype"]

    def predict(self, inp):
        inp = inp.astype(self.input_dtype)
        count = inp.shape[0]
        out = np.zeros((count, self.output_shape[1]), dtype=self.output_dtype)
        for i in range(count):
            self.interpreter.set_tensor(self.input_index, inp[i:i+1])
            self.interpreter.invoke()
            out[i] = self.interpreter.get_tensor(self.output_index)[0]
        return out

    def predict_single(self, inp):
        """ Like predict(), but only for a single record. The input data can be a Python list. """
        inp = np.array([inp], dtype=self.input_dtype)
        self.interpreter.set_tensor(self.input_index, inp)
        self.interpreter.invoke()
        out = self.interpreter.get_tensor(self.output_index)
        return out[0]

पूरा बेंचमार्क कोड और एक प्लॉट यहां पाया जा सकता है: https://medium.com/@micwurm/use-tensorflow-lite-to-speed-up-predictions-a3954886eb98


कूल, ने पहले कभी इसकी कोशिश नहीं की, लेकिन शायद यह शॉट के लायक होगा। संकेत के लिए धन्यवाद!
15:97 बजे गाहदिल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.