速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

使用 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:03754
用户头像

发布了 1850 篇内容, 共 119.0 次阅读, 收获喜欢 78 次。

关注

评论

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

2021MLB CUP 青少年棒球公开赛·秋季赛泉城开战,DC试训带来新希望

科技新消息

Python代码阅读(第39篇):获取列表出现频率最高的元素

Felix

Python 编程 Code Programing 阅读代码

随便讲讲Python图像处理库PIL的使用

Regan Yue

Python 10月月更

ffmpeg 开发环境搭建

webrtc developer

ffmpeg

网络安全—如何预防常见的API漏洞

郑州埃文科技

数据中心 API IP地址

架构师训练营模块一作业

CheneyWang

架构实战营

算力挖矿系统开发内容(现成案例)

面试官:Java从编译到执行,发生了什么?

Java 架构 面试 JVM

redis在微服务领域的贡献

Java redis 面试 微服务 后端

区块链钱包系统软件开发详情(搭建案例)

模块一作业:微信业务架构图与学生管理系统毕设架构设计

deng

架构实战营

👊 【Spring 技术特性】SpringMVC集成Java Bean Validation实现参数检验功能(上)

洛神灬殇

spring Bean Validation 10月月更

五个维度打造研发管理体系

车江毅

研发管理 软件开发 技术管理 研发体系 研发团队

第 19 章 -《Linux 一学就会》- shell脚本的基础

学神来啦

Linux Shell linux一学就会 linux基础

从瀑布式到DevOps,开发流程经历了什么?

SoFlu软件机器人

DevOps 敏捷开发

多币种钱包系统开发介绍(现成)

Vue进阶(幺肆零):vue 新增数组或对象更新后,视图不更新的解决方案

No Silver Bullet

Vue 10月月更

2021MLB CUP 青少年棒球公开赛·秋季赛从济南拉开战幕

科技新消息

区块链数字货币钱包系统开发公司(案例)

淘宝小部件:全新的开放卡片技术!

阿里巴巴终端技术

小程序 ios android 淘宝 客户端开发

区块链加密货币钱包软件系统开发公司(现成)

锁仓挖矿软件系统开发模板(源码)

区块链多币种钱包软件系统开发费用(案例)

020云原生之Pod介绍

穿过生命散发芬芳

云原生 10月月更

区块链数字钱包系统软件开发详情(搭建)

阿里内部珍藏版:SpringCloud Alibaba第三版(全彩手册)

Java 架构 面试 微服务 大厂

2021年10月国产数据库排行榜:达梦反超OceanBase夺榜眼,TDSQL实现“四连增”,数据生态加速建设

墨天轮

opengauss TiDB oceanbase 国产数据库 达梦

带你掌握不同平台下,探索JDK源码所需的native方法

华为云开发者联盟

Java jdk 系统 native JDK代码

金九银十面试了3家大厂Java岗,我得到的知识总结

Java 程序员 架构 面试 大厂

架构实战营 模块一作业

felix

架构实战营

加密数字货币钱包软件系统开发详情(案例)

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