如何做好网站搜索引擎优化,求职seo推荐,做本地生活圈网站好吗,怎么做自己的发卡网站Tensorflow 2.12 简单智能商城商品推荐系统搭建 前言架构数据召回排序部署调用结尾 前言 基于 Tensorflow 2.12 搭建一个简单的智能商城商品推荐系统demo~ 主要包含6个部分#xff0c;首先是简单介绍系统架构#xff0c;接着是训练数据收集、处理#xff0c;然后是召回模型、… 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 pprint
import pandas as pdfrom typing import Dict, Textimport numpy as np
import tensorflow as tf
import 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转换为Datasettensorflow
order_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_modelself.product_model: tf.keras.Model product_modelself.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 pd
import numpy as np
import tensorflow as tf
import 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转换为Datasettensorflow
order_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# 用户 embeddingsself.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)])# 商品 embeddingsself.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/serving2、配置文件 这里我们有两个训练好的模型一个是召回模型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接口了。召回服务的调用路径为http://localhost:8501/v1/models/index:predict其中v1对应之前建立的版本号文件夹1index对应的是召回模型名称predict是表示进行预测的意思同理排序模型的调用路径为http://localhost:8501/v1/models/rank:predict。 这里模拟为用户Id为1和2的两个用户进行商品推荐示例如下
# 1、先进行召回推荐这里使用curl命令来进行调用
curl -d {instances:[1,2]} -X POST http://localhost:8501/v1/models/index:predict
# 召回推荐返回如下
{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 http://localhost:8501/v1/models/rank:predict
# 排序返回如下可以取排序后分数最高的前10个商品作为最终的结果推荐给用户
{outputs: [ # 排序列表[1.19891763], # 排序的依据分数与请求参数中的商品Id一一对应100条[1.15422344],......]
}结尾
一个简单的推荐系统demo搭建到这里就结束了当然生产的推荐肯定不会这么简单需要我们收集更多的用户特征、商品特征以及优化、调整超参数