使用 Amazon SageMaker 构建语义内容推荐系统

训练和部署主题模型

在本模块中,您将使用内置的 Amazon SageMaker Neural Topic Model (NTM) 算法来训练主题模型。

Amazon SageMaker NTM 是一种无监督学习算法,旨在按主题整理文档语料库,这些主题中包含基于其统计分布的词语分组。例如,如果一篇文档中频繁出现 bike(自行车)、car(汽车)、train(火车)、mileage(里程)和 speed(速度)等词,那么该文档的主题很可能是“交通”。主题模型可用于根据检测到的主题对文档进行分类或总结,或根据主题相似性检索信息、推荐内容。NTM 从文档中学习到的主题被称为潜在表示,因为这些主题是从语料库中观察到的词语分布中推断出来的。主题的语义通常通过分析其中排名靠前的词语来推断。由于该方法是无监督的,因此只预先指定主题的数量,而不指定主题本身。此外,无法保证这些主题与人为分类文档的常用方式一致。

在接下来的步骤中,您将为训练作业指定 NTM 算法,指定模型的基础设施,设置超参数值以优化模型,然后运行模型。然后,将模型部署到由 Amazon SageMaker 管理的端点,以进行预测。

 时长

20 分钟

步骤 1:创建并运行训练作业

内置的 Amazon SageMaker 算法以 Docker 容器的形式存储在 Amazon Elastic Container Registry (Amazon ECR) 中。要训练模型,您首先需要在 Amazon ECR 中指定距离您所在区域最近的 NTM 容器的位置。

在 Notebook 实例中,将以下代码复制粘贴到一个新的代码单元格中,然后点击 Run(运行)。

import boto3
from sagemaker.amazon.amazon_estimator import get_image_uri
container = get_image_uri(boto3.Session().region_name, 'ntm')

Amazon SageMaker Python SDK 包含 sagemaker.estimator.Estimator 估计器。如果我们在自选的自定义 VPC(而非 Amazon VPC)中训练模型,该估计器允许您指定可能相关的基础设施(Amazon EC2 实例类型、实例数量、超参数、输出路径)和任何可选的安全相关设置(虚拟私有云 (VPC)、安全组等)。NTM 可以充分利用 GPU 硬件,通常在 GPU 上的训练速度比在 CPU 上快一个数量级。如果通信开销与计算时间相比较低,多 GPU 或多实例训练可以进一步提高训练速度,且提升幅度大致呈线性关系。

要创建 sagemaker.estimator.Estimator 类的实例,请将以下代码复制粘贴到一个新的代码单元格中,然后点击 Run(运行)。

sess = sagemaker.Session()
ntm = sagemaker.estimator.Estimator(container,
                                    role, 
                                    train_instance_count=2, 
                                    train_instance_type='ml.c4.xlarge',
                                    output_path=output_path,
                                    sagemaker_session=sess)

现在,您可以设置主题模型的超参数:

ntm.set_hyperparameters(num_topics=NUM_TOPICS, feature_dim=vocab_size, mini_batch_size=128, 
                        epochs=100, num_patience_epochs=5, tolerance=0.001)

对于数据通道,SageMaker 提供两种模式:

  • FullyReplicated(完全复制):所有数据文件都将复制到每个 worker。
  • ShardedByS3Key(按 S3 键分片):数据文件将分片到不同的 worker,即每个 worker 接收完整数据集的不同部分。

截止至本文撰写时,Amazon SageMaker Python SDK 默认对所有数据通道使用 FullyReplicated 模式。当使用多个 worker 时,此模式适用于验证(测试)通道,但对于训练通道效率较低。

在这种情况下,您希望每个 worker 遍历完整数据集的不同部分,以便在每个 epoch 内提供不同的梯度。您可以按如下方式将训练数据通道的分布模式指定为 ShardedByS3Key。

from sagemaker.session import s3_input
s3_train = s3_input(s3_train_data, distribution='ShardedByS3Key') 
ntm.fit({'train': s3_train, 'test': s3_val_data})

您应该会在终端中看到以下输出:

Completed - Training job completed

大功告成!您已经使用 NTM 算法训练了主题模型。

在下一步中,您将把模型部署到 Amazon SageMaker 托管服务。

步骤 2:部署主题模型

训练好的模型本身只是一个包含模型权重的 tar 文件,它本身不执行任何操作。为了让模型发挥作用并获得预测结果,您需要部署模型。

在 Amazon SageMaker 中部署模型有两种方式,具体取决于您希望如何生成推理结果:

  • 要一次获得一个推理结果,可以使用 Amazon SageMaker 托管服务设置一个持久端点。
  • 要对整个数据集进行推理,请使用 Amazon SageMaker Batch Transform(Amazon SageMaker 批量转换)。

本教程提供了这两种选项,您可以根据自己的使用场景选择最佳方法。

选项 A:使用 Amazon SageMaker 托管服务部署主题模型

使用 Amazon SageMaker 托管服务时,实时 HTTPS 端点位于 Amazon EC2 实例上,您可以向该实例传递有效负载并获得推理结果。

部署模型时,调用 sagemaker.estimator.Estimator 对象的 deploy 方法。调用 deploy 方法时,您需要指定用于托管端点的 ML 实例的数量和类型。

复制并粘贴以下代码,然后点击 Run(运行)来部署模型。

ntm_predictor = ntm.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge')

deploy 方法会创建可部署的模型,配置 Amazon SageMaker 托管服务端点,然后启动端点来托管模型。

要使用某个端点进行推理,您需要确保两点:第一,输入数据要序列化成训练后的模型能够读取的格式;第二,模型推理得出的输出结果要反序列化成人类可以直接读懂的格式。在下面的代码中,使用 csv_serializer 和 json_deserializer,将 CSV 格式的数据(作为向量)传递给模型,以生成 JSON 输出。

将以下代码复制粘贴到代码单元格中,然后点击 Run(运行)。

from sagemaker.predictor import csv_serializer, json_deserializer

ntm_predictor.content_type = 'text/csv'
ntm_predictor.serializer = csv_serializer
ntm_predictor.deserializer = json_deserializer

接下来,提取训练数据的主题向量,这些向量将在 K-NN 模型中使用。

将以下代码复制粘贴到一个新的代码单元格中,然后点击 Run(运行)。

predictions = []
for item in np.array(vectors.todense()):
    np.shape(item)
    results = ntm_predictor.predict(item)
    predictions.append(np.array([prediction['topic_weights'] for prediction in results['predictions']]))
    
predictions = np.array([np.ndarray.flatten(x) for x in predictions])
topicvec = train_labels[newidx]
topicnames = [categories[x] for x in topicvec]

大功告成!现在,您可以探索模型的输出了。

选项 B:使用 Batch Transform 部署主题模型

使用 Batch Transform,您可以一次对一批数据运行推理。Amazon SageMaker 将创建必要的计算基础设施,并在批处理作业完成后将其删除。

批量转换代码将从主题模型创建一个 sagemaker.transformer.Transformer 对象。然后,它调用该对象的 transform 方法来创建一个转换作业。创建 sagemaker.transformer.Transformer 对象时,您需要指定用于执行批量转换作业的实例数量和类型,以及在 Amazon S3 中存储推理结果的位置。

要以批处理作业的形式运行推理,请将以下代码复制粘贴到代码单元格中,然后点击 Run(运行)。

np.savetxt('trainvectors.csv',
           vectors.todense(),
           delimiter=',',
           fmt='%i')
batch_prefix = '20newsgroups/batch'

train_s3 = sess.upload_data('trainvectors.csv', 
                            bucket=bucket, 
                            key_prefix='{}/train'.format(batch_prefix))
print(train_s3)
batch_output_path = 's3://{}/{}/test'.format(bucket, batch_prefix)

ntm_transformer = ntm.transformer(instance_count=1,
                                  instance_type ='ml.m4.xlarge',
                                  output_path=batch_output_path
                                 )
ntm_transformer.transform(train_s3, content_type='text/csv', split_type='Line')
ntm_transformer.wait()

转换作业完成后,您可以使用以下代码将输出结果下载回本地 Notebook 实例进行检查。

!aws s3 cp --recursive $ntm_transformer.output_path ./
!head -c 5000 trainvectors.csv.out

大功告成!该模型将每个文档转换为 NUM_TOPICS 维的训练向量。现在,您可以探索主题模型了。

步骤 3:探索主题模型

探索模型输出的一种方法是使用 T-SNE 图来可视化生成的主题向量。T-SNE(t-Distributed Stochastic Neighbor Embedding,t 分布随机近邻嵌入)是一种非线性降维技术,旨在确保原始高维空间中最近邻之间的距离在生成的低维空间中得以保持。如果将维度设置为 2,它可以作为一种可视化工具,将主题向量在二维空间中可视化。

在 Jupyter Notebook 中,将以下代码复制粘贴到一个新的代码单元格中,然后点击 Run(运行)。

from sklearn.manifold import TSNE
time_start = time.time()
tsne = TSNE(n_components=2, verbose=1, perplexity=50, n_iter=5000)
tsne_results = tsne.fit_transform(predictions)
print('t-SNE done! Time elapsed: {} seconds'.format(time.time()-time_start))
tsnedf = pd.DataFrame()
tsnedf['tsne-2d-one'] = tsne_results[:,0]
tsnedf['tsne-2d-two'] = tsne_results[:,1]
tsnedf['Topic']=topicnames
plt.figure(figsize=(25,25))
sns.lmplot(
    x="tsne-2d-one", y="tsne-2d-two",
    hue='Topic',
    palette=sns.color_palette("hls", NUM_TOPICS),
    data=tsnedf,
    legend="full",
    fit_reg=False
)
plt.axis('Off')
plt.show()

TSNE 图应该展示一些大的主题簇,如下图所示。这种图可用于提取数据集中不同主题簇的数量。目前,NUM_TOPICS 设置为 30,但在 TSNE 图中,似乎有许多主题彼此靠得很近,可以合并成一个主题。归根结底,由于主题建模在很大程度上是一个无监督学习问题,您必须使用这类可视化方法来确定将数据集划分为多少个主题才是正确的。

尝试使用不同的主题数量,看看可视化结果会是什么样的。

总结

在本模块中,您从 Amazon ECR 中检索了 Amazon SageMaker Neural Topic Model (NTM) 算法。然后,您指定了算法特定的超参数,并提供了用于存储构件的 Amazon S3 存储桶。接下来,您使用 Amazon SageMaker 托管服务或 Batch Transform 将模型部署到端点。最后,您使用不同的主题数量探索了模型。

下一个模块中,您将训练并部署内容推荐模型。

训练并部署内容推荐模型