我们是如何测试人工智能的(六)推荐系统拆解

推荐系统简介

推荐系统的问题

根据之前学习到的内容,我们已经基本了解到了要如何构建一个二分类模型。我们都知道模型大体可以分成,回归,二分类和多分类。但推荐系统是属于哪一种场景呢,比如我们常见的广告推荐或者内容推荐,这些场景都是由系统来判断用户的喜好来推送广告或者视频内容,以追求更高的点击率和转化率。这种场景怎么看都不像跟这三种类型的算法有关系。

实现思路

其实解决这个问题的思路也比较简单, 我们可以遵循如下的原则:

  1. 借助专家系统,根据用户的信息初筛一个候选的视频集合(比如 1000 个),比如可以先简单根据用户的年龄,性别,爱好,职业进行推测他喜欢的类型并过滤出候选集合。 这是一种预处理机制, 在人工智能系统中,模型往往无法处理所有的情况,需要一些预处理与后处理辅助模型。在推荐系统中这个步骤往往被称为大排序,先根据规则来筛选候选集合。这么做有多种原因,其中一种比较典型的是担心模型的性能无法支撑过多的候选集合的计算。
  2. 训练一个二分类模型,这个模型用于推理出用户是否会点击这个视频(根据业务场景来,有可能是点击,有可能是点赞,也有可能是转化)。
  3. 将候选集合分别输入给模型进行推理。计算出每个视频会被用户点击的概率。
  4. 把模型的推理结果进行排序,取 top n 个概率最高的视频推送给用户。这一步就与传统的二分类模型不同, 我们已经知道模型输出的是目标属于某个类别的概率。而在传统二分类模型中, 需要用户自己设定一个阈值(也叫置信度)来辅助判断目标的类别, 概率大于这个阈值的判定为正例,小于这个阈值的判定为负例,这正是二分类模型的原理。但是在推荐系统中, 我们并不会因为用户喜欢这个内容的概率超过了某个阈值就进行推送, 因为候选集合太多了, 我们不能把超过某个阈值的都推送过去(广告位或者内容推送是有数量限制的)。 所以最终选择的是根据用户喜欢这个内容的概率进行排序,然后取 topN 来进行推送。

如此我们就把一个推荐系统的问题转换成了一个二分类的问题。 我们可以理解为世界上所有的监督学习场景,都是由二分类,多分类和回归问题变种而来。

写一个简单的模型训练 DEMO(使用 spark ml 库)


from pyspark.sql import SparkSession
from pyspark.ml import Pipeline
from pyspark.ml.feature import Tokenizer, StopWordsRemover, CountVectorizer
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import BinaryClassificationEvaluatorfrom pyspark import SparkContext, SparkConf, SQLContext
from pyspark.sql import functions as F
from pyspark.sql.window import Windowconf = SparkConf().setMaster("local").setAppName("My App")
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)# 定义数据
dicts = [['man', 'The Shawshank Redemption', 1.0],['man', 'The Godfather', 1.0],['man', 'Forrest Gump', 1.0],['woman', 'Titanic', 1.0],['woman', 'Forrest Gump', 0.0],['woman', 'The Godfather', 0.0],['woman', 'The Shawshank Redemption', 0.0],['man', 'Titanic', 0.0],['man', 'A Beautiful Mind', 0.0],['woman', 'A Beautiful Mind', 1.0],
]
rdd = sc.parallelize(dicts, 3)
dataf = sqlContext.createDataFrame(rdd, ['gender', 'title', 'interested'])# 将性别进行独热编码,以便把数据转换成算法可以识别的形式
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler
stringIndexer = StringIndexer(inputCol="gender", outputCol="gender_num")
data_indexed = stringIndexer.fit(dataf).transform(dataf)
encoder = OneHotEncoder(inputCol="gender_num", outputCol="gender_onehot")
data_encoded = encoder.fit(data_indexed).transform(data_indexed)
data = data_encoded.select('gender_onehot', 'interested', 'title')
data.show()# 使用分词器
tokenizer = Tokenizer(inputCol="title", outputCol="words")
# 使用停用词
remover = StopWordsRemover(inputCol="words", outputCol="filtered_words")
# 将文本数据转换成特征向量,注意下面被注释的代码,这里是词向量转换,在NLP中,我们经常会把文本进行词向量转换,我们在下面会详细讲解词向量的内容。
# word2vec.fit(remover)
vectorizer = CountVectorizer(inputCol="filtered_words", outputCol="final_words")# 将所有特征组合成一个特征向量
vectorAssembler = VectorAssembler(inputCols=["gender_onehot", "final_words"], outputCol="features")# 定义逻辑回归
classifier = LogisticRegression(labelCol="interested", featuresCol="features", maxIter=10)
# 定义流水线, 当数据来了以后就可以按顺序处理数据
pipeline = Pipeline(stages=[tokenizer, remover, vectorizer, vectorAssembler, classifier])
# 模型训练
model = pipeline.fit(data)# 模型推理
predictions = model.transform(data)
evaluator = BinaryClassificationEvaluator(labelCol="interested", rawPredictionCol="rawPrediction")
accuracy = evaluator.evaluate(predictions)
print("Accuracy:", accuracy)
predictions.show()df_desc = predictions.orderBy(F.desc("probability"))
df_desc.show()

词向量

上面用于训练模型的数据中有一列是视频的标题,我们会发现代码中我们使用了一系列 NLP(Natural Language Processing,自然语言处理)的算法:

  • 分词器(tokenizer):用于在一个句子中提取一个一个的词
  • 停用词(stop words):用于去掉一些语义无关的语气词,介词等,比如the或者中文中的语气词。 在模型训练中往往需要去掉这些词以去除噪音,优化模型空间,减少索引量等等
  • 词向量(也叫词嵌入):可以理解为计算出词与词之间的关联性,从而训练出的围绕中心词的特征向量。

上述概念中可能词向量是最难以理解的,这里尽量尝试用简单易懂的语言来解释这个概念。 我们之前训练反欺诈模型的时候,也遇到过一些离散特征,比如title也是以文本形式存在的数据。
我们在反欺诈中处理这样的使用的 one-hot(独热编码),独热编码也是一种处理离散特征常用的方法。假设我们有一群学生,他们可以通过四个特征来形容,分别是:

  • 性别:[“男”,“女”]
  • 年级:[“初一”,“初二”,“初三”]
  • 学校:[“一中”,“二中”,“三中”,“四中”] 我们用采用 N 位状态寄存器来对 N 个状态进行编码,拿上面的例子来说,就是:

因此,当我们再来描述一个学生的时候(男生,初一,来自一中),就可以采用 [1 0 1 0 0 0 1 0 0] 这样的形式来表示。这也一种用于特征组合的实现方法之一。

或者我们也可以使用类似 bitmap 的方法做出一个 one—hot 向量来表示离散特征。 我们可以用类似下面的形式表达:

假设职业这一列一共有 100 个值, 假设教师在编号 6 这个位置上,编号 6 所在位置 ide 值就是 1,其他的值都是 0,我们以这个向量来代表教师这个特征. 以此类推,如果学生代表的编号是 10,那么
10 这个位置所在的值是 1,其他位置的值都是 0,用词向量来代表学生。 这样最后我们就有 100 个 100 维度的向量来表示这些特征。

上面两种方法都是很常见的用来用来表达文本特征的方法,但它们的问题是词与词之间是独立的,互相没有关联。 比如我们的训练数据中有一个句子this is apple juice,我们期望当
出现 this is orange __ 的时候,模型能够为我们推测出这个空白处也应该填写单词juice。 也就是我们希望模型能通过之前针对第一个句子的训练就能找到单词与单词之间的关系,模型能够知道
appleorange是含义相似的词,从而能推测出orange后面也可以填写juice。 而这正是词向量要做的事情。

如上图,词向量围绕这一些中心词(性别,事务,高贵程度),计算出每一个词与这些中心词的相关程度。而要得到这个词向量本身就需要相关算法训练出来,比如 world2vec:


from pyspark.ml.feature import Word2Vecfrom pyspark.sql import SparkSessionspark = SparkSession \.builder \.appName("dataFrame") \.getOrCreate()# Input data: Each row is a bag of words from a sentence or document.
documentDF = spark.createDataFrame([("Hi I heard about Spark".split(" "),),("I wish Java could use case classes".split(" "),),("Logistic regression models are neat".split(" "),)
], ["text"])documentDF.show()# Learn a mapping from words to Vectors.
word2Vec = Word2Vec(vectorSize=5, minCount=0, inputCol="text", outputCol="result")
model = word2Vec.fit(documentDF)result = model.transform(documentDF)
for row in result.collect():text, vector = rowprint("Text: [%s] => \nVector: %s\n" % (", ".join(text), str(vector)))# 运行结果
Text: [Hi, I, heard, about, Spark] => 
Vector: [-0.056896060705184937,-0.029017432034015658,0.020092955231666567,-0.0003222271800041199,-0.02170231742784381]Text: [I, wish, Java, could, use, case, classes] => 
Vector: [0.003511839745832341,0.025775608922620968,-0.01780955892588411,0.0012207544807876858,-0.0023355478021715365]Text: [Logistic, regression, models, are, neat] => 
Vector: [0.008233835361897946,-0.01995183974504471,-0.013863331265747549,-0.051928133144974714,-0.014838875085115433]

上面是一个训练词向量的代码,它的计算原理大概可以描述为:在文本中选取中心词并选取中心词前后数个单词,并训练出这些词会出现在中心词周围的概率。

总结

这些就是一个推荐系统中的大概步骤, 当然实际的推荐系统是非常复杂的, 我目前也只是列了一个简单的 DEMO,帮助大家理解推荐系统都在做什么事情。 更多手把手教你人工智能测试内容请关注我的星球:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/441309.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索水下低光照图像检测性能,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建海底生物检测识别分析系统

海底这类特殊数据场景下的检测模型开发相对来水比较少,在前面的博文中也有一些涉及,感兴趣的话可以自行移步阅读即可: 《尝试探索水下目标检测,基于yolov5轻量级系列模型n/s/m开发构建海底生物检测系统》 《基于YOLOv5C3CBAMCBA…

Django4.2(DRF)+Vue3 读写分离项目部署上线

文章目录 1 前端2 后端2.1 修改 settings.py 文件关于静态文件2.2 关于用户上传的文件图片 3 Nginx4 镜像制作4.1 nginx4.3 Django镜像4.3.1 构建 5 docker-compose 文件内容 1 前端 进入前端项目的根目录,运行如下命令进行构建 npm run build构建完成后&#xff…

Easy-Es操作Elasticsearch

文章目录 1 Easy-Es1.1 简介1.2 MySQL与Easy-Es语法对比1.3 集成及配置1.3.1 pom.xml1.3.2 配置 1.4 使用1.4.1 注解的使用1.4.2 EsMapper接口1.4.3 简单搜索 1.5 使用案例1.5.1 综合商品搜索1.5.2 相关商品推荐1.5.3 聚合搜索商品相关信息 1 Easy-Es 使用过Spring Data操作ES…

【Tomcat与网络3】Tomcat的整体架构

目录 1.演进1:将连接和处理服务分开 2演进2:Container的演进 3 再论Tomcat的容器结构 4 Tomcat处理请求的过程 5 请求的处理过程与Pipeline-Valve管道 在前面我们介绍了Servlet的基本原理,本文我们结合Tomcat来分析一下如何设计一个大型…

Cache Lab:Part A【模拟出使用LRU策略的高速缓存存储器组织结构】

目录 任务描述 知识回顾 实验内容 测试结果 Cache Lab 对应《CS:APP》6.3节至第六章结束的内容。 任务描述 Your job for Part A is to fill in the csim.c file so that it takes the same command line arguments and produces the identical output as the reference …

[NCTF2019]Fake XML cookbook(特详解)

先试了一下弱口令,哈哈习惯了 查看页面源码发现xml function doLogin(){var username $("#username").val();var password $("#password").val();if(username "" || password ""){alert("Please enter the usern…

基于大数据的B站数据分析系统的设计与实现

摘要:随着B站(哔哩哔哩网)在国内视频分享平台的崛起,用户规模和数据量不断增加。为了更好地理解和利用这些海量的B站数据,设计并实现了一套基于Python的B站数据分析系统。该系统采用了layui作为前端框架、Flask作为后端…

代码随想录算法训练营29期|day35 任务以及具体任务

860.柠檬水找零 class Solution {public boolean lemonadeChange(int[] bills) {int five 0;int ten 0;for (int i 0; i < bills.length; i) {if (bills[i] 5) {five;} else if (bills[i] 10) {five--;ten;} else if (bills[i] 20) {if (ten > 0) {ten--;five--;} …

242. 有效的字母异位词(力扣)(C语言题解)

✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&#xff0c;麻烦点点赞哦&#x1f388; 所属专栏&#xff1a;刷题 我的主页&#xff1a;脑子不好的小菜鸟 文章特点&#xff1a;关键点和步骤讲解放在 代码相应位置 题目链接&#xff1a; 242. 有效的字母异位词 …

玻璃封装高温烧结航空插头插座连接器

概述 随着风电行业深入发展&#xff0c;风力发电机组使用的传感器主要有:位置传感器、加速度传感器、压力传感器、温度传感器、液位传感器、电压电流互感器、压点薄膜传感器等。对电子元器件的性能提出了更进一步的要求。连接器作为连接各个电子元器件的血脉&#xff0c;在保持…

萝卜视频源码前后端带视频演示

萝卜影视源码前端是用JAVA开发的全原生APP源码&#xff0c;后端用的是二次开发的苹果CMS&#xff0c;支持局域网投屏&#xff0c;视频软解硬解&#xff0c;播放器自带弹幕功能。支持解析官方视频&#xff0c;支持M3U8&#xff0c;MP4。 开屏广告&#xff0c;全局广告&#xff0…

Unity3D正则表达式的使用

系列文章目录 unity工具 文章目录 系列文章目录前言一、匹配正整数的使用方法1-1、代码如下1-2、结果如下 二、匹配大写字母2-1、代码如下1-2、结果如下 三、Regex类3-1、Match&#xff08;&#xff09;3-2、Matches()3-3、IsMatch&#xff08;&#xff09; 四、定义正则表达式…

【测试运维】接口测试各知识md文档学习笔记第1篇(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论接口测试相关知识。目标&#xff1a;了解接口测试服务对象&#xff0c;基本作用&#xff0c;接口测试环境插件工具&#xff0c;掌握jmeter的使用&#xff0c;掌握接口测试的测试用例编写。熟悉Jmeter工具组成&#xff0…

数据的绘画:数据可视化为我们打开信息的画卷

在迅猛发展的大数据时代&#xff0c;数据可视化成为我们逐步适应信息激增的得力工具。通过直观展示庞大复杂的数据&#xff0c;数据可视化不仅简化了信息的理解&#xff0c;更为我们提供了深入洞察的机会。这一技术的崛起不仅仅是技术的进步&#xff0c;更是对我们信息处理方式…

C++_list

目录 一、模拟实现list 1、list的基本结构 2、迭代器封装 2.1 正向迭代器 2.2 反向迭代器 3、指定位置插入 4、指定位置删除 5、结语 前言&#xff1a; list是STL(标准模板库)中的八大容器之一&#xff0c;而STL属于C标准库的一部分&#xff0c;因此在C中可以直接使用…

04MARL - priori kownledge and challenge

文章目录 一、General Learning Process二、中心化学习与独立学习1.central learning1.1 CQL1.2 局限性 2.Independent Learning2.1 IQL2.2 局限性 三、MARL挑战1.非平稳性1.1单智能体强化学习的非平稳性1.2 MARL非平稳性 2.信用分配问题3.均衡选择4.拓展性 四、协作型MARL的模…

Web实战丨基于Django的简单网页计数器

文章目录 写在前面Django简介主要程序运行结果系列文章写在后面 写在前面 本期内容 基于django的简单网页计数器 所需环境 pythonpycharm或vscodedjango 下载地址 https://download.csdn.net/download/m0_68111267/88795604 Django简介 Django 是一个用 Python 编写的高…

MySQL的原生API实现插入数据后在可视化工具上不显示的问题解决

显示表中有两行数据&#xff0c;该表也设置了主键和唯一索引 点进表里看却没有数据 问题原因出现在这里&#xff0c;虽然很多常用的数据库连接池都会开启自动提交&#xff0c;但ibatis的SqlSession使用sessionFactory.openSession()创建时&#xff0c;默认的自动提交是false&am…

纯静态微信小程序水果商城

首页代码 <view class"container"><!-- 轮播图 --><view class"swiper-container"><swiper class"screen-swiper" indicator-dots"true" circular"true" autoplay"true" interval"300…

数据结构——栈和队列(C语言)

栈种常见的数据结构&#xff0c;它用来解决一些数据类型的问题&#xff0c;那么好&#xff0c;我来带着大家来学习一下栈 文章目录 栈对栈的认识栈的模拟实现栈的练习方法一方法二 栈 对栈的认识 栈&#xff08;stack&#xff09;是限定只能在表的一端进行插入删除操作的线性…