Dans ce module, vous utilisez l'algorithme intégré Amazon SageMaker k-Nearest Neighbors (k-NN) pour entraîner le modèle de recommandation de contenu.

Amazon SageMaker K-Nearest Neighbors (k-NN) est un algorithme d'apprentissage supervisé non paramétrique, basé sur un index, qui peut être utilisé pour les tâches de classification et de régression. Pour la classification, l'algorithme interroge les k points les plus proches de la cible et renvoie l'étiquette la plus fréquemment utilisée de leur classe comme étiquette prédite. Pour les problèmes de régression, l'algorithme renvoie la moyenne des valeurs prédites renvoyées par les voisins les plus proches de k.

L'entraînement avec l'algorithme k-NN comporte trois étapes : l'échantillonnage, la réduction de la dimension et la construction de l'index. L'échantillonnage réduit la taille de l'ensemble de données initial afin qu'il tienne dans la mémoire. Pour la réduction de la dimension, l'algorithme diminue la dimension caractéristique des données afin de réduire l'empreinte du modèle k-NN en mémoire et la latence d'inférence. Nous proposons deux méthodes de réduction des dimensions : la projection aléatoire et la transformation rapide Johnson-Lindenstrauss. En règle générale, nous utilisons la réduction dimensionnelle pour les ensembles de données de grande dimension (d >1000) afin d'éviter la « malédiction de la dimensionnalité » qui perturbe l'analyse statistique des données qui deviennent de plus en plus clairsemées au fur et à mesure que les dimensions augmentent. L'objectif principal de l'entraînement de l'algorithme k-NN est de construire l'index. L'index permet les recherches efficaces de distances entre les points dont les valeurs ou les étiquettes de classe n'ont pas encore été déterminées et les points les plus proches de k à utiliser pour l'inférence.

Dans les étapes suivantes, vous spécifiez votre algorithme k-NN pour la tâche d'entraînement, définissez les valeurs des hyperparamètres pour optimiser le modèle et exécutez le modèle. Ensuite, vous déployez le modèle sur un point de terminaison géré par Amazon SageMaker pour effectuer des prédictions.

Durée du module : 20 minutes


  • Étape 1. Créer et exécuter la tâche d'entraînement

    Dans le module précédent, vous avez créé des vecteurs de rubrique. Dans ce module, vous créez et déployez le module de recommandation de contenu qui conserve un index des vecteurs de rubrique.

    Tout d'abord, créez un dictionnaire qui relie les étiquettes mélangées aux étiquettes d'origine dans les données d'entraînement. Dans votre bloc-notes, copiez et collez le code suivant et choisissez Exécuter.

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

    Ensuite, stockez les données d'entraînement dans votre compartiment S3 à l'aide du code suivant :

    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))
    

    Utilisez ensuite la fonction d'assistance suivante pour créer un estimateur k-NN semblable à l'estimateur NTM que vous avez créé dans le module 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)
    

    Pendant l'exécution de la tâche d'entraînement, examinez soigneusement les paramètres de la fonction d'assistance.

    L'algorithme Amazon SageMaker k-NN propose un certain nombre de mesures de distance différentes pour déterminer la position des voisins les plus proches. Une mesure couramment utilisée dans le traitement du langage naturel est la distance cosinus. D'un point de vue mathématique, la « similarité » cosinus entre deux vecteurs A et B est donnée par l'équation suivante :

    En affectant à index_metric la valeur COSINE, Amazon SageMaker utilise automatiquement la similarité cosinus pour calculer la position des voisins les plus proches. La distance par défaut est la norme L2 qui est la distance euclidienne standard. Il convient de noter qu'au moment de la publication de ce document, COSINE est pris en charge pour le type d'index faiss.IVFFlat, mais pas pour la méthode d'indexation faiss.IVFPQ.

    La sortie suivante doit s'afficher sur votre terminal.

    Completed - Training job completed

    Bravo ! Étant donné que vous souhaitez que ce modèle renvoie les voisins les plus proches en fonction d'une rubrique de test particulière, vous devez le déployer en tant que point de terminaison hébergé en direct.

  • Étape 2. Déployer le modèle de recommandation de contenu

    Comme vous l'avez fait avec le modèle NTM, définissez la fonction d'assistance suivante pour le modèle k-NN afin de lancer le point de terminaison. Dans la fonction d'assistance, le jeton d'acceptation applications/jsonlines; verbose=true indique au modèle k-NN de renvoyer toutes les distances cosinus et non pas simplement le voisin le plus proche. Pour créer un moteur de recommandation, vous devez obtenir les principales suggestions k pour lesquelles vous devez affecter au paramètre verbose la valeur « true » et non pas la valeur par défaut « false ».

    Copiez et collez le code suivant dans votre bloc-notes et choisissez Exécuter.

    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)

    Ensuite, prétraitez les données de test afin de pouvoir exécuter des inférences.

    Copiez et collez le code suivant dans votre bloc-notes et choisissez Exécuter.

    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])       
    

    Dans la dernière étape de ce module, vous explorez votre modèle de recommandation de contenu.

  • Étape 3. Explorer le modèle de recommandation de contenu

    Maintenant que vous avez obtenu les prédictions, vous pouvez créer le graphique des distributions des rubriques de test par rapport aux rubriques k les plus proches recommandées par le modèle k-NN.

    Copiez et collez le code suivant dans votre bloc-notes et choisissez Exécuter.

    # 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()
    

    Exécutez le code suivant pour créer le graphique des distributions des rubriques :

    plot_topic_distribution(18)
    

    Essayez à présent d'autres rubriques. Exécutez les cellules de code suivantes :

    plot_topic_distribution(25)
    plot_topic_distribution(5000)

    Vos graphiques peuvent être quelque peu différents en fonction du nombre de rubriques (NUM_TOPICS) que vous choisissez. Dans l'ensemble, toutefois, ces graphiques montrent que la distribution de rubriques des documents les plus proches trouvés en utilisant la similarité Cosinus par le modèle k-NN est assez similaire à la distribution des rubriques du document de test que nous avons introduit dans le modèle.

    Les résultats suggèrent que k-NN peut être un bon moyen de créer un système de recherche d'informations basé sur la sémantique notamment en incorporant d'abord les documents dans des vecteurs de rubrique, puis en utilisant un modèle k-NN pour traiter les recommandations.


Félicitations ! Dans ce module, vous avez entraîné, déployé et exploré votre modèle de recommandation de contenu.

Dans le module suivant, vous allez nettoyer les ressources que vous avez utilisées dans cet exercice.