चौथा चरण: मॉडल बनाना, ट्रेनिंग देना, और उसका आकलन करना

इस सेक्शन में, हम अपने मॉडल को बनाने, उनकी ट्रेनिंग और आकलन करने के लिए काम करेंगे. चरण 3 में, हम S/W का इस्तेमाल करके, n-gram मॉडल या क्रम वाले मॉडल का इस्तेमाल करने का विकल्प चुनते हैं. अब समय है, हमारे क्लासिफ़िकेशन एल्गोरिदम लिखने और उसे ट्रेनिंग देने का. हम इसके लिए tf.keras एपीआई के साथ TensorFlow का इस्तेमाल करेंगे.

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

लेयर का लीनियर स्टैक

चित्र 9: लेयर का लीनियर स्टैक

इनपुट लेयर और इंटरमीडिएट लेयर को अलग-अलग तरीके से बनाया जाएगा. यह इस बात पर निर्भर करता है कि हम n-ग्राम बना रहे हैं या सीक्वेंस मॉडल. लेकिन मॉडल टाइप पर ध्यान दिए बिना, दी गई समस्या के लिए आखिरी लेयर एक जैसी होगी.

आखिरी लेयर बनाना

जब हमारे पास सिर्फ़ दो क्लास (बाइनरी क्लासिफ़िकेशन) हों, तो हमारे मॉडल को एक संभावना वाला स्कोर देना चाहिए. उदाहरण के लिए, दिए गए इनपुट के नमूने के लिए 0.2 को आउट करने का मतलब है कि “20% कॉन्फ़िडेंस है कि यह सैंपल फ़र्स्ट क्लास में है (क्लास 1), 80% है कि यह दूसरी क्लास (क्लास 0) में है.” इस तरह के प्रॉबबिलिटी स्कोर का आउटपुट देने के लिए, एक्टिवेशन फ़ंक्शन का

जब दो से ज़्यादा क्लास होती हैं (मल्टी-क्लास वर्गीकरण) तो हमारे मॉडल को हर क्लास के लिए एक संभावना स्कोर देना चाहिए. इन स्कोर का योग 1 होना चाहिए. उदाहरण के लिए, {0: 0.2, 1: 0.7, 2: 0.1} को आउट करने का मतलब है कि “20% कॉन्फ़िडेंस है कि यह सैंपल 0 क्लास में है, 70% यह क्लास 1 में है, और 10% यह क्लास 2 में है.” इन स्कोर को आउटपुट करने के लिए, लास्ट लेयर में ऐक्टिवेशन फ़ंक्शन सॉफ़्टमैक्स होना चाहिए और मॉडल को ट्रेनिंग देने के लिए इस्तेमाल किया जाने वाला लॉस फ़ंक्शन क्लास क्रॉस-एंट्रॉपी होना चाहिए. (दाईं ओर चित्र 10 देखें).

आखिरी लेयर

इमेज 10: आखिरी लेयर

यह कोड एक ऐसा फ़ंक्शन बताता है जो क्लास की संख्या को इनपुट के तौर पर लेता है. साथ ही, यह लेयर की इकाइयों की सही संख्या (बाइनरी के लिए एक यूनिट) और हर क्लास के लिए एक यूनिट देता है. इसके अलावा, हर क्लास के लिए सही इकाई होती है:

def _get_last_layer_units_and_activation(num_classes):
    """Gets the # units and activation function for the last network layer.

    # Arguments
        num_classes: int, number of classes.

    # Returns
        units, activation values.
    """
    if num_classes == 2:
        activation = 'sigmoid'
        units = 1
    else:
        activation = 'softmax'
        units = num_classes
    return units, activation

नीचे दिए गए दो सेक्शन में, n-ग्राम मॉडल के क्रम के लिए, बाकी मॉडल लेयर और सिलसिलेवार मॉडल बनाने की जानकारी दी गई है.

S/W का अनुपात छोटा होने पर, हमने पाया है कि n-ग्राम मॉडल, क्रम वाले मॉडल की तुलना में बेहतर परफ़ॉर्म करते हैं. बड़ी संख्या में छोटे, घने वेक्टर होने पर क्रम के मॉडल बेहतर होते हैं. ऐसा इसलिए होता है, क्योंकि एम्बेडिंग के संबंध में घनी जगह आती है और कई सैंपल पर बेहतर काम होता है.

बिल्ड n-gram मॉडल [Option A]

हम ऐसे मॉडल को रेफ़र करते हैं जो टोकन को अलग-अलग प्रोसेस करते हैं (जो खाते के वर्ड ऑर्डर में शामिल नहीं होता). इसे n-ग्राम मॉडल के तौर पर देखा जाता है. आसान लेयर वाले पर्सपेट्रन (इसमें लॉजिस्टिक रिग्रेशन शामिल है), लॉजिस्टिक रिग्रेशन मशीन, और वेक्टर मशीनों के साथ काम करने वाले सभी मॉडल इस कैटगरी में शामिल होते हैं. वे टेक्स्ट ऑर्डर करने के बारे में किसी भी जानकारी का फ़ायदा नहीं ले सकते.

हमने ऊपर बताए गए कुछ n-ग्राम मॉडल की परफ़ॉर्मेंस की तुलना की. हमें पता चला कि मल्टी-लेयर पर्सपेट्रॉन (MLP) आम तौर पर, अन्य विकल्पों की तुलना में बेहतर परफ़ॉर्म करते हैं. एमएलपी को समझना और समझना आसान होता है. साथ ही, एमएलपी को सटीक तरीके से कैलकुलेट करने की ज़रूरत होती है.

यह कोड, tf.keras में दो लेयर वाले एमएलपी मॉडल के बारे में बताता है. इसमें रेगुलराइज़ेशन के लिए ड्रॉपडाउन लेयर (ट्रेनिंग सैंपल के लिए ओवरफ़िटिंग कुछ जोड़े गए हैं.

from tensorflow.python.keras import models
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.layers import Dropout

def mlp_model(layers, units, dropout_rate, input_shape, num_classes):
    """Creates an instance of a multi-layer perceptron model.

    # Arguments
        layers: int, number of `Dense` layers in the model.
        units: int, output dimension of the layers.
        dropout_rate: float, percentage of input to drop at Dropout layers.
        input_shape: tuple, shape of input to the model.
        num_classes: int, number of output classes.

    # Returns
        An MLP model instance.
    """
    op_units, op_activation = _get_last_layer_units_and_activation(num_classes)
    model = models.Sequential()
    model.add(Dropout(rate=dropout_rate, input_shape=input_shape))

    for _ in range(layers-1):
        model.add(Dense(units=units, activation='relu'))
        model.add(Dropout(rate=dropout_rate))

    model.add(Dense(units=op_units, activation=op_activation))
    return model

सीक्वेंस मॉडल बनाएं [Option B]

हम उन मॉडल को रेफ़र करते हैं जो टोकन के पास होने के हिसाब से सीख सकते हैं. ये सिलसिलेवार मॉडल के तौर पर सीख सकते हैं. इसमें CNN और RNN क्लास की मॉडल शामिल हैं. इन मॉडल के लिए डेटा को, वेक्टर के तौर पर पहले से प्रोसेस किया जाता है.

आम तौर पर, क्रम वाले मॉडल में सीखने के लिए ज़्यादा पैरामीटर होते हैं. इन मॉडल में पहली लेयर, एम्बेडिंग लेयर होती है. यह एक घनी वेक्टर स्पेस में मौजूद शब्दों के बीच के संबंध के बारे में बताती है. कई शब्दों वाले रिश्तों को सीखने का काम, कई नमूनों पर करना अच्छा होता है.

हो सकता है कि किसी डेटासेट में मौजूद शब्द उस डेटासेट के लिए खास नहीं हों. इस तरह, हम अन्य डेटासेट का इस्तेमाल करके अपने डेटासेट में मौजूद शब्दों के बीच के संबंध के बारे में जान सकते हैं. ऐसा करने के लिए, हम एम्बेड किए गए किसी दूसरे डेटासेट को एम्बेड करने की अपनी लेयर में ट्रांसफ़र कर सकते हैं. इन एम्बेडिंग को पहले से ट्रेनिंग दी गई एम्बेड करने की सुविधा कहा जाता है. पहले से ट्रेनिंग वाले एम्बेड का इस्तेमाल करने से, मॉडल को सीखने की प्रक्रिया में शुरुआत करने में मदद मिलती है.

पहले से ट्रेनिंग देने वाले एम्बेडिंग उपलब्ध हैं, जिन्हें बड़े पैमाने के इस्तेमाल से ट्रेनिंग दी गई है, जैसे कि GloVe. GloVe को कई कॉर्पोरा (मुख्य रूप से विकिपीडिया) के लिए प्रशिक्षित किया गया है. हमने GloVe एम्बेडिंग के वर्शन का इस्तेमाल करके अपने सिलसिलेवार मॉडल की ट्रेनिंग की और पाया कि अगर हम पहले से ट्रेनिंग वाले एम्बेडिंग के वज़न में खो गए थे और बाकी नेटवर्क को ट्रेनिंग दी थी, तो मॉडल अच्छा परफ़ॉर्म नहीं करते थे. ऐसा इसलिए हो सकता है, क्योंकि एम्बेड करने की ट्रेनिंग के लिए इस्तेमाल किए गए संदर्भ को, उस संदर्भ से अलग हो सकता था जिसमें हम इसका इस्तेमाल कर रहे थे.

हो सकता है कि Wikipedia डेटा पर GloVe एम्बेड किए गए एम्बेड किए गए टेक्स्ट, हमारे IMDb डेटासेट में मौजूद भाषा के पैटर्न से मेल न खाएं. अनुमानित संबंधों को अपडेट करने की ज़रूरत पड़ सकती है—उदाहरण के लिए, एम्बेड करने के वज़न में संदर्भ से जुड़े बदलाव करने की ज़रूरत पड़ सकती है. हम दो चरणों में ऐसा करते हैं:

  1. पहली बार चलाने पर, एम्बेड करने वाली परत के महत्व को फ़्रीज़ कर दिया जाता है. साथ ही, हम बाकी नेटवर्क को सीखने की अनुमति देते हैं. इस रन के आखिर में, मॉडल के महत्व एक ऐसी स्थिति तक पहुंचते हैं जो उनके शुरू न किए जाने वाले मानों से कहीं बेहतर होती है. दूसरी बार चलाने के लिए, हम एम्बेड करने की लेयर को भी सीखने की अनुमति देते हैं, ताकि नेटवर्क में सभी ट्रैफ़िक को ठीक किया जा सके. हम इस प्रोसेस को बेहतर एम्बेड करने की सुविधा कहते हैं.

  2. बेहतर एम्बेड की गई एम्बेडिंग का इस्तेमाल करने से परफ़ॉर्मेंस बेहतर होती है. हालांकि, इसके लिए नेटवर्क को ट्रेनिंग देने के लिए खर्च में बढ़ोतरी की ज़रूरत पड़ती है. ज़रूरत के मुताबिक सैंपल होने पर, हम नए सिरे से एम्बेड करने का तरीका सीख सकते थे. हमने देखा कि S/W > 15K के लिए, बिल्कुल शुरू से शुरू करके फ़ाइन-ट्यून किए गए एम्बेडिंग के सटीक इस्तेमाल से शुरू हो रहा है.

हमने CNN और sepCNN, RNN (LSTM & GRU), CNN-RNN, और स्टैक किए गए RNN जैसे अलग-अलग क्रम के मॉडल की तुलना की तुलना की है. हमने पाया कि sepCNN, एक कॉन्वोलूशनल नेटवर्क वैरिएंट है जो अक्सर ज़्यादा डेटा की बचत करता है. साथ ही, यह कंप्यूटिंग की क्षमता को दूसरी मॉडल की तुलना में ज़्यादा बेहतर परफ़ॉर्म करता है.

यह कोड चार लेयर वाला sepCNN मॉडल बनाता है:

from tensorflow.python.keras import models
from tensorflow.python.keras import initializers
from tensorflow.python.keras import regularizers

from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.layers import Dropout
from tensorflow.python.keras.layers import Embedding
from tensorflow.python.keras.layers import SeparableConv1D
from tensorflow.python.keras.layers import MaxPooling1D
from tensorflow.python.keras.layers import GlobalAveragePooling1D

def sepcnn_model(blocks,
                 filters,
                 kernel_size,
                 embedding_dim,
                 dropout_rate,
                 pool_size,
                 input_shape,
                 num_classes,
                 num_features,
                 use_pretrained_embedding=False,
                 is_embedding_trainable=False,
                 embedding_matrix=None):
    """Creates an instance of a separable CNN model.

    # Arguments
        blocks: int, number of pairs of sepCNN and pooling blocks in the model.
        filters: int, output dimension of the layers.
        kernel_size: int, length of the convolution window.
        embedding_dim: int, dimension of the embedding vectors.
        dropout_rate: float, percentage of input to drop at Dropout layers.
        pool_size: int, factor by which to downscale input at MaxPooling layer.
        input_shape: tuple, shape of input to the model.
        num_classes: int, number of output classes.
        num_features: int, number of words (embedding input dimension).
        use_pretrained_embedding: bool, true if pre-trained embedding is on.
        is_embedding_trainable: bool, true if embedding layer is trainable.
        embedding_matrix: dict, dictionary with embedding coefficients.

    # Returns
        A sepCNN model instance.
    """
    op_units, op_activation = _get_last_layer_units_and_activation(num_classes)
    model = models.Sequential()

    # Add embedding layer. If pre-trained embedding is used add weights to the
    # embeddings layer and set trainable to input is_embedding_trainable flag.
    if use_pretrained_embedding:
        model.add(Embedding(input_dim=num_features,
                            output_dim=embedding_dim,
                            input_length=input_shape[0],
                            weights=[embedding_matrix],
                            trainable=is_embedding_trainable))
    else:
        model.add(Embedding(input_dim=num_features,
                            output_dim=embedding_dim,
                            input_length=input_shape[0]))

    for _ in range(blocks-1):
        model.add(Dropout(rate=dropout_rate))
        model.add(SeparableConv1D(filters=filters,
                                  kernel_size=kernel_size,
                                  activation='relu',
                                  bias_initializer='random_uniform',
                                  depthwise_initializer='random_uniform',
                                  padding='same'))
        model.add(SeparableConv1D(filters=filters,
                                  kernel_size=kernel_size,
                                  activation='relu',
                                  bias_initializer='random_uniform',
                                  depthwise_initializer='random_uniform',
                                  padding='same'))
        model.add(MaxPooling1D(pool_size=pool_size))

    model.add(SeparableConv1D(filters=filters * 2,
                              kernel_size=kernel_size,
                              activation='relu',
                              bias_initializer='random_uniform',
                              depthwise_initializer='random_uniform',
                              padding='same'))
    model.add(SeparableConv1D(filters=filters * 2,
                              kernel_size=kernel_size,
                              activation='relu',
                              bias_initializer='random_uniform',
                              depthwise_initializer='random_uniform',
                              padding='same'))
    model.add(GlobalAveragePooling1D())
    model.add(Dropout(rate=dropout_rate))
    model.add(Dense(op_units, activation=op_activation))
    return model

अपने मॉडल को ट्रेनिंग दें

अब जब हमने मॉडल आर्किटेक्चर बना लिया है, तो हमें मॉडल को ट्रेनिंग देना होगा. ट्रेनिंग में मॉडल की मौजूदा स्थिति के आधार पर अनुमान लगाना, यह अनुमान लगाना कि अनुमान कितना गलत है, और नेटवर्क के वेट या पैरामीटर को अपडेट करना, इस गड़बड़ी को कम करना और मॉडल को बेहतर बनाना है. हम इस प्रोसेस को तब तक दोहराते हैं, जब तक हमारा मॉडल इकट्ठा न हो जाए. साथ ही, सीखने की प्रक्रिया पूरी न हो सके. इस प्रोसेस के लिए तीन मुख्य पैरामीटर चुने जाने चाहिए (टेबल 2 देखें).

  • मेट्रिक: मेट्रिक का इस्तेमाल करके, हमारे मॉडल की परफ़ॉर्मेंस का आकलन करने का तरीका. हमने अपने प्रयोगों में, मेट्रिक के तौर पर सटीक जानकारी का इस्तेमाल किया है.
  • ऐप्लिकेशन अनइंस्टॉल करना: यह एक ऐसा फ़ंक्शन है जिसका इस्तेमाल उस नुकसान की वैल्यू का हिसाब लगाने के लिए किया जाता है जिसे ट्रेनिंग प्रोसेस के बाद, नेटवर्क के वज़न को कम करके कम किया जाता है. डेटा को अलग-अलग ग्रुप में बांटने से जुड़ी समस्याओं के लिए, क्रॉस-एंट्रॉपी हानि ठीक से काम करती है.
  • ऑप्टिमाइज़र: एक ऐसा फ़ंक्शन जो तय करता है कि लॉस फ़ंक्शन के आउटपुट के आधार पर, नेटवर्क वेट कैसे अपडेट किए जाएंगे. हमने अपने प्रयोगों में लोकप्रिय ऐडम ऑप्टिमाइज़र का इस्तेमाल किया.

Keras में, हम compile तरीका का इस्तेमाल करके, इन लर्निंग पैरामीटर को किसी मॉडल में पास कर सकते हैं.

लर्निंग पैरामीटर वैल्यू
मेट्रिक सटीक
हानि फ़ंक्शन - बाइनरी वर्गीकरण बाइनरी_क्रॉसएंट्रॉपी
हानि फ़ंक्शन - एकाधिक वर्ग वर्गीकरण Sparse_categorycal_Crossentropy
ऑप्टिमाइज़र AdMob

टेबल 2: लर्निंग पैरामीटर

असल ट्रेनिंग फ़िट तरीके का इस्तेमाल करके की जाती है. आपके डेटासेट के साइज़ के आधार पर, इस तरीके से ज़्यादातर कंप्यूट साइकल खर्च होंगे. हर ट्रेनिंग दोहराव के दौरान, आपके ट्रेनिंग डेटा के batch_size सैंपल का इस्तेमाल करके, नुकसान की गणना की जाती है और इस वैल्यू के आधार पर महत्व को एक बार अपडेट किया जाता है. मॉडल, ट्रेनिंग का पूरा डेटासेट देख लेने के बाद, ट्रेनिंग की प्रोसेस epoch पूरी करती है. हर अवधि के आखिर में, हम पुष्टि करने वाले डेटासेट का इस्तेमाल यह जानने के लिए करते हैं कि मॉडल कितनी अच्छी तरह सीख रहा है. हम पहले से तय अवधि के लिए, डेटासेट की मदद से ट्रेनिंग को दोहराते हैं. इसे जल्दी ऑप्टिमाइज़ करके, हम इस सुविधा को ऑप्टिमाइज़ कर सकते हैं. हालांकि, ऐसा तब किया जाता है, जब पुष्टि करने के लिए किया गया समय लगातार दिखता रहता है. इससे, यह पता चलता है कि अब मॉडल को कोई ट्रेनिंग नहीं मिल रही है.

ट्रेनिंग हाइपरपैरामीटर वैल्यू
सीखने की दर एक से तीन
युग 1000
बैच का साइज़ 512
तय समय से पहले रोकना पैरामीटर: val_loss, धैर्य: 1

टेबल 3: ट्रेनिंग हाइपरपैरामीटर

नीचे दिया गया Kerberos कोड, ट्रेनिंग प्रोसेस को लागू करता है. इसके लिए, ऊपर दी गई टेबल 2 & 3 में चुने गए पैरामीटर का इस्तेमाल करें:

def train_ngram_model(data,
                      learning_rate=1e-3,
                      epochs=1000,
                      batch_size=128,
                      layers=2,
                      units=64,
                      dropout_rate=0.2):
    """Trains n-gram model on the given dataset.

    # Arguments
        data: tuples of training and test texts and labels.
        learning_rate: float, learning rate for training model.
        epochs: int, number of epochs.
        batch_size: int, number of samples per batch.
        layers: int, number of `Dense` layers in the model.
        units: int, output dimension of Dense layers in the model.
        dropout_rate: float: percentage of input to drop at Dropout layers.

    # Raises
        ValueError: If validation data has label values which were not seen
            in the training data.
    """
    # Get the data.
    (train_texts, train_labels), (val_texts, val_labels) = data

    # Verify that validation labels are in the same range as training labels.
    num_classes = explore_data.get_num_classes(train_labels)
    unexpected_labels = [v for v in val_labels if v not in range(num_classes)]
    if len(unexpected_labels):
        raise ValueError('Unexpected label values found in the validation set:'
                         ' {unexpected_labels}. Please make sure that the '
                         'labels in the validation set are in the same range '
                         'as training labels.'.format(
                             unexpected_labels=unexpected_labels))

    # Vectorize texts.
    x_train, x_val = vectorize_data.ngram_vectorize(
        train_texts, train_labels, val_texts)

    # Create model instance.
    model = build_model.mlp_model(layers=layers,
                                  units=units,
                                  dropout_rate=dropout_rate,
                                  input_shape=x_train.shape[1:],
                                  num_classes=num_classes)

    # Compile model with learning parameters.
    if num_classes == 2:
        loss = 'binary_crossentropy'
    else:
        loss = 'sparse_categorical_crossentropy'
    optimizer = tf.keras.optimizers.Adam(lr=learning_rate)
    model.compile(optimizer=optimizer, loss=loss, metrics=['acc'])

    # Create callback for early stopping on validation loss. If the loss does
    # not decrease in two consecutive tries, stop training.
    callbacks = [tf.keras.callbacks.EarlyStopping(
        monitor='val_loss', patience=2)]

    # Train and validate model.
    history = model.fit(
            x_train,
            train_labels,
            epochs=epochs,
            callbacks=callbacks,
            validation_data=(x_val, val_labels),
            verbose=2,  # Logs once per epoch.
            batch_size=batch_size)

    # Print results.
    history = history.history
    print('Validation accuracy: {acc}, loss: {loss}'.format(
            acc=history['val_acc'][-1], loss=history['val_loss'][-1]))

    # Save model.
    model.save('IMDb_mlp_model.h5')
    return history['val_acc'][-1], history['val_loss'][-1]

सिलसिलेवार विज्ञापन मॉडल की ट्रेनिंग के लिए, कृपया यहां दिए गए कोड के उदाहरण देखें.