टेक्स्ट कार्यों के लिए सामान्य सेव्डमॉडल एपीआई

यह पृष्ठ वर्णन करता है कि टेक्स्ट-संबंधित कार्यों के लिए TF2 SavedModels को पुन: प्रयोज्य SavedModel API को कैसे कार्यान्वित करना चाहिए। (यह अब अप्रचलित TF1 हब प्रारूप के लिए टेक्स्ट के लिए सामान्य हस्ताक्षरों को प्रतिस्थापित और विस्तारित करता है।)

सिंहावलोकन

टेक्स्ट एम्बेडिंग की गणना करने के लिए कई एपीआई हैं (जिन्हें टेक्स्ट के सघन प्रतिनिधित्व या टेक्स्ट फीचर वैक्टर के रूप में भी जाना जाता है)।

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

  • प्रीप्रोसेस्ड इनपुट के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई एक ही कार्य को हल करता है, लेकिन दो अलग-अलग सेव्डमॉडल द्वारा कार्यान्वित किया जाता है:

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

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

  • ट्रांसफॉर्मर एनकोडर के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई पूर्व-संसाधित इनपुट से बीईआरटी और अन्य ट्रांसफार्मर एनकोडर के विशेष मामले में टेक्स्ट एम्बेडिंग के लिए एपीआई का विस्तार करता है।

    • इनपुट टेक्स्ट के एक से अधिक खंडों से एनकोडर इनपुट बनाने के लिए प्रीप्रोसेसर का विस्तार किया जाता है।
    • ट्रांसफार्मर एनकोडर व्यक्तिगत टोकन के संदर्भ-जागरूक एम्बेडिंग को उजागर करता है।

प्रत्येक मामले में, टेक्स्ट इनपुट यूटीएफ-8 एन्कोडेड स्ट्रिंग होते हैं, आमतौर पर सादे टेक्स्ट के, जब तक कि मॉडल दस्तावेज़ अन्यथा प्रदान नहीं करता है।

एपीआई के बावजूद, विभिन्न मॉडलों को विभिन्न भाषाओं और डोमेन के पाठ पर और विभिन्न कार्यों को ध्यान में रखते हुए पूर्व-प्रशिक्षित किया गया है। इसलिए, प्रत्येक टेक्स्ट एम्बेडिंग मॉडल हर समस्या के लिए उपयुक्त नहीं है।

टेक्स्ट इनपुट से टेक्स्ट एम्बेडिंग

टेक्स्ट इनपुट से टेक्स्ट एम्बेडिंग के लिए एक सेव्डमॉडल आकार [batch_size] के एक स्ट्रिंग टेंसर में इनपुट के एक बैच को स्वीकार करता है और उन्हें इनपुट के घने प्रतिनिधित्व (फीचर वैक्टर) के साथ आकार के फ्लोट32 टेंसर [batch_size, dim] में मैप करता है।

उपयोग सारांश

obj = hub.load("path/to/model")
text_input = ["A long sentence.",
              "single-word",
              "http://example.com"]
embeddings = obj(text_input)

पुन : प्रयोज्य सेव्डमॉडल एपीआई से याद करें कि मॉडल को प्रशिक्षण मोड में चलाने के लिए (उदाहरण के लिए, ड्रॉपआउट के लिए) एक कीवर्ड तर्क obj(..., training=True) की आवश्यकता हो सकती है, और वह obj लागू होने पर .variables , .trainable_variables और .regularization_losses विशेषताएँ प्रदान करता है। .

केरस में इन सबका ध्यान रखा जाता है

embeddings = hub.KerasLayer("path/to/model", trainable=...)(text_input)

प्रशिक्षण वितरित किया गया

यदि टेक्स्ट एम्बेडिंग का उपयोग एक मॉडल के भाग के रूप में किया जाता है जिसे वितरण रणनीति के साथ प्रशिक्षित किया जाता है, hub.load("path/to/model") या hub.KerasLayer("path/to/model", ...) , सम्मानपूर्वक, मॉडल के वेरिएबल को वितरित तरीके से बनाने के लिए distributionStrategy दायरे के अंदर होना चाहिए। उदाहरण के लिए

  with strategy.scope():
    ...
    model = hub.load("path/to/model")
    ...

उदाहरण

प्रीप्रोसेस्ड इनपुट के साथ टेक्स्ट एंबेडिंग

पूर्व-संसाधित इनपुट के साथ एक टेक्स्ट एम्बेडिंग को दो अलग-अलग SaveModels द्वारा कार्यान्वित किया जाता है:

  • एक प्रीप्रोसेसर जो आकार के एक स्ट्रिंग टेंसर को संख्यात्मक टेंसर के एक निर्देशांक [batch_size] पर मैप करता है,
  • एक एनकोडर जो प्रीप्रोसेसर द्वारा लौटाए गए टेंसर के एक निर्देश को स्वीकार करता है, एम्बेडिंग गणना का प्रशिक्षित भाग निष्पादित करता है, और आउटपुट का एक निर्देश लौटाता है। कुंजी "default" के अंतर्गत आउटपुट [batch_size, dim] आकार का एक फ्लोट32 टेंसर है।

यह प्रीप्रोसेसर को इनपुट पाइपलाइन में चलाने की अनुमति देता है लेकिन एक बड़े मॉडल के हिस्से के रूप में एनकोडर द्वारा गणना की गई एम्बेडिंग को ठीक करता है। विशेष रूप से, यह एनकोडर बनाने की अनुमति देता है जिसे टीपीयू पर चलाया और ठीक किया जा सकता है।

यह एक कार्यान्वयन विवरण है कि कौन से टेंसर प्रीप्रोसेसर के आउटपुट में समाहित हैं, और कौन से (यदि कोई हैं) "default" के अलावा अतिरिक्त टेंसर एनकोडर के आउटपुट में समाहित हैं।

एनकोडर के दस्तावेज़ीकरण में यह निर्दिष्ट होना चाहिए कि इसके साथ किस प्रीप्रोसेसर का उपयोग किया जाए। आमतौर पर, बिल्कुल एक ही सही विकल्प होता है।

उपयोग सारांश

text_input = tf.constant(["A long sentence.",
                          "single-word",
                          "http://example.com"])
preprocessor = hub.load("path/to/preprocessor")  # Must match `encoder`.
encoder_inputs = preprocessor(text_input)

encoder = hub.load("path/to/encoder")
encoder_outputs = encoder(encoder_inputs)
embeddings = encoder_outputs["default"]

पुन : प्रयोज्य सेव्डमॉडल एपीआई से याद करें कि एनकोडर को प्रशिक्षण मोड में चलाने के लिए (उदाहरण के लिए, ड्रॉपआउट के लिए) एक कीवर्ड तर्क encoder(..., training=True) की आवश्यकता हो सकती है, और वह encoder लागू होने पर विशेषताएँ .variables , .trainable_variables और .regularization_losses प्रदान करता है। .

preprocessor मॉडल में .variables हो सकते हैं लेकिन इसे आगे प्रशिक्षित करने के लिए नहीं है। प्रीप्रोसेसिंग मोड-निर्भर नहीं है: यदि preprocessor() में training=... तर्क है, तो इसका कोई प्रभाव नहीं पड़ता है।

केरस में इन सबका ध्यान रखा जाता है

encoder_inputs = hub.KerasLayer("path/to/preprocessor")(text_input)
encoder_outputs = hub.KerasLayer("path/to/encoder", trainable=True)(encoder_inputs)
embeddings = encoder_outputs["default"]

प्रशिक्षण वितरित किया गया

यदि एनकोडर का उपयोग एक मॉडल के भाग के रूप में किया जाता है जो वितरण रणनीति के साथ प्रशिक्षित होता है, hub.load("path/to/encoder") या hub.KerasLayer("path/to/encoder", ...) पर कॉल करें , आदरणीय, अंदर ही होना चाहिए

  with strategy.scope():
    ...

वितरित तरीके से एनकोडर वैरिएबल को फिर से बनाने के लिए।

इसी तरह, यदि प्रीप्रोसेसर प्रशिक्षित मॉडल का हिस्सा है (जैसा कि ऊपर दिए गए सरल उदाहरण में है), तो इसे भी वितरण रणनीति के दायरे में लोड करने की आवश्यकता है। यदि, हालांकि, प्रीप्रोसेसर का उपयोग इनपुट पाइपलाइन में किया जाता है (उदाहरण के लिए, tf.data.Dataset.map() को पास किए गए कॉलेबल में), तो इसकी लोडिंग वितरण रणनीति के दायरे से बाहर होनी चाहिए, ताकि इसके वेरिएबल्स (यदि कोई हो) को रखा जा सके। ) होस्ट सीपीयू पर।

उदाहरण

ट्रांसफार्मर एनकोडर के साथ टेक्स्ट एम्बेडिंग

टेक्स्ट के लिए ट्रांसफॉर्मर एनकोडर इनपुट अनुक्रमों के एक बैच पर काम करते हैं, प्रत्येक अनुक्रम में n पर कुछ मॉडल-विशिष्ट बाउंड के भीतर टोकन टेक्स्ट के n ≥ 1 खंड शामिल होते हैं। बीईआरटी और इसके कई एक्सटेंशनों के लिए, वह सीमा 2 है, इसलिए वे एकल खंड और खंड जोड़े स्वीकार करते हैं।

ट्रांसफॉर्मर एन्कोडर्स के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई इस सेटिंग में प्रीप्रोसेस्ड इनपुट के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई का विस्तार करता है।

preprocessor

ट्रांसफॉर्मर एनकोडर के साथ टेक्स्ट एम्बेडिंग के लिए एक प्रीप्रोसेसर सेव्डमॉडल, प्रीप्रोसेस्ड इनपुट (ऊपर देखें) के साथ टेक्स्ट एम्बेडिंग के लिए प्रीप्रोसेसर सेव्डमॉडल के एपीआई को लागू करता है, जो सिंगल-सेगमेंट टेक्स्ट इनपुट को सीधे एनकोडर इनपुट में मैप करने का एक तरीका प्रदान करता है।

इसके अलावा, प्रीप्रोसेसर सेव्डमॉडल एनकोडर के लिए एक इनपुट अनुक्रम में एन टोकननाइज्ड सेगमेंट को पैक करने के लिए टोकननाइजेशन (अलग-अलग प्रति सेगमेंट) और bert_pack_inputs के लिए कॉल करने योग्य सबऑब्जेक्ट tokenize प्रदान करता है। प्रत्येक सबऑब्जेक्ट पुन: प्रयोज्य सेव्डमॉडल एपीआई का अनुसरण करता है।

उपयोग सारांश

पाठ के दो खंडों के लिए एक ठोस उदाहरण के रूप में, आइए एक वाक्य प्रवेश कार्य को देखें जो पूछता है कि क्या एक आधार (पहला खंड) एक परिकल्पना (दूसरा खंड) करता है या नहीं।

preprocessor = hub.load("path/to/preprocessor")

# Tokenize batches of both text inputs.
text_premises = tf.constant(["The quick brown fox jumped over the lazy dog.",
                             "Good day."])
tokenized_premises = preprocessor.tokenize(text_premises)
text_hypotheses = tf.constant(["The dog was lazy.",  # Implied.
                               "Axe handle!"])       # Not implied.
tokenized_hypotheses = preprocessor.tokenize(text_hypotheses)

# Pack input sequences for the Transformer encoder.
seq_length = 128
encoder_inputs = preprocessor.bert_pack_inputs(
    [tokenized_premises, tokenized_hypotheses],
    seq_length=seq_length)  # Optional argument.

केरस में, इस गणना को इस प्रकार व्यक्त किया जा सकता है

tokenize = hub.KerasLayer(preprocessor.tokenize)
tokenized_hypotheses = tokenize(text_hypotheses)
tokenized_premises = tokenize(text_premises)

bert_pack_inputs = hub.KerasLayer(
    preprocessor.bert_pack_inputs,
    arguments=dict(seq_length=seq_length))  # Optional argument.
encoder_inputs = bert_pack_inputs([tokenized_premises, tokenized_hypotheses])

tokenize का विवरण

preprocessor.tokenize() को कॉल करने पर आकार का एक स्ट्रिंग Tensor स्वीकार होता है [batch_size] और एक RaggedTensor आकार का होता है [batch_size, ...] जिसका मान int32 टोकन आईडी है जो इनपुट स्ट्रिंग्स का प्रतिनिधित्व करता है। batch_size के बाद r ≥ 1 रैग्ड आयाम हो सकते हैं लेकिन कोई अन्य समान आयाम नहीं हो सकता।

  • यदि r =1 है, तो आकार [batch_size, (tokens)] है, और प्रत्येक इनपुट को केवल टोकन के एक फ्लैट अनुक्रम में टोकन किया जाता है।
  • यदि r >1, तो समूहीकरण के r -1 अतिरिक्त स्तर हैं। उदाहरण के लिए, Tensorflow_text.BertTokenizer टोकन को शब्दों के आधार पर समूहित करने के लिए r =2 का उपयोग करता है और [batch_size, (words), (tokens_per_word)] आकार देता है। यह मौजूदा मॉडल पर निर्भर है कि इनमें से कितने अतिरिक्त स्तर मौजूद हैं, यदि कोई हैं, और वे किस समूह का प्रतिनिधित्व करते हैं।

उपयोगकर्ता टोकनयुक्त इनपुट को संशोधित कर सकता है (लेकिन इसकी आवश्यकता नहीं है), उदाहरण के लिए, seq_length सीमा को समायोजित करने के लिए जिसे पैकिंग एनकोडर इनपुट में लागू किया जाएगा। टोकननाइज़र आउटपुट में अतिरिक्त आयाम यहां मदद कर सकते हैं (उदाहरण के लिए, शब्द सीमाओं का सम्मान करने के लिए) लेकिन अगले चरण में अर्थहीन हो जाते हैं।

पुन: प्रयोज्य सेव्डमॉडल एपीआई के संदर्भ में, preprocessor.tokenize ऑब्जेक्ट में .variables हो सकते हैं लेकिन इसे आगे प्रशिक्षित करने का इरादा नहीं है। टोकनाइजेशन मोड-निर्भर नहीं है: यदि preprocessor.tokenize() में training=... तर्क है, तो इसका कोई प्रभाव नहीं पड़ता है।

bert_pack_inputs का विवरण

preprocessor.bert_pack_inputs() पर कॉल टोकनयुक्त इनपुट (प्रत्येक इनपुट सेगमेंट के लिए अलग से बैच) की एक पायथन सूची स्वीकार करता है और ट्रांसफॉर्मर एनकोडर मॉडल के लिए निश्चित-लंबाई इनपुट अनुक्रमों के एक बैच का प्रतिनिधित्व करने वाले टेंसर का एक निर्देश लौटाता है।

प्रत्येक टोकनयुक्त इनपुट [batch_size, ...] आकार का एक int32 RaggedTensor है, जहां बैच_साइज के बाद रैग्ड आयामों की संख्या r या तो 1 है या preprocessor.tokenize(). (उत्तरार्द्ध केवल सुविधा के लिए है; पैकिंग से पहले अतिरिक्त आयामों को समतल कर दिया जाता है।)

एनकोडर की अपेक्षा के अनुरूप पैकिंग इनपुट खंडों के आसपास विशेष टोकन जोड़ती है। bert_pack_inputs() कॉल बिल्कुल मूल BERT मॉडल और उनके कई एक्सटेंशन द्वारा उपयोग की जाने वाली पैकिंग योजना को लागू करता है: पैक्ड अनुक्रम एक स्टार्ट-ऑफ-सीक्वेंस टोकन के साथ शुरू होता है, इसके बाद टोकनयुक्त सेगमेंट होते हैं, प्रत्येक एक सेगमेंट के अंत में समाप्त होता है टोकन. Seq_length तक की शेष स्थिति, यदि कोई हो, पैडिंग टोकन से भरी जाती है।

यदि एक पैक्ड अनुक्रम seq_length से अधिक होगा, bert_pack_inputs() अपने खंडों को लगभग समान आकार के उपसर्गों में छोटा कर देता है ताकि पैक्ड अनुक्रम बिल्कुल seq_length के भीतर फिट हो जाए।

पैकिंग मोड-निर्भर नहीं है: यदि preprocessor.bert_pack_inputs() में training=... तर्क है, तो इसका कोई प्रभाव नहीं पड़ता है। इसके अलावा, preprocessor.bert_pack_inputs में वेरिएबल होने या फाइन-ट्यूनिंग का समर्थन करने की उम्मीद नहीं है।

एनकोडर

एनकोडर को उसी तरह से encoder_inputs के निर्देश पर कॉल किया जाता है, जैसे प्रीप्रोसेस्ड इनपुट (ऊपर देखें) के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई में, जिसमें पुन: प्रयोज्य सेव्डमॉडल एपीआई के प्रावधान शामिल हैं।

उपयोग सारांश

encoder = hub.load("path/to/encoder")
encoder_outputs = encoder(encoder_inputs)

या केरस में समकक्ष:

encoder = hub.KerasLayer("path/to/encoder", trainable=True)
encoder_outputs = encoder(encoder_inputs)

विवरण

encoder_outputs निम्नलिखित कुंजियों के साथ टेंसर का एक निर्देश है।

  • "sequence_output" : प्रत्येक पैक किए गए इनपुट अनुक्रम के प्रत्येक टोकन के संदर्भ-जागरूक एम्बेडिंग के साथ आकार का एक फ्लोट32 टेंसर [batch_size, seq_length, dim]
  • "pooled_output" : आकार का एक फ्लोट32 टेंसर [batch_size, dim] प्रत्येक इनपुट अनुक्रम को समग्र रूप से एम्बेड करने के साथ, कुछ प्रशिक्षण योग्य तरीके से अनुक्रम_आउटपुट से प्राप्त होता है।
  • "default" , जैसा कि पूर्व-संसाधित इनपुट के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई द्वारा आवश्यक है: प्रत्येक इनपुट अनुक्रम के एम्बेडिंग के साथ आकार का एक फ्लोट32 टेंसर [batch_size, dim] (यह पूल्ड_आउटपुट का सिर्फ एक उपनाम हो सकता है।)

इस एपीआई परिभाषा के लिए encoder_inputs की सामग्री की कड़ाई से आवश्यकता नहीं है। हालाँकि, BERT-शैली इनपुट का उपयोग करने वाले एनकोडर के लिए, एनकोडर को इंटरचेंज करने और प्रीप्रोसेसर मॉडल का पुन: उपयोग करने में घर्षण को कम करने के लिए निम्नलिखित नामों ( टेन्सरफ्लो मॉडल गार्डन के एनएलपी मॉडलिंग टूलकिट से) का उपयोग करने की अनुशंसा की जाती है:

  • "input_word_ids" : पैक किए गए इनपुट अनुक्रम के टोकन आईडी के साथ आकार का एक int32 टेंसर [batch_size, seq_length] (अर्थात, स्टार्ट-ऑफ-सीक्वेंस टोकन, एंड-ऑफ-सेगमेंट टोकन और पैडिंग शामिल है)।
  • "input_mask" : आकार का एक int32 टेंसर [batch_size, seq_length] पैडिंग से पहले मौजूद सभी इनपुट टोकन की स्थिति पर मान 1 और पैडिंग टोकन के लिए मान 0।
  • "input_type_ids" : इनपुट सेगमेंट के सूचकांक के साथ आकार का एक int32 टेंसर [batch_size, seq_length] जिसने संबंधित स्थिति में इनपुट टोकन को जन्म दिया। पहले इनपुट सेगमेंट (इंडेक्स 0) में स्टार्ट-ऑफ-सीक्वेंस टोकन और इसके एंड-ऑफ-सेगमेंट टोकन शामिल हैं। दूसरे और बाद के खंड (यदि मौजूद हैं) में उनके संबंधित खंड-अंत टोकन शामिल हैं। पैडिंग टोकन को फिर से इंडेक्स 0 मिलता है।

प्रशिक्षण वितरित किया गया

वितरण रणनीति के दायरे के अंदर या बाहर प्रीप्रोसेसर और एनकोडर ऑब्जेक्ट को लोड करने के लिए, वही नियम लागू होते हैं जो प्रीप्रोसेस्ड इनपुट के साथ टेक्स्ट एम्बेडिंग के लिए एपीआई में लागू होते हैं (ऊपर देखें)।

उदाहरण