最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

使用 AWS Sagemaker 训练因子分解机模型并应用于推荐系统

  • 2019-10-08
  • 本文字数:6554 字

    阅读完需:约 22 分钟

使用AWS Sagemaker训练因子分解机模型并应用于推荐系统

使用 AWS Sagemaker 系列文章:

第一篇:使用 AWS Sagemaker 训练因子分解机模型并应用于推荐系统(本博文)


第二篇:使用 AWS Sagemaker 部署的终端节点进行推荐预测的常用场景


————


在线服务和应用中,经常遇到需要对用户历史行为进行分析并预测,典型的案例如页面点击预测及推荐系统。这些案例的特点是历史数据集非常庞大,而且大多数情况,数据集是稀疏的。让我们以电影点评网站为例来理解稀疏数据集。在电影点评网站中,拥有大量的用户以及大量的电影,然而几乎不可能实现每个用户对每个电影都进行点评或打分。因此如果我们以用户为行,以电影为列,构建一个表格,对该用户点评过的电影单元格置 1,未点评过的置 0,我们可以发现,该表格中绝大部分数据都将是 0。这就是稀疏数据集的典型例子。


针对稀疏数据集,因子分解机(Factorization Machines,FM)是比较有效的算法模型。



直观来说因子分解机可以考虑为由用户(User)为行、电影(Movie)为列构成的矩阵 R 可以表示为一个用户(User)为行、K 列特征构成的矩阵 P 与电影(Movie)为行、K 列特征构成的矩阵 Q 的转置的乘积。其中的 K 即潜藏特征值,可以将他理解为用户与电影之间的关系。在因子分解机中,这一值是可以自行设定的。算法的主要目的就是计算出 P 和 Q 矩阵,并使 P 与 QT 的乘积尽可能与 R 一致。


本次实验采用国内用户对大量国内外电影的评论作为训练数据集,利用 AWS SageMaker 自带的因子分解机算法构建模型,通过 SageMaker 的超参调优服务观察参数调整对模型表现的影响。最后,以实际应用中经常会遇到的用法演示模型的预测结果。本次实验全部使用 Python3.6 完成,在 SageMaker 中选用 conda_python3 的 Kernel。

数据准备阶段

本次数据总量大约为 396 万条,用户数 49 万,电影数 3 万多。考虑到演示的目的和运算的效率,训练模型时使用其中 10 万条数据的采样。


In [3]:


df_all = pd.read_csv('all_movie_rates_noblank.csv')print(df_all.shape)print(df_all['UserId'].nunique())print(df_all['MovieID'].nunique())
复制代码


(3963891, 3)


490790


33345


首先我们对数据进行基本的观察。可以看到这 10 万条数据包含 53902 个用户和 26004 部电影。随后我们对数据集进行训练集和测试集的拆分,这里采用训练数据:测试数据 = 4:1 的比例进行拆分。


In [4]:


df=pd.read_csv('all_movie_rates_100k.csv')print(df.shape)print(df['UserId'].nunique())print(df['MovieID'].nunique())
df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)print(df_train.shape, df_test.shape)
print(df_train.head(10))print(df_test.head(10))(107029, 3)
复制代码


53902


26004


(85623, 3) (21406, 3)


MovieID Rate UserId


63287 1296827 10 BloodzBoi


73804 3564327 6 LadyHoney


76527 6874441 8 49886917


71411 3152563 8 feathercat


64499 2004250 6 jingtianwst83


42130 3230459 6 funni


88502 3313801 6 chrisocean


79349 3072140 0 lala1123


21431 2053746 6 145992805


39240 1464338 8 HeroineDaode


MovieID Rate UserId


44496 26304167 8 152833029


11855 1299900 8 leonah


13955 26085750 2 49298107


27112 4202982 8 Kylin-2015


28103 4739952 10 likong


53598 3443393 4 3832465


65338 2052363 6 1926472


1116 6129707 8 vero_nicat


38854 26841337 2 158039357


78721 1307026 8 TowaErio

为用户和电影分别建立字典(Python Dictionary)

数据集中的用户 ID 和电影 ID 均为随机字符串,为了方便我们后续建立有序矩阵以及模型训练后预测结果的数据对应,我们首先为用户和电影分别建立由 0 开始的 index 序列,并使其与 ID 字符串对应。


In [5]:


filename = 'all_movie_rates_100k.csv'user_number = 53902movie_number = 26004
def createIDtoIndexDict(filename, user_number, movie_number): u_Dict = {} m_Dict = {} i = 0 m = 0 with open(filename, 'r') as f: sample = csv.reader(f, delimiter=',') for MovieID, Rate, UserId in sample: if UserId == 'UserId': continue else: if UserId not in u_Dict.keys(): u_Dict[UserId] = i i = i+1 if MovieID not in m_Dict.keys(): m_Dict[MovieID] = m m = m+1 return u_Dict, m_Dict u_Dict, m_Dict = createIDtoIndexDict(filename, user_number, movie_number)
复制代码

建立稀疏矩阵(Sparse Matrix)和标签向量(Label Vector)

因子分解机的训练是针对稀疏矩阵的,因此我们要将数据集中电影、评分、用户的序列转为稀疏矩阵,并根据用户评分的结果生成标签向量。我们使用 Python Scipy 模块中的 lil_matrix 来构建。


生成的矩阵应当是每一个用户 ID 作为单独一列、每一部电影在所有用户列之后也作为单独一列,针对原数据集中每行的数据,在对应的用户列和电影列置 1。标签向量以用户评分为基准,我们设定用户评分大于等于 6 的为“喜爱”,并在对应的标签向量位置置 1,反之为“不喜爱”,标签向量相应位置置 0。


训练集和测试集均进行同样的操作。


df_train.to_csv('100k_train.csv', index=False, encoding="utf_8_sig")df_test.to_csv('100k_test.csv', index=False, encoding="utf_8_sig")
columns = user_number+movie_numberdef loadDataset(filename, lines, columns): X = scipy.sparse.lil_matrix((lines, columns)).astype('float32') Y = [] line = 0 with open (filename, 'r') as f: sample = csv.reader(f, delimiter=',') for MovieID, Rate, UserId in sample: if UserId == 'UserId': continue else: X[line, u_Dict[UserId]] = 1 X[line, user_number+m_Dict[MovieID]] = 1 if Rate == 'Rate' or int(Rate) < 6: Y.append(0) else: Y.append(1) line=line+1
Y=np.array(Y).astype('float32') print(X.shape) print(Y.shape) return X, Y
复制代码


In [222]:


X_train, Y_train = loadDataset('100k_train.csv', df_train.shape[0], columns)X_test, Y_test = loadDataset('100k_test.csv', df_test.shape[0], columns)print(X_train.shape, X_test.shape)print(Y_train.shape, Y_test.shape)
复制代码


(85623, 79906)


(85623,)


(21406, 79906)


(21406,)


(85623, 79906) (21406, 79906)


(85623,) (21406,)


我们获得了训练集为 85623✖️79906 的矩阵,训练标签向量为 85263 元素;测试集为 21406✖️79906 矩阵,其标签向量为 21406 元素。

转换稀疏矩阵为 protobuf 格式,并保存到 S3

稀疏矩阵中绝大多数元素均为 0,如果直接保存稀疏矩阵,会占用大量的存储空间,因此我们将其转为 protobuf 格式的数据,并保存到 S3。


In [224]:


bucket = 'movie-recommendation-demo-raw-data'prefix = 'sagemaker/movie-recommendation'train_key      = 'train.protobuf'train_prefix   = '{}/{}'.format(prefix, 'train')test_key       = 'test.protobuf'test_prefix    = '{}/{}'.format(prefix, 'test')output_prefix  = 's3://{}/{}/output'.format(bucket, prefix)
def writeDatasetToProtobuf(X, Y, bucket, prefix, key): import io,boto3 import sagemaker.amazon.common as smac buf = io.BytesIO() smac.write_spmatrix_to_sparse_tensor(buf, X, Y) buf.seek(0) print(buf) obj = '{}/{}'.format(prefix, key) boto3.resource('s3').Bucket(bucket).Object(obj).upload_fileobj(buf) print('Wrote dataset: {}/{}'.format(bucket,obj)) return 's3://{}/{}'.format(bucket,obj) train_data = writeDatasetToProtobuf(X_train, Y_train, bucket, train_prefix, train_key) test_data = writeDatasetToProtobuf(X_test, Y_test, bucket, test_prefix, test_key)
print(train_data)print(test_data)print('Output: {}'.format(output_prefix))<_io.BytesIO object at 0x7f99a8b8e1a8>
Wrote dataset: movie-recommendation-demo-raw-data/sagemaker/movie-recommendation/train/train.protobuf
<_io.BytesIO object at 0x7f99a8b8e1a8>
Wrote dataset: movie-recommendation-demo-raw-data/sagemaker/movie-recommendation/test/test.protobuf
s3://movie-recommendation-demo-raw-data/sagemaker/movie-recommendation/train/train.protobuf
s3://movie-recommendation-demo-raw-data/sagemaker/movie-recommendation/test/test.protobuf
Output: s3://movie-recommendation-demo-raw-data/sagemaker/movie-recommendation/output
复制代码


程序输出中 Output 的内容是模型训练完成后,保存模型代码的位置。

FM 模型训练

FM 是 SageMaker 自带的算法之一,因此通过 SageMaker 训练模型非常容易。首先我们需要引入 SageMaker 的 SDK,并建立 SageMaker 的 session、定义位于该 Region 的因子分解机算法 Container 以及获取 SageMaker 的运行角色。


In [225]:


from sagemaker import get_execution_rolefrom sagemaker.amazon.amazon_estimator import get_image_uriimport sagemakersess = sagemaker.Session()
role = get_execution_role()container = get_image_uri(boto3.Session().region_name, 'factorization-machines')
复制代码


随后我们定义 FM 训练需要的一些参数。首先是环境参数,包括之前定义好的 Container、角色、输出位置和 session、还包括训练使用的 EC2 实例,本例中采用“ml.c4.xlarge”来训练。


之后,我们需要定义 FM 算法的超参(Hyperparameters)。在本例中特征列为用户数与电影数的总和 79906、预测方式为二分类(即结果为判断“喜爱”或是“不喜爱”)、最小批量为 1000、epoch 时期为 50 次。其中 num_factors 即为在算法介绍中提到的潜藏特征 K 的数量,根据 SageMaker 官方文档的说明,建议在 2-1000 之间,通常 64 为最优值,因此,我们也设为 64。


最后为模型提供训练集和测试集在 S3 中的位置,训练就开始了。


In [226]:


fm = sagemaker.estimator.Estimator(container,                                   role,                                    train_instance_count=1,                                    train_instance_type='ml.c4.xlarge',                                   output_path=output_prefix,                                   sagemaker_session=sess)fm.set_hyperparameters(feature_dim=79906,                      predictor_type='binary_classifier',                      mini_batch_size=1000,                      num_factors=64,                      epochs=50)
fm.fit({'train': train_data, 'test':test_data})
复制代码


INFO:sagemaker:Creating training-job with name: factorization-machines-2018-12-18-03-18-50-388


2018-12-18 03:18:50 Starting – Starting the training job…


2018-12-18 03:18:56 Starting – Launching requested ML instances……


2018-12-18 03:19:58 Starting – Preparing the instances for training…


2018-12-18 03:20:45 Downloading – Downloading input data…


2018-12-18 03:20:55 Training – Downloading the training image…


Docker entrypoint called with argument(s): train


[12/18/2018 03:22:09 INFO 139830159329088] #quality_metric: host=algo-1, test binary_classification_accuracy=0.736288890965


[12/18/2018 03:22:09 INFO 139830159329088] #quality_metric: host=algo-1, test binary_classification_cross_entropy=0.548373071499


[12/18/2018 03:22:09 INFO 139830159329088] #quality_metric: host=algo-1, test binary_f_1.000=0.84806072188


[2018-12-18 03:22:09.767] [tensorio] [info] data_pipeline_stats={“name”: “/opt/ml/input/data/test”, “epoch”: 1, “duration”: 366, “num_examples”: 22}


[2018-12-18 03:22:09.767] [tensorio] [info] data_pipeline_stats={“name”: “/opt/ml/input/data/test”, “duration”: 40228, “num_epochs”: 2, “num_examples”: 23}


#metrics {“Metrics”: {“totaltime”: {“count”: 1, “max”: 40280.484199523926, “sum”: 40280.484199523926, “min”: 40280.484199523926}, “setuptime”: {“count”: 1, “max”: 39.59202766418457, “sum”: 39.59202766418457, “min”: 39.59202766418457}}, “EndTime”: 1545103329.767301, “Dimensions”: {“Host”: “algo-1”, “Operation”: “training”, “Algorithm”: “factorization-machines”}, “StartTime”: 1545103329.299489}
复制代码


[2018-12-18 03:22:09.784] [tensorio] [info] data_pipeline_stats={“name”: “/opt/ml/input/data/train”, “epoch”: 50, “duration”: 1287, “num_examples”: 86}


[2018-12-18 03:22:09.784] [tensorio] [info] data_pipeline_stats={“name”: “/opt/ml/input/data/train”, “duration”: 39923, “num_epochs”: 51, “num_examples”: 4301}


Billable seconds: 92


模型训练完成了。在模型训练结束后的总结中,我们可以看到几个重要的指标:


  • 模型训练计费时间 92 秒,所以并不会花很多钱;

  • 模型的二分准确度为 73.62%

  • 接下来,我们考虑一下应用 SageMaker 的超参调优(Hyperparameters Tuning)来尝试其他的超参设置是否可以获得更好的二分准确度。SageMaker 的超参调优可以通过 SageMaker 的 Console 直接配置完成。简单来讲,就是首先设定目标,本例中我们希望最大化(Maximize)模型二分准确度。之后给予可调参数的变动范围,本例中我们希望测试 mini batch size 和 epochs 的设置是否可以提升结果表现。最后定义训练集、测试集、算法的相应位置,以及优化任务运行的次数(最大为 100),即可开始。


当优化任务全部运行完成后,我们可以获得表现最好的模型的数据,如图



在这一参数配置下,模型的二分准确度提升为 76.2%。应用这一超参配置训练模型,并部署为 Endpoint。Endpoint 可以理解为模型基于 http 访问的 API 接口,有了 Endpoint 就可以进行预测服务了。


In [227]:


fm.set_hyperparameters(feature_dim=79906,                      predictor_type='binary_classifier',                      mini_batch_size=200,                      num_factors=64,                      epochs=134)In [228]:
fm_predictor = fm.deploy(initial_instance_count=1, instance_type='ml.t2.medium')INFO:sagemaker:Creating model with name: factorization-machines-2018-12-18-05-56-31-040
INFO:sagemaker:Creating endpoint with name factorization-machines-2018-12-18-05-47-26-108
—————————————————————–!
复制代码


我们的模型部署完成,Endpoint 名称为“factorization-machines-2018-12-18-05-47-26-108”。之后我们可以通过这个名称来调用 Endpoint 完成预测任务。


后续我们会继续利用已部署的终端节点 Endpoint 对常见的应用场景进行预测。


使用 AWS Sagemaker 系列文章:


第一篇:使用AWS Sagemaker训练因子分解机模型并应用于推荐系统(本博文)


第二篇:使用AWS Sagemaker部署的终端节点进行推荐预测的常用场景


————


作者介绍:


崔辰


AWS 大中华区创新中心技术业务拓展经理。加入 AWS 之前,崔辰在中国惠普、IBM、微软以及海航科技等公司担任过售前技术顾问、市场经理和战略合作经理等职务。在 10 多年的科技领域工作经历中,崔辰服务过众多企业级客户。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/aws-sagemaker-system-recommend-use/


2019-10-08 10:03634
用户头像

发布了 1835 篇内容, 共 91.9 次阅读, 收获喜欢 73 次。

关注

评论

发布
暂无评论
发现更多内容

Vue 组件如何在设置 Props

devpoint

Vue Vue3 InfoQ极客传媒15周年庆

软件、硬件、生态齐发力,英特尔夯实云计算基石

科技之家

InfluxDB 时间线简析

观测云

观测云产品更新|观测云计费更新;新增 Jenkins CI 可观测;新增自定义查看器图表同步搜索等

观测云

Hoo研究院 | OlympusDao调研报告

区块链前沿News

DAO Hoo 算法稳定

AQUANEE尚处初期,已获币安等顶尖机构青睐

BlockChain先知

一文搞懂│http 和 https 的通信过程及区别

https 安全 HTTP 通信 6月月更

行泊一体方案「换道超车」,百度担当汽车智能化风向标

百度开发者中心

华为云AppCube零门槛搭建5G消息服务号

乌龟哥哥

6月月更

学生管理系统架构设计

yuansteel

应用实践 | 物易云通基于 Apache Doris 的实时数据仓库建设

SelectDB

数据库 架构 最佳实践 Doris MySQL 数据库

DevEco Studio强大的预览功能让开发效率大大提升!

HarmonyOS开发者

HarmonyOS

投稿开奖丨轻量应用服务器征文活动(4月)奖励公布

阿里云弹性计算

Hexo 防火墙 SSL证书 CDN加速 安全组

OpenKruise v1.2:新增 PersistentPodState 实现有状态 Pod 拓扑固定与 IP 复用

阿里巴巴云原生

阿里云 云原生 开源项目

架构实战营第三模块课后作业

Geek_53787a

课后总结

1.4 宏观/中观/微观架构(连载)

凌晞

架构 架构设计 架构设计实战

架构设计-外包学生管理系统

Roy

架构实战营

InfoQ 极客传媒 15 周年庆征文|国产自研数据库GaussDB(DWS)架构详解【高斯数据库】

恒山其若陋兮

架构 InfoQ极客传媒15周年庆 GaussDB架构

【前端之路】react框架学习

恒山其若陋兮

React 6月月更

关于并发和并行,Go和Erlang之父都弄错了?

OneFlow

并发 并行

InfoQ 极客传媒 15 周年庆征文|纯 CSS 画一张生日贺卡祝 InfoQ 生日快乐

1_bit

前端 热门活动 InfoQ极客传媒15周年庆

百度APP视频播放中的解码优化

百度开发者中心

leetcode 126. Word Ladder II 单词接龙 II(困难)

okokabcd

LeetCode 搜索 算法与数据结构

优酷弹幕穿人「渲染技术」揭秘

阿里巴巴文娱技术

工程能力 音视频开发 渲染

API 网关 Apache APISIX 在 Amazon Graviton3 上的安装与性能测试

亚马逊云科技 (Amazon Web Services)

apisix;Tech 专栏

python偏函数

红毛丹

Python 6月月更

程序猿必备的数电知识,快来看看你掌握多少!(建议收藏)

孤寒者

进制转换 数电 常见进制

数字化时代做知识管理的最佳实践方式

小炮

如何保证设计出合理架构 - 作业

阿拉阿拉幽幽

AQUANEE尚处初期,已或币安等顶尖机构青睐

西柚子

学生管理系统详细架构

intelamd

使用AWS Sagemaker训练因子分解机模型并应用于推荐系统_语言 & 开发_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章