欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

手机商城系统搭建,电商商城系统搭建

终极管理员 知识笔记 82阅读

Tensorflow 2.12 简单智能商城商品推荐系统搭建 前言架构数据召回排序部署调用结尾

前言

基于 Tensorflow 2.12 搭建一个简单的智能商城商品推荐系统demo~
主要包含6个部分首先是简单介绍系统架构接着是训练数据收集、处理然后是召回模型、排序模型的搭建以及训练、导出等最后是部署模型提供REST API接口以及如何调用进行推荐。

Tensorflow是谷歌开源的机器学习框架可以帮助我们轻松地构建和部署机器学习模型。这里记录学习使用Tensorflow来搭建一个简单的智能商城商品推荐系统。
相关版本

python 3.1.0pandas 2.0.3tensorflow 2.12.0tensorflow-recommenders 0.7.3 架构

通常一个商城系统主要包含前端、后台前端包含网站、移动H5、APP、小程序、公众号等后台主要包含相关的API服务以及存储层等。
首先运营通过后台来录入商品信息、进行上架然后前端用户通过商城APP、小程序来浏览商品、搜索商品、进行下单购买、关注、收藏等。
一般系统中都会保留用户的这些操作数据例如浏览数据、搜索数据、下单数据等结合运营录入的商品数据通过定时Job生成用户的特征数据、商品的特征数据然后使用机器学习来找到用户喜欢的但又没有购买过的商品进行简单的AI推荐。
这里简单的画了一个图

数据

数据收集部分这里就不展开讲了相信现在大部分电商系统都有保留用户的一些搜索数据、下单数据等以及后台录入的商品数据通过一个定时JOB定时把数据查询出来导出为CSV文件即可作为后续进行模型训练的数据集。
当然没有也没关系可以写一个简单的Java方法、或者python方法随机生成数据写到CSV文件中。
这里先从最简单的开始只使用用户的下单数据以及商品数据来进行训练主要特征为用户Id、商品Id。

召回

主要是训练一个双塔召回模型根据用户的历史下单数据以及商品数据召回几百到数千条用户喜欢的商品基于内容的推荐。
召回模型搭建分为以下几部分
1、数据处理
2、模型搭建
3、模型训练
4、模型评估
5、模型导出

import pprintimport pandas as pdfrom typing import Dict, Textimport numpy as npimport tensorflow as tfimport tensorflow_recommenders as tfrs# -*- coding:utf-8 -*-# 使用pandas加载数据order_df  pd.read_csv(C:\\data\\python\\data\\blog\\order.csv, encodinggbk)pprint.pprint(order_df.shape)pprint.pprint(order_df.head(5))# 处理数据类型转为字符串order_df[user_id]  order_df[user_id].astype(str)order_df[product_id]  order_df[product_id].astype(str)# 将DataFramepandas转换为Datasettensorfloworder_df  tf.data.Dataset.from_tensor_slices(dict(order_df))for x in order_df.take(1).as_numpy_iterator():    pprint.pprint(x)# 准备嵌入向量的词汇表用户的user_ds  order_df.map(lambda x: {    user_id: x[user_id],    product_id: x[product_id]})# 准备嵌入向量的词汇表商品的product_ds  order_df.map(lambda x: x[product_id])# 随机数种子tf.random.set_seed(42)# 打乱数据shuffled  user_ds.shuffle(100_000, seed42, reshuffle_each_iterationFalse)# 切分数据分为训练数据以及验证数据train  shuffled.take(80_000)test  shuffled.skip(80_000).take(20_000)# 数据分片user_ids  user_ds.batch(1_000_000).map(lambda x: x[user_id])product_ids  product_ds.batch(1_000)# 获取唯一的用户Id列表以及商品列表unique_user_ids  np.unique(np.concatenate(list(user_ids)))pprint.pprint(unique_user_ids[:5])unique_product_ids  np.unique(np.concatenate(list(product_ids)))pprint.pprint(unique_product_ids[:5])# 将用户特征映射到用户embedding中查询塔user_model  tf.keras.Sequential([    tf.keras.layers.StringLookup(vocabularyunique_user_ids, mask_tokenNone),    tf.keras.layers.Embedding(len(unique_user_ids)  1, 32)])# 将商品特征映射到商品embedding中候选条目塔product_model  tf.keras.Sequential([    tf.keras.layers.StringLookup(vocabularyunique_product_ids, mask_tokenNone),    tf.keras.layers.Embedding(len(unique_product_ids)  1, 32)])# 定义模型指标metrics  tfrs.metrics.FactorizedTopK(    candidatesproduct_ds.batch(128).map(product_model))# 任务类把损失函数和指标计算放在一起本身是一个keras层task  tfrs.tasks.Retrieval(    metricsmetrics)# 完整的双塔召回模型类负责循环训练模型class RecModel(tfrs.Model):    # 初始化方法    def __init__(self, user_model, product_model):        super().__init__()        self.user_model: tf.keras.Model  user_model        self.product_model: tf.keras.Model  product_model        self.task: tf.keras.layers.Layer  task    # 计算损失    def compute_loss(self, features: Dict[Text, tf.Tensor], trainingFalse) -> tf.Tensor:        # 获取用户特征        user_embeddings  self.user_model(features[user_id])        # 获取商品特征        positive_product_embeddings  self.product_model(features[product_id])        # 计算损失        return self.task(user_embeddings, positive_product_embeddings)# 创建模型实例model  RecModel(user_model, product_model)model.compile(optimizertf.keras.optimizers.Adagrad(learning_rate0.05))# 缓存数据cached_train  train.shuffle(100_000).batch(8192).cache()cached_test  test.batch(4096).cache()# 开始训练model.fit(cached_train, epochs3)# 评估模型model.evaluate(cached_test, return_dictTrue)# 为训练好的模型建立索引这里设置召回前100条商品条目index  tfrs.layers.factorized_top_k.BruteForce(model.user_model, k100)index.index_from_dataset(    tf.data.Dataset.zip((product_ds.batch(100), product_ds.batch(100).map(model.product_model))))# 进行预测scores, products  index(tf.constant([42]))pprint.pprint(f用户Id 42 召回结果: {products[0, :5]})# 保存、加载模型路径path  C:\\data\\python\\data\\blog\\index\\# 保存模型tf.saved_model.save(index, path)# 加载模型loaded  tf.saved_model.load(path)# 进行预测scores, products  loaded([42])pprint.pprint(f用户Id 42 召回结果: {products[0, :5]})
排序

排序部分主要是根据用户对商品的评分数据训练出一个排序模型当然有的系统不一定有评分模块可以以用户的订单数据为基础结合系统中的其他数据经过一定的转换算法来生成评分数据如用户下单记录可以先简单理解为用户喜欢这个商品记录用户对这个商品的基础评分1分假如用户多次购买这个商品在基础分上再加1分其它的数据如用户分享过的、点赞过的、搜索过的商品都可以加1分或者作为基础分这样来把系统中的隐式反馈数据转换为显式评分数据方便后续进行排序模型训练。这里先简单的以用户的下单数据来作为评分数据进行训练即用户下单的商品都赋值为1分下图中rating列。

排序模型搭建同样分为以下几部分
1、数据处理
2、模型搭建
3、模型训练
4、模型评估
5、模型导出

import pprintfrom typing import Dict, Textimport pandas as pdimport numpy as npimport tensorflow as tfimport tensorflow_recommenders as tfrs# 使用pandas加载数据order_df  pd.read_csv(C:\\data\\python\\data\\blog\\order.csv, encodinggbk)pprint.pprint(order_df.shape)pprint.pprint(order_df.head(5))# 处理数据类型order_df[user_id]  order_df[user_id].astype(str)order_df[product_id]  order_df[product_id].astype(str)order_df[rating]  order_df[rating].astype(float)# 将DataFramepandas转换为Datasettensorfloworder_df  tf.data.Dataset.from_tensor_slices(dict(order_df))for x in order_df.take(1).as_numpy_iterator():    pprint.pprint(x)# 准备嵌入向量的词汇表ratings  order_df.map(lambda x: {    user_id: x[user_id],    product_id: x[product_id],    rating: x[rating]})# 随机数种子tf.random.set_seed(42)# 打乱数据shuffled  ratings.shuffle(100_000, seed42, reshuffle_each_iterationFalse)# 切分数据分为训练数据以及验证数据train  shuffled.take(80_000)test  shuffled.skip(80_000).take(20_000)# 数据分片user_ids  ratings.batch(1_000_000).map(lambda x: x[user_id])product_ids  ratings.batch(1_000_000).map(lambda x: x[product_id])# 获取唯一的用户Id列表以及商品列表unique_user_ids  np.unique(np.concatenate(list(user_ids)))pprint.pprint(unique_user_ids[:5])unique_product_ids  np.unique(np.concatenate(list(product_ids)))pprint.pprint(unique_product_ids[:5])# 实现排序模型class BaseModel(tf.keras.Model):  def __init__(self):    super().__init__()    embedding_dimension  32    # 用户 embeddings    self.user_embeddings  tf.keras.Sequential([      tf.keras.layers.StringLookup(vocabularyunique_user_ids, mask_tokenNone),      tf.keras.layers.Embedding(len(unique_user_ids)  1, embedding_dimension)    ])    # 商品 embeddings    self.product_embeddings  tf.keras.Sequential([      tf.keras.layers.StringLookup(        vocabularyunique_product_ids, mask_tokenNone),      tf.keras.layers.Embedding(len(unique_product_ids)  1, embedding_dimension)    ])    # 预测模型    self.ratings  tf.keras.Sequential([      tf.keras.layers.Dense(256, activationrelu),      tf.keras.layers.Dense(64, activationrelu),      tf.keras.layers.Dense(1)  ])  def call(self, inputs):    # 获取输入    user_id, product_id  inputs    # 获取用户特征、商品特征    user_embedding  self.user_embeddings(user_id)    product_embedding  self.product_embeddings(product_id)    # 计算评分    return self.ratings(tf.concat([user_embedding, product_embedding], axis1))# 完整的模型class RankModel(tfrs.models.Model):  def __init__(self):    super().__init__()    self.ranking_model: tf.keras.Model  BaseModel()    # 定义损失函数以及评估指标    self.task: tf.keras.layers.Layer  tfrs.tasks.Ranking(      loss  tf.keras.losses.MeanSquaredError(),      metrics[tf.keras.metrics.RootMeanSquaredError()]    )  def call(self, features: Dict[str, tf.Tensor]) -> tf.Tensor:    return self.ranking_model((features[user_id], features[product_id]))  def compute_loss(self, features: Dict[Text, tf.Tensor], trainingFalse) -> tf.Tensor:    # 获取实际评分    labels  features.pop(rating)    # 获取预测评分    rating_predictions  self(features)    # 计算损失    return self.task(labelslabels, predictionsrating_predictions)# 实例化模型model  RankModel()model.compile(optimizertf.keras.optimizers.Adagrad(learning_rate0.05))# 缓存训练和评估数据cached_train  train.shuffle(100_000).batch(8192).cache()cached_test  test.batch(4096).cache()# 训练模型model.fit(cached_train, epochs3)# 评估模型model.evaluate(cached_test, return_dictTrue)# 测试排序模型test_ratings  {}test_product_ids  [1, 2, 3, 4, 5]for product_id in test_product_ids:  test_ratings[product_id]  model({      user_id: np.array([1]),      product_id: np.array([product_id])  })# 倒序打印排序结果for product, score in sorted(test_ratings.items(), keylambda x: x[1], reverseTrue):  print(f排序结果 {product}: {score})# 保存模型tf.saved_model.save(model, C:\\data\\python\\data\\blog\\rank\\)# 加载模型loaded  tf.saved_model.load(C:\\data\\python\\data\\blog\\rank\\)# 进行排序print(loaded({user_id: np.array([42]), product_id: [42]}).numpy())
部署

召回以及排序模型训练好之后我们需要进行部署提供接口给前端应用进行调用TensorFlow也提供了部署的组件TensorFlow Serving方便开发者快速进行部署以便提供推荐服务。
1、拉取镜像

docker pull tensorflow/serving

2、配置文件
这里我们有两个训练好的模型一个是召回模型index一个是排序模型rank还需要再编写一个配置文件models.config配置两个模型的相关信息包含模型的名称、路径、以及生成模型的平台具体如下

model_config_list:{     config:{          name:index,          base_path:/models/index,          model_platform:tensorflow     },     config:{          name:rank,          base_path:/models/rank,          model_platform:tensorflow     }}

编写完成后总的文件以及相关目录如下

这些文件在dockerfile中进行添加或者启动容器后上传都可以这里注意一个点模型文件夹里面还需要再建一个版本号文件夹例如1用来表示版本号具体可见下面截图

3、启动容器
这里直接以上面拉取的tensorflow/serving镜像为基础启动容器同时挂载本地的models文件夹到容器的models文件夹下以及指定多模型配置文件models.config即可运行具体如下

docker run -t -p 8501:8501 --mount typebind,sourceE:\data\python\simple\models,target/models -e MODEL_NAMEindex -t tensorflow/serving --model_config_file/models/models.config &

如果有用docker desktop可以在containers界面看到启动的容器点击进去查看日志可以看到两个模型已经成功加载服务也成功启动相关截图如下

查看容器的文件目录可以看到我们挂载进去的models文件夹以及下面的相关模型、配置文件截图如下

调用

推荐模型部署好之后我们就可以用http post的方式来调用推荐服务提供的rest api接口了。召回服务的调用路径为 这里模拟为用户Id为1和2的两个用户进行商品推荐示例如下

# 1、先进行召回推荐这里使用curl命令来进行调用curl -d {instances:[1,2]} -X POST  召回推荐返回如下{    predictions: [ # 推荐列表        { # 用户Id为1召回结果            output_1: [3.94739556,2.27907419, ...... ], # 召回的依据分数100个            output_2: [59001,3039, ...... ] # 召回商品Id与分数一一对应100个        },        { # 用户Id为2召回结果            output_1: [2.272927,2.263876706, ...... ],            output_2: [11632,7338, ...... ]        }    ]}# 2、将召回推荐的结果再输入排序模型来进行排序得到最终的推荐结果这里对用户Id为1的召回结果进行排序用户Id为2同理curl -d {inputs:{customer_id:[1,1, ...... ],product_id:[59001,3039, ......这里是召回的100个商品Id太长了省略 ]}} -X POST  排序返回如下可以取排序后分数最高的前10个商品作为最终的结果推荐给用户{    outputs: [ # 排序列表        [1.19891763], # 排序的依据分数与请求参数中的商品Id一一对应100条        [1.15422344],        ......    ]}
结尾

一个简单的推荐系统demo搭建到这里就结束了当然生产的推荐肯定不会这么简单需要我们收集更多的用户特征、商品特征以及优化、调整超参数

标签:
声明:无特别说明,转载请标明本文来源!