内容目录
- 1.思考题
- 1.1ALS都有哪些应用场景
- 1.2ALS进行矩阵分解的时候,为什么可以并行化处理
- 1.3梯度下降法中的批量梯度下降(BGD),随机梯度下降(SGD),和小批量梯度下降有什么区别(MBGD)
- 1.4你阅读过和推荐系统/计算广告/预测相关的论文么?有哪些论文是你比较推荐的,可以分享到微信群中
- 2.编程题
- 2.1对MovieLens数据集进行评分预测
- 2.1.1SlopeOne算法原理
- 2.2.2SlopeOne算法的优缺点
- 2.2.3SlopeOne算法实战
- 2.2.3.4SlopeOne算法总结
- 2.2Paper Reading(1周)积累,总结笔记,自己的思考及idea
- 2.2.1阅读论文的一些思考
- 2.3设计自己的句子生成器
1.思考题
1.1ALS都有哪些应用场景
1.网易云的歌曲推荐;
2.抖音的小视频推荐;
3.西瓜视频的文章推荐;
4.被用做编程语言算法底层逻辑,如用作spark Mlib协同过滤
1.2ALS进行矩阵分解的时候,为什么可以并行化处理
ALS方法是一个高效的求解矩阵分解的算法,目前Spark Mllib中的协同过滤算法就是基于ALS求解的矩阵分解算法,它可以很好地拓展到分布式计算场景,轻松应对大规模训练数据的情况。下面对ALS算法原理及特点做一个简单介绍。
ALS算法的原理基本就是名字表达的意思,通过交替优化求得极值。一般过程是先固定,那么公式就变成了一个关于的二次函数,可以作为最小二乘问题来解决,求出最优的后,固定,再解关于的最小二乘问题,交替进行直到收敛。相比SGD算法,ALS算法有如下两个优势。
(1)并行化处理
从上面 、的更新公式中可以看到,当固定后,迭代更新时每个只依赖自己,不依赖于其他的标的物的特征向量,所以可以将不同的的更新放到不同的服务器上执行。同理,当固定后,迭代更新时每个只依赖自己,不依赖于其他用户的特征向量,一样可以将不同用户的更新公式放到不同的服务器上执行。Spark的ALS算法就是采用这样的方式做到并行化的。
(2)对于隐式特征问题比较合适
用户真正的评分是很稀少的,所以利用隐式行为是更好的选择(其实也是不得已的选择)。当利用了隐式行为,那么用户行为矩阵就不会那么稀疏了,即有非常多的对是非空的,计算量会更大,这时采用ALS算法是更合适的,因为固定或者,让整个计算问题更加简单,容易求目标函数的极值。
1.3梯度下降法中的批量梯度下降(BGD),随机梯度下降(SGD),和小批量梯度下降有什么区别(MBGD)
- 批量梯度下降:在每次更新时用所有样本,要留意,在梯度下降中,对于的更新,所有的样本都有贡献,也就是参与调整。其计算得到的是一个标准梯度,对于最优化问题,凸问题,也肯定可以达到一个全局最优。因而理论上来说一次更新的幅度是比较大的。如果样本不多的情况下,当然是这样收敛的速度会更快啦。但是很多时候,样本很多,更新一次要很久,这样的方法就不合适啦。下图是其更新公式
- 随机梯度下降:在每次更新时用1个样本,可以看到多了随机两个字,随机也就是说我们用样本中的一个例子来近似我所有的样本,来调整θ,因而随机梯度下降是会带来一定的问题,因为计算得到的并不是准确的一个梯度,对于最优化问题,凸问题,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。但是相比于批量梯度,这样的方法更快,更快收敛,虽然不是全局最优,但很多时候是我们可以接受的,所以这个方法用的也比上面的多。下图是其更新公式:
- mini-batch梯度下降:在每次更新时用b个样本,其实批量的梯度下降就是一种折中的方法,他用了一些小样本来近似全部的,其本质就是我1个指不定不太准,那我用个30个50个样本那比随机的要准不少了吧,而且批量的话还是非常可以反映样本的一个分布情况的。在深度学习中,这种方法用的是最多的,因为这个方法收敛也不会很慢,收敛的局部最优也是更多的可以接受!
总的来说,随机梯度下降一般来说效率高,收敛到的路线曲折,但一般得到的解是我们能够接受的,在深度学习中,用的比较多的是mini-batch梯度下降。
2.编程题
2.1对MovieLens数据集进行评分预测
数据集:MovieLens
工具:可以使用Surprise或者其他说明使用的模型,及简要原理
2.1.1SlopeOne算法原理
Step1,计算Item之间的评分差的均值
b与a:((3.5-5)+(5-2)+(3.5-4.5))/3=0.5/3
c与a:((4-2)+(1-4.5))/2=-1.5/2
d与a:((2-2)+(4-4.5))/2=-0.5/2
c与b:((4-5)+(1-3.5))/2=-3.5/2
d与b:((2-5)+(4-3.5))/2=-2.5/2
d与c:((2-4)+(4-1))/2=1/2Step2,预测用户A对商品c和d的评分
a对c评分=((-0.75+5)+(-1.75+3.5))/2=3
a对d评分=((-0.25+5)+(-1.25+3.5))/2=3.5
Step3,将预测评分排序,推荐给用户推荐顺序为{d, c}
2.2.2SlopeOne算法的优缺点
SlopeOne算法,把三个步骤通过一个例子的去讲述,发现这个算法也不是很难。每个算法的提出,都是为了解决某个问题,这个问题或大或小,如果帮忙解决当时很大的问题,我们称之为Basline算法系列了。那么属于SlopeOne算法的特点是什么?
- 适用于item更新不频繁,数量相对较稳定
- item数<<user数
- 算法简单,易于实现,执行效率高
- 依赖用户行为,存在冷启动问题和稀疏性问题
2.2.3SlopeOne算法实战
#导入surprise 库的相关模块
from surprise import Dataset
from surprise import Reader
from surprise import SlopeOne
from surprise import accuracy
from surprise.model_selection import KFold
# 数据读取
file_path = 'E:/python/machina/kaggle_practice/week4/data/ratings.csv'
reader = Reader(line_format='user item rating timestamp', sep=',', skip_lines=1)
data = Dataset.load_from_file(file_path, reader=reader)
train_set = data.build_full_trainset()
'''
该算法适用于物品更新不频繁,数量相对较稳定并且物品数目明显小于用户数的场景。依赖用户的用户行为日志和物品偏好的相关内容。
优点:
1.算法简单,易于实现,执行效率高;
2.可以发现用户潜在的兴趣爱好;
缺点:
依赖用户行为,存在冷启动问题和稀疏性问题。
'''
# SlopeOne
algo = SlopeOne()
# 定义K折交叉验证迭代器,K=3
kf = KFold(n_splits=3)
for trainset, testset in kf.split(data):
algo.fit(trainset)
predictions = algo.test(testset)
accuracy.rmse(predictions, verbose=True)
uid = str(196)
iid = str(302)
pred = algo.predict(uid, iid, r_ui=4, verbose=True)
# 打印结果
# RMSE: 0.8689
print(pred)
2.2.3.4SlopeOne算法总结
- ALS和SGD都是数学上的优化方法,可以解决最优化问题(损失函数最小化)
- ALS-WR算法,可以解决过拟合问题,当隐特征个数很多的时候也不会造成过拟合
- ALS,SGD都可以进行并行化处理
- SGD方法可以不需要遍历所有的样本即可完成特征向量的求解
- Facebook把SGD和ALS两个算法进行了揉合,提出了旋转混合式求解方法,可以处理1000亿数据,效率比普通的Spark MLlib快了10倍
2.2Paper Reading(1周)积累,总结笔记,自己的思考及idea
SlopeOne是一种推荐算法,属于Rating-based collaborative filtering领域,即是预测某个user对于某个给定的item的评分,本质上是一种协同过滤算法。该算法易于实现,可以实时动态更新,响应快,给出的结果也足够好,可适用于冷启动用户,方便部署。Slope one算法可以直译为斜率为一,因据其作者认为,该算法可以近似用f(x)=x+b这个函数式来表示。具体如何,下面分解。
该算法的motivation是基于商品的’popularity differential’,即商品间受欢迎度的差异,念来十分拗口,但想法十分朴素。
如上图所示,来做个小学数学题,试想有商品ItemI,ItemJ,User A对二者的评分分别是1,1.5,已知User B 对ItemI 的评分是2,试预测UserB 对ItemJ的评分,那么我们可以这么认为,商品间受欢迎的差异从某种程度上是固定的,打个不恰当的比方,所有人都更喜欢美女,而相较而言不那么喜欢长相奇怪的,但不同人间是有差异的,某男A资深直男癌,眼光比较高,对林志玲评分为3,村东头的翠花评分为1,某男B死肥宅,是个女的都可以接受,对村东头的翠花评分都到了3,对林志玲更是疯狂打出了5分的最高分,那么注意了现在,男A和男B的喜好眼光都是不同的,但对于林志玲和翠花的打分的分数的差却是一样的,3-1=5-3,都更喜欢林志玲而不是翠花,喜欢的程度差是一定的,这就是slope one算法的精髓,据这样的思考方式,很容易就能求出UserB 对ItemJ的评分2+(1.5-1)=2.5
理解了上面那个例子就相当于理解了slope one算法的全部,剩下的就是据此朴素想法上的一些修补而产生的一些变体。
接着来比较一下slope one算法跟其它算法,试看看相对优劣。
第一部分(Per user average): 在预测一个对新item的评分时,将用户过去对所有item的评分加以平均,简单粗暴,效果随缘。
第二部分: bias from mean
是用户u对商品i的评分, 是有对i作过评分的用户的集合,是用户v对商品i的评分,其余两个上面带一横的分别是用户u,v以往做过的评分的均值,card简单来说就是其内集合的元素项的个数,整体式子不难理解,含义就是bias from mean。第三部分: adjusted cosine item-based
整个式子看上去较为复杂,我们一步一步来看,是有对i,j都作过评分的用户的集合,其它符号与上面是一样的含义,整体是计算商品i,j间的相似度,根据这相似度的不同衡量方式可以衍生出不同的算法,然后第二个式子的,即用户u对商品i的评分便可以根据该用户对其它商品的评分进行参考(根据商品间的相似度作为权重)计算,当然两商品间越相似,用户对两商品的评分也越相似。Alpha,Belta在这里就当做某种校正因子不必深究。
第四部分:the pearson reference scheme
该算法属于memory-based,简单来说就是很耗内存,lazy learning,事先不做或很少做准备,等开始使用的时候才从内存(已经存了大量数据)中提出一堆数据开始计算并返回结果。
式子又比较复杂,慢慢来看,Gamma(u,v)其实就是用户u,v间的相似度,所以这其实就是在上面bias from mean算法的基础上引入用户间的相似度作为权重而已
第五部分:the slope one
终于到了我们的主角出场,
呃,跟我们上面的朴素想法不同,这式子看着也挺复杂的,慢慢来看,就是我们前面说过的不同商品i,j间受欢迎度的差异,第一个式子就是简单的对不同人取个均值,第二个式子就是简单的对不同物再取个均值,最后得到的就是用户u对商品j的评分,果然是一个朴素的想法
第六部分:the weighted slope one scheme
这就是slope one的一个变体,如其名所示,就是多考虑了下某方面的权重,那么这个权重究竟是哪方面的?从式子来看,就是那个,那么这个是什么?,是什么,上面已经说过,其是有对i,j都作过评分的用户的集合,就是对i,j都作过评分的用户的个数,通常来说,若更多的人对某商品i,j对都作过评分,其相应的统计均值更接近均衡,更可靠,所以相应的权重更高也容易理解。
第七部分:the bi-polar slope one scheme
这又是对slope one的另一个变体,对比本体,我们发现,dev部分就是在左上角多了个like,对应的,这里应该还有个dislike,这里略去,领会精神,知道还存在对应的另一个就好。其实好好看上面的式子,会发现,其实这个式子的各个组成部分在上面算法的介绍中都出现过。这里只要详细介绍下 就好, 表示是有对i,j都作过评分的用户的集合, 其实就是有对i,j都作过评分,而且都表示喜欢商品i,j的用户的集合,dislike与此相反,不必赘述。那么什么叫用户表示喜欢某商品呢,其实就是对某商品的评分高于其对以往所有商品评分的均值,毕竟这世界同时存在着直男癌和死肥宅,直男癌对所有商品评分都低,死肥宅对所有商品评分都高,只有取他们自己评分的均值才能知道到底什么才是他们的真爱。接下来我们来分析下为什么这么做。我们发现,对比 ,和对集合中的元素有更严格的定义,如果有某对商品i,j,某用户a表示喜欢i却不喜欢j,则和中都将不包含某用户a这个元素,跟相比,则对应的这条信息记录就从此在式子里消失不见了,不再参与最后p(u)的计算,第一直觉是,有些数据不见了,那么根据大数据时代的基本定律,数据即石油,该算法应该是比本体slope one更差才对,但结果是更好,为什么呢?其实本质是这里做了个过滤,某用户a喜欢i却不喜欢j,与同时喜欢i,j或同时不喜欢i,j的人本质就不是同类型的人,我们预测评分,用协同过滤,要做参考当然是参考同类型的人比较好,那些不同类型的人带入的数据其实只带来了干扰,过滤掉他们当然就带来更好的效果,所以大数据时代的数据即石油,应该修正为质量高的数据才为石油更好些。
最后是各个算法间预测的比较,上面那个数值越低越好。可以看到,pearson预测性能表现也不错,但论对内存的消耗,响应速度,对冷启动用户的支持,slope one类型的算法就胜过太多了。
2.2.1阅读论文的一些思考
1.SlopeOne系列算法为协同过滤推荐系统中的可伸缩性问题提供了引人注目的解决方案,但作为主要问题的数据稀疏性问题仍然存在。现在很多的算法都会采用各种复杂的方法,这些方法不仅对SlopeOne的可伸缩性产生负面影响,而且还需要评级矩阵以外的一些其他信息。为了解决这个问题,我觉得可以使用加权斜率的新方法
2.协同过滤是推荐系统中广泛使用的技术之一。数据稀疏性是影响协同过滤预测精度的主要因素。SlopeOne算法使用简单的线性回归模型来解决数据稀疏性问题。结合用户的相似性,KNN可以优化参与预测的用户做出的评分质量。基于SlopeOne算法,可以提出一种将不确定邻居与SlopeOne相结合的协同过滤算法。首先,根据与其他用户的相似性,为每个用户动态选择不同数量的邻居。其次,在item-item之间的平均偏差是基于邻居用户的评级生成的。最后,通过线性回归模型预测对象等级
2.3设计自己的句子生成器
import random
# 用Python完成一个简单的人物对话
# 1.切分字符串
# 2.随机字符串内容
# 定语从句语法
host = """
host = 寒暄 报数 询问 具体业务 结尾
报数 = 我是人工智障 数字 号 ,
数字 = 单个数字 | 数字 单个数字
单个数字 = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
寒暄 = 称谓 打招呼 | 打招呼
称谓 = 人称 ,
人称 = 菜鸟 | 大佬 | 大师
打招呼 = 你好 | 您好
询问 = 请问你要 | 您需要
具体业务 = web进阶 | 学BI名企课 | 理解NLP | 报CV
结尾 = 吗?"""
# 得到语法字典
def getGrammarDict(gram, linesplit = "\n", gramsplit = "="):
#定义字典
result = {}
for line in gram.split(linesplit):
# 去掉首尾空格后,如果为空则退出
if not line.strip():
continue
expr, statement = line.split(gramsplit)
# print(expr)
result[expr.strip()] = [i.split() for i in statement.split("|")]
#print(result)
return result
# 生成句子
def generate(gramdict, target, isEng = False):
if target not in gramdict:
return target
find = random.choice(gramdict[target])
#print(find)
blank = ''
# 如果是英文中间间隔为空格
if isEng:
blank = ' '
return blank.join(generate(gramdict, t, isEng) for t in find)
gramdict = getGrammarDict(host)
# Python随机生成的人物对话内容
'''
大佬,您好我是人工智障4号,请问你要报CV吗?
菜鸟 , 你好 我是人工智障 7 号 , 请问你要 报CV 吗?
'''
print(generate(gramdict,"host"))
print(generate(gramdict,"host", True))