في هذه الوحدة، سوف تستخدم لوغاريتم أقرب مجاور-K‏ (k-NN) المدمج في Amazon SageMaker لتدريب نموذج توصيات المحتوى.

إن تقنية أقرب مجاور-K‏ (k-NN) في Amazon SageMaker عبارة عن لوغاريتم تعلّم لا بارامتري قائم على الفهرس الخاضع للإشراف ويمكن استخدامه لمهام التصنيف والتراجع. للتصنيف، يستفسر اللوغاريتم عن أقرب نقاط k من الهدف ويعرض التسمية الأكثر استخدامًا في فئتها في شكل تسمية متوقعة. وبسبب مشاكل التراجع، يعرض اللوغاريتم متوسط القيم المتوقعة التي تعرضها أقرب مجاورات k.

التدريب على لوغاريتم k-NN له ثلاث خطوات: إنشاء النماذج وتقليل الأبعاد وإنشاء الفهرس. يقلل إنشاء النماذج حجم مجموعة البيانات الأولية بحيث تتناسب مع الذاكرة. وبالنسبة إلى تقليل الأبعاد، يقلل اللوغاريتم بُعد الميزة الخاص بالبيانات للحد من تأثير نموذج k-NN في الذاكرة وزمن الانتقال إلى الاستدلال. نقدم طريقتين لتقليل الأبعاد، هما: التنبؤ العشوائي وتحويل Johnson-Lindenstrauss السريع. عادة ما نستخدم تقليل الأبعاد لمجموعات البيانات ذات الأبعاد الكبيرة (d >1000) لتجنب «لعنة الأبعاد» التي تسبب مشاكل في التحليلات الإحصائية للبيانات التي تتفرق مع تزايد الأبعاد. الهدف الأساسي من تدريب k-NN هو إنشاء الفهرس. يتيح الفهرس عمليات البحث الفعالة عن المسافات بين النقاط التي لم يتم تحديد قيمها أو تسميات فئتها وأقرب نقاط k لاستخدامها من أجل الاستدلال.

في الخطوات التالية، حدد لوغاريتم k-NN من أجل مهمة تدريب واضبط قيم المعلمة الفائقة لضبط النموذج وقم بتشغيله. ثم انشر النموذج على نقطة النهاية التي يديرها Amazon SageMaker لوضع التنبؤات.

الوقت اللازم لاستكمال الوحدة: 20دقيقة


  • الخطوة 1. إنشاء مهمة تدريب وتشغيلها

    في الوحدة السابقة، أنشأت متجهات الموضوع. في هذه الوحدة، سوف تنشئ وتنشر وحدة توصيات المحتوى التي تحتفظ بفهرس متجهات الموضوع.

    أولاً، أنشئ القاموس الذي يربط التسميات العشوائية بالتسميات الأصلية في بيانات التدريب. في دفتر الملاحظات الخاص بك، انسخ والصق التعليمة البرمجية التالية واختر تشغيل.

    labels = newidx 
    labeldict = dict(zip(newidx,idx))

    ثم قم بتخزين بيانات التدريب في حاوية S3 الخاصة بك باستخدام التعليمة البرمجية التالية:

    import io
    import sagemaker.amazon.common as smac
    
    
    print('train_features shape = ', predictions.shape)
    print('train_labels shape = ', labels.shape)
    buf = io.BytesIO()
    smac.write_numpy_to_dense_tensor(buf, predictions, labels)
    buf.seek(0)
    
    bucket = BUCKET
    prefix = PREFIX
    key = 'knn/train'
    fname = os.path.join(prefix, key)
    print(fname)
    boto3.resource('s3').Bucket(bucket).Object(fname).upload_fileobj(buf)
    s3_train_data = 's3://{}/{}/{}'.format(bucket, prefix, key)
    print('uploaded training data location: {}'.format(s3_train_data))
    

    بعد ذلك، استخدم وظيفة المساعدة لإنشاء أداة تقدير k-NN بحيث تشبه إلى حد كبير أداة التقدير NTM التي أنشأتها في الوحدة 3.

    def trained_estimator_from_hyperparams(s3_train_data, hyperparams, output_path, s3_test_data=None):
        """
        Create an Estimator from the given hyperparams, fit to training data, 
        and return a deployed predictor
        
        """
        # set up the estimator
        knn = sagemaker.estimator.Estimator(get_image_uri(boto3.Session().region_name, "knn"),
            get_execution_role(),
            train_instance_count=1,
            train_instance_type='ml.c4.xlarge',
            output_path=output_path,
            sagemaker_session=sagemaker.Session())
        knn.set_hyperparameters(**hyperparams)
        
        # train a model. fit_input contains the locations of the train and test data
        fit_input = {'train': s3_train_data}
        knn.fit(fit_input)
        return knn
    
    hyperparams = {
        'feature_dim': predictions.shape[1],
        'k': NUM_NEIGHBORS,
        'sample_size': predictions.shape[0],
        'predictor_type': 'classifier' ,
        'index_metric':'COSINE'
    }
    output_path = 's3://' + bucket + '/' + prefix + '/knn/output'
    knn_estimator = trained_estimator_from_hyperparams(s3_train_data, hyperparams, output_path)
    

    وأثناء سير مهمة التدريب، تعرّف أكثر على المعلمات في وظيفة المساعد.

    يوفر لوغاريتم k-NN في Amazon SageMaker عددًا من مقاييس المسافات المختلفة لحساب أقرب مجاور. من المقاييس الشائعة المستخدمة في معالجة اللغة الطبيعية مقياس مسافة جيب التمام. من الناحية الرياضية، يتحدد «وجه التشابه» لجيب التمام بين المتجه أ والمتجه ب بالمعادلة التالية:

    بتعيين index_metric على جيب التمام، يستخدم Amazon SageMaker تلقائيًا تشابه جيب التمام لحساب أقرب مجاورات. المسافة الافتراضية هي قاعدة L2 وهي المسافة القياسية في Euclidean. لاحظ أنه في عملية النشر، لا يتم دعم جيب التمام إلا لنوع الفهرس faiss.IVFFlat وليس طريقة الفهرسة faiss.IVFPQ.

    وستظهر النتيجة التالية في الوحدة الطرفية.

    Completed - Training job completed

    تمت العملية بنجاح! ونظرا لأنك تريد من هذا النموذج أن يعرض أقرب المجاورات بناءً على موضوع اختبار معين، فيجب نشره في صورة نقطة نهاية مستضافة ومباشرة.

  • الخطوة 2. نشر نموذج توصية المحتوى

    مثلما فعلت في نموذج NTM، حدد وظيفة المساعد التالية لنموذج k-NN لتشغيل نقطة النهاية. في وظيفة المساعد، يطلب رمز القبول applications/jsonlines; verbose=true من نموذج k-NN أن يعرض جميع مسافات جيب التمام بدلًا من أقرب مجاور فقط. لإنشاء محرك التوصيات، يجب الحصول على أفضل اقتراحات k حسب النموذج الذي تريد أن تعين له معلمة verbose على القيمة صحيح، بدلًا من القيمة الافتراضية «خطأ».

    انسخ والصق التعليمة البرمجية التالية في دفتر الملاحظات الخاص بك واختر تشغيل.

    def predictor_from_estimator(knn_estimator, estimator_name, instance_type, endpoint_name=None): 
        knn_predictor = knn_estimator.deploy(initial_instance_count=1, instance_type=instance_type,
                                            endpoint_name=endpoint_name,
                                            accept="application/jsonlines; verbose=true")
        knn_predictor.content_type = 'text/csv'
        knn_predictor.serializer = csv_serializer
        knn_predictor.deserializer = json_deserializer
        return knn_predictor
    import time
    
    instance_type = 'ml.m4.xlarge'
    model_name = 'knn_%s'% instance_type
    endpoint_name = 'knn-ml-m4-xlarge-%s'% (str(time.time()).replace('.','-'))
    print('setting up the endpoint..')
    knn_predictor = predictor_from_estimator(knn_estimator, model_name, instance_type, endpoint_name=endpoint_name)

    ثم قم بمعالجة مسبقة لبيانات الاختبار بحيث يمكنك تشغيل الاستدلالات.

    انسخ والصق التعليمة البرمجية التالية في دفتر الملاحظات الخاص بك واختر تشغيل.

    def preprocess_input(text):
        text = strip_newsgroup_header(text)
        text = strip_newsgroup_quoting(text)
        text = strip_newsgroup_footer(text)
        return text    
        
    test_data_prep = []
    for i in range(len(newsgroups_test)):
        test_data_prep.append(preprocess_input(newsgroups_test[i]))
    test_vectors = vectorizer.fit_transform(test_data_prep)
    
    test_vectors = np.array(test_vectors.todense())
    test_topics = []
    for vec in test_vectors:
        test_result = ntm_predictor.predict(vec)
        test_topics.append(test_result['predictions'][0]['topic_weights'])
    
    topic_predictions = []
    for topic in test_topics:
        result = knn_predictor.predict(topic)
        cur_predictions = np.array([int(result['labels'][i]) for i in range(len(result['labels']))])
        topic_predictions.append(cur_predictions[::-1][:10])       
    

    في الخطوة الأخيرة من هذه الوحدة، تستكشف نموذج توصيات المحتوى.

  • الخطوة 3. استكشاف نموذج توصيات المحتوى

    بما أنك حصلت على التنبؤات، يمكنك تخطيط توزيعات الموضوع الخاصة بموضوعات الاختبار مقارنةً بأقرب موضوعات k يوصي بها نموذج k-NN.

    انسخ والصق التعليمة البرمجية التالية في دفتر الملاحظات الخاص بك واختر تشغيل.

    # set your own k.
    def plot_topic_distribution(topic_num, k = 5):
        
        closest_topics = [predictions[labeldict[x]] for x in topic_predictions[topic_num][:k]]
        closest_topics.append(np.array(test_topics[topic_num]))
        closest_topics = np.array(closest_topics)
        df = pd.DataFrame(closest_topics.T)
        df.rename(columns ={k:"Test Document Distribution"}, inplace=True)
        fs = 12
        df.plot(kind='bar', figsize=(16,4), fontsize=fs)
        plt.ylabel('Topic assignment', fontsize=fs+2)
        plt.xlabel('Topic ID', fontsize=fs+2)
        plt.show()
    

    شغّل التعليمة البرمجية التالية لتخطيط توزيع الموضوع:

    plot_topic_distribution(18)
    

    الآن، جرّب بعض الموضوعات الأخرى. شغّل خانات التعليمة البرمجية التالية:

    plot_topic_distribution(25)
    plot_topic_distribution(5000)

    قد تبدو تخطيطاتك مختلفة قليلًا بناءً على عدد الموضوعات (NUM_TOPICS) التي تختارها. ولكن بوجه عام، هذه المخططات توضح أن توزيع الموضوعات لمستندات أقرب المجاورات التي تستخدم تشابه جيب التمام عن طريق نموذج k-NN تشبه إلى حدٍ ما توزيع الموضوعات لمستند الاختبار الذي يتم إدراجه في النموذج.

    تقول النتائج أن نموذج k-NN قد يكون طريقة جيدة لإنشاء نظام استرداد معلومات قائم على الدلالات اللفظية عن طريق إدماج المستندات في متجهات الموضوع أولاً ثم استخدام نموذج k-NN ليخدم التوصيات.


تهانينا! في هذه الوحدة، تدربت على نموذج توصية المحتوى وقمت بنشره واستكشافه.

في الوحدة التالية، ستقوم بتنظيف الموارد التي استخدمتها في هذا التمرين المعملي.