ในโมดูลนี้ คุณจะใช้อัลกอริทึม k-Nearest Neighbors (k-NN) ในตัวของ Amazon SageMaker เพื่อฝึกฝนโมเดลการแนะนำเนื้อหา

Amazon SageMaker K-Nearest Neighbors (k-NN) คืออัลกอริทึมการเรียนรู้แบบนอนพาราเมตริกอิงดัชนีที่มีผู้สอน ซึ่งสามารถใช้สำหรับงานด้านการแยกประเภทและการถดถอยได้ สำหรับการแยกประเภท อัลกอริทึมนี้จะสืบค้นจุดที่ใกล้เป้าหมายที่สุด k ตัว และส่งผลลัพธ์ที่ใช้บ่อยที่สุดของประเภทนั้นคืนกลับมาเป็นผลลัพธ์ที่คาดการณ์ สำหรับปัญหาด้านการถดถอย อัลกอริทึมนี้จะส่งกลับค่าเฉลี่ยของค่าที่คาดการณ์ซึ่งส่งคืนมาจากเพื่อนบ้านที่ใกล้ที่สุด k ตัว

การฝึกฝนด้วยอัลกอริทึม k-NN ประกอบด้วย 3 ขั้นตอน ได้แก่ การสุ่มตัวอย่าง การลดมิติ และการสร้างดัชนี การสุ่มตัวอย่างจะลดขนาดของชุดข้อมูลเริ่มต้นเพื่อให้พอดีกับหน่วยความจำ สำหรับการลดมิติ อัลกอริทึมนี้จะลดมิติคุณลักษณะของข้อมูลเพื่อลดฟุตพรินต์ของโมเดล k-NN ในหน่วยความจำและเวลาแฝงของการอนุมาน เรามีวิธีการลดมิติ 2 วิธี ได้แก่ การคาดคะเนเชิงสุ่มและการแปลงแบบ Johnson-Lindenstrauss ที่รวดเร็ว โดยทั่วไป คุณจะใช้การลดมิติสำหรับชุดข้อมูลที่มีมิติสูง (d >1000) เพื่อหลีกเลี่ยง “ปัญหาของมิติข้อมูล” ซึ่งเป็นอุปสรรคต่อการวิเคราะห์เชิงสถิติของข้อมูลที่จะมีน้อยลงเมื่อมิติข้อมูลเพิ่มขึ้น วัตถุประสงค์หลักของการฝึกฝน k-NN ก็คือการสร้างดัชนี ดัชนีจะช่วยเพิ่มประสิทธิภาพในการค้นหาระยะทางระหว่างจุดที่ยังไม่มีการระบุค่าหรือผลลัพธ์ของประเภท และจุดที่ใกล้ที่สุด k ตัวเพื่อใช้สำหรับการอนุมาน

ในขั้นตอนต่อไปนี้ คุณจะต้องกำหนดอัลกอริทึม k-NN สำหรับงานฝึกฝน ตั้งค่าไฮเปอร์พารามิเตอร์เพื่อปรับจูนโมเดล และเรียกใช้โมเดล จากนั้น คุณจะต้องปรับใช้โมเดลไปยังตำแหน่งข้อมูลที่จัดการโดย Amazon SageMaker เพื่อสร้างการคาดการณ์

ระยะเวลาที่ใช้ในการศึกษาโมดูล: 20 นาที


  • ขั้นตอนที่ 1 สร้างและเรียกใช้งานฝึกฝน

    ในโมดูลก่อนหน้านี้ คุณได้สร้างเวกเตอร์หัวข้อเอาไว้ ในโมดูลนี้ คุณจะต้องสร้างและปรับใช้โมเดลการแนะนำเนื้อหาซึ่งเก็บดัชนีของเวกเตอร์หัวข้อเอาไว้

    อันดับแรก ให้สร้างดิกชันนารีซึ่งเชื่อมโยงผลลัพธ์แบบสลับเข้ากับผลลัพธ์ดั้งเดิมในข้อมูลการฝึกฝน ในโน้ตบุ๊กของคุณ ให้คัดลอกและวางโค้ดต่อไปนี้แล้วเลือก Run (เรียกใช้)

    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)
    

    ขณะที่งานฝึกฝนกำลังดำเนินอยู่ ให้พิจารณาพารามิเตอร์ในฟังก์ชันตัวช่วย

    อัลกอริทึม Amazon SageMaker k-NN มีตัววัดระยะทางที่แตกต่างกันจำนวนมากสำหรับการคำนวณเพื่อนบ้านที่ใกล้ที่สุด หนึ่งในตัววัดยอดนิยมที่ใช้ในการประมวลผลภาษาธรรมชาติก็คือระยะทางแบบโคไซน์ ในทางคณิตศาสตร์ “ความคล้ายคลึง” โคไซน์ระหว่างสองเวกเตอร์ A กับ B ได้มาจากสมการต่อไปนี้

    เมื่อตั้งค่า index_metric เป็น COSINE แล้ว Amazon SageMaker จะใช้ความคล้ายคลึงโคไซน์สำหรับการคำนวณเพื่อนบ้านที่ใกล้ที่สุดโดยอัตโนมัติ ระยะทางตามค่าเริ่มต้นคือ L2 norm ซึ่งเป็นระยะทางแบบยูคลิดมาตรฐาน โปรดทราบว่าเมื่อเผยแพร่ ระบบจะสนับสนุน COSINE เฉพาะสำหรับดัชนีประเภท faiss.IVFFlat เท่านั้น และไม่สนับสนุนการทำดัชนีด้วยวิธี faiss.IVFPQ

    คุณควรจะเห็นผลลัพธ์ต่อไปนี้ในเทอร์มินัลของคุณ

    Completed - Training job completed

    สำเร็จ! เนื่องจากคุณต้องการให้โมเดลนี้ส่งค่าเพื่อนบ้านที่ใกล้ที่สุดกลับมาโดยมีหัวข้อการทดสอบที่เจาะจง คุณจึงจำเป็นต้องปรับใช้โมเดลเป็นตำแหน่งข้อมูลที่โฮสต์แบบสด

  • ขั้นตอนที่ 2 ปรับใช้โมเดลการแนะนำเนื้อหา

    เช่นเดียวกับที่ทำในโมเดล NTM ให้ระบุฟังก์ชันตัวช่วยต่อไปนี้สำหรับโมเดล k-NN เพื่อเปิดใช้ตำแหน่งข้อมูล ในฟังก์ชันตัวช่วย โทเค็นยอมรับ applications/jsonlines; verbose=true จะบอกให้โมเดล k-NN ส่งกลับระยะทางแบบโคไซน์ทั้งหมดแทนที่จะส่งเพียงเพื่อนบ้านที่ใกล้ที่สุด หากต้องการสร้างเอ็นจินคำแนะนำ คุณจะต้องรับการแนะนำหลัก k ตัวจากโมเดล ซึ่งคุณจะต้องตั้งค่าพารามิเตอร์ verbose ให้เป็น true (จริง) แทนที่จะเป็น false (เท็จ) ตามค่าเริ่มต้น

    คัดลอกและวางโค้ดต่อไปนี้ลงในโน้ตบุ๊กของคุณแล้วเลือก Run (เรียกใช้)

    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)

    ถัดไป ให้เตรียมข้อมูลทดสอบเพื่อให้คุณสามารถเรียกใช้การอนุมานได้

    คัดลอกและวางโค้ดต่อไปนี้ลงในโน้ตบุ๊กของคุณแล้วเลือก Run (เรียกใช้)

    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 ได้

    คัดลอกและวางโค้ดต่อไปนี้ลงในโน้ตบุ๊กของคุณแล้วเลือก Run (เรียกใช้)

    # 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 เพื่อให้การแนะนำ


ขอแสดงความยินดี! ในโมดูลนี้ คุณได้ฝึกฝน ปรับใช้ และสำรวจโมเดลการแนะนำเนื้อหาเรียบร้อยแล้ว

ในโมดูลถัดไป คุณจะต้องล้างข้อมูลทรัพยากรที่คุณใช้ในแล็บนี้