В этом модуле вы будете использовать встроенный в Amazon SageMaker алгоритм k-ближайших соседей (k-NN), чтобы обучить модель рекомендаций по контенту.

Алгоритм K-ближайших соседей (k-NN) в Amazon SageMaker – это непараметрический алгоритм контролируемого обучения на основе индексов, который можно использовать для задач классификации и регрессии. Для классификации этот алгоритм опрашивает k ближайших к цели точек и возвращает наиболее часто используемую метку их класса в качестве спрогнозированной метки. При решении проблем регрессии этот алгоритм извлекает среднее из спрогнозированных значений, возвращенных k ближайшими соседями.

Обучение с помощью алгоритма k-NN состоит из трех шагов: получение выборки, снижение размерности и построение индекса. При получении выборки размер исходного набора данных сокращается, чтобы его можно было уместить в памяти. При снижении размерности алгоритм уменьшает размерность свойств, чтобы сократить объем модели k-NN в памяти и задержку формирования логических выводов. Мы предоставляем два способа снижения размерности: случайная проекция и быстрое преобразование Джонсона – Линденштраусса. Обычно снижение размерности применяется к наборам данных высокой размерности (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 предоставляет несколько различных метрик дистанции для определения ближайших соседей. Одной из популярных метрик, которые используются в обработке естественного языка, является расстояние по косинусу. С точки зрения математики, «подобие» между двумя векторами A и B по косинусу задается следующим уравнением:

    Если для параметра index_metric задано значение COSINE, Amazon SageMaker автоматически использует подобие по косинусу для вычисления ближайших соседей. Стандартное расстояние – это L2-норма, которая является Евклидовым расстоянием. Обратите внимание, что на момент публикации значение COSINE поддерживается только для типа индекса faiss.IVFFlat, но не для метода индексирования faiss.IVFPQ.

    В терминале должны отобразиться указанные ниже выходные данные.

    Completed - Training job completed

    Готово! Поскольку требуется, чтобы эта модель возвращала ближайших соседей по заданной обучающей теме, вам потребуется развернуть ее как размещенную конечную точку в режиме реального времени.

  • Шаг 2. Развертывание модели рекомендаций по контенту

    Как и в случае с моделью NTM, определите следующую вспомогательную функцию для модели k-NN, чтобы запустить конечную точку. Во вспомогательной функции значение токена accept applications/jsonlines; verbose=true сообщает модели k-NN, что необходимо возвратить не только одно расстояние для ближайшего соседа, а все по косинусу. Чтобы создать движок рекомендаций, необходимо получить лучшие k прогнозов по модели, для которых требуется задать в параметре verbose значение true вместо значения по умолчанию false.

    Скопируйте приведенный ниже код, вставьте его в блокнот и нажмите Исполнить.

    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 для предоставления рекомендаций.


Поздравляем! В этом модуле вы обучили, развернули и исследовали модель рекомендаций по контенту.

В следующем модуле мы очистим ресурсы, которые использовали в этом курсе.