00:00
呃,那最后我们的要实现的当然就是这里的这个get RM SE这个方法DeFine get RM SE,那么它里边的参数是什么呢?我们是不是首先要选择一个,哎,我这里边给大家还是直接把它这个敲出来,它有可能会知道我们想要做的事情,对吧?大家看这里边的model直接就给了一个什么类型呢?这个model是不是就是我们RARS.train返回的这个数据类型啊,它的类型叫做一个matrix factorization model啊,所以我们要把这个这个也要引入对不对?好,后边还有一个,这个是其实是我们的测试数据对不对,我们直接就叫data就好了,好,后面是一个RRA类型的RDD,然后它有返回值吗?它是应该有返回值的,对不对?所以这里大家注意啊,计算RMSE当前参数对应模型的RSE返回是什么?是不是应该是一个double啊?呃,这个大家一想就能想到,这个计算肯定是一个double类型。
01:19
好,那我们把这个函数来做一个实现,里边大家会想到,首先我是不是先要去求这个预测评分啊,是不是根据我当前这个model调用它的predict方法去做预测评分啊,计算预测评分,大家回忆一下我们计算预测评分的时候是怎么做的,是不是首先要拿到一个user movies,当时我们说这个有点像一个空矩阵对不对?呃,我们说是说叫空矩阵,其实大家想存储的过程当中中是怎么存的,他的user movies,其实我们就是把每一个u ID mid是不是取出来,最后放到这里去做评价的时候,这里其实就是一组u ID midd构成的,哎,一组这样这样的一个RDD,对不对,我们就把这个东西传进去了,那大家想我们本身的那个train data。
02:20
或者说test data,它是什么类型的数据呢?它是不是u ID mid,再加上一个RA,一个评分,真实评分对不对,所以我们这里是不是其实就是少了一个rating数据啊,啊,所以大家想其实就是这样的一个数据,那我们这里边其实也不用在迪卡耳机或者怎么样了,大家会想到啊,我们是不是直接。还是定义一个user movies啊,啊,我们这里叫user movies,或者大家这里应该叫product product对不对,Products user products就应该等于是不是我从data里边把它做一个筛选,这个里边本来RA数据是不是就是u ID midd,还有一个rating啊,还有一个评分对不对,我是不是就是把它的前两项选出来,就相当于是一个空虚帧啊,哎,所以我这里其实就简单操作,其实这样啊,把每一项做一个转化,转化成什么呢?是不是选择它的啊,大家看这是RA里边的标准结构是user product RA对不对,我们要选的是不是user,然后另外还有item里边的product,是不是就取这两个,这就相当于是用户物品的一个空矩阵,哎,所以我们接下来做预测评分计算的时候。
03:43
Predict RA。它就应该等于model,我们去调用predict方法里边是不是直接把user product传进去就可以了,哎,就是这样做计算就可以,这样就可以简单一点对吧?好,那呃,接下来大家会想到我是不是应该,哎大家想啊,这里边已经拿到预测评分了,本身它这个里边是不是有这个实际评分啊,啊,然后我们是不是对应的去减就可以了,但是大家注意我是不是应该得根据它的u ID mid。
04:20
把它做一个筛选啊,你得u ID midd匹配上的那个才能对应减对不对,你不能直接上来就减对吧?所以这里边我们就再做一个转换,我们想到什么这个匹配这种操作,大家想到什么,是不是想到连表查询这样的一个操作啊,我们做一个什么样的连接之后,有可能他们就一一对应上了,对,是不是内连接inner drawing之后是不是,如果我要是以这个u ID midd作为键值外键去做这个内连接的话,那大家想是不是就是一组u ID mid对应的真实值和预测值全拿出来了,哎,所以我们接下来就做这件事情啊,呃,以u ID m mid作为外键,呃,内连接对吧,Inner drawing做这样的一个。
05:20
事情,那首先我们定义一个就是实际的观测值吧,观测值我们叫observed,大家会想到我们要要做这个,呃,内内内连接这个实际实际观测。值和预测值,那这个观测值我们是不是应该它的主键就作为我们前面这个u ID midd拿出来作为它的主键啊,哎,Data点做一个map操作,里边的内容是不是还是每一个item,我们要把它转换成本来这里边的内容是不是应该得到大家看到得到的这个predict是不是一个又变成了一个rating类型的RDD啊呃,接下来啊,我们这里不是不是要predict啊,我们这里是观测值是不是直接拿这个,呃,就是data啊,Data里边的东西对不对,那么。
06:26
本身这里边的东西应该是什么呢?本来是user product ra3个都有,对不对,我们现在是要把它转成是不是前面是一个user和product,后边是一个RA这样的格式啊,所以我们把RA放在后边,前边啊,等一下我们就拿前面这个作为KK去group by了,对吧?大家能想到啊,就可以做这样的事情了,或者说我们直接拿前面这个做做drawing了,对不对,对吧,我们直接做照应是以前面这个作为K的,那这里是item。
07:02
点user后边是item.product转成这样的一个格式,那同样大家会想到对应的我们这个预测值叫predict的话,它是不是应该从predict RA里面去找啊,这就不是data里面去找了,对不对?他也做一个转化,我们转化成艾特一样,对不对?直接把它粘过来好,所以我们把它同样转化成这样的格式,等一下我们对这两个去做一个inner drawing的话,是不是得到的结果就是一个u ID mid,然后后边对应一个预测值,一个真实值啊,哎,所以这是我们的一个很好的一个想法啊,接下来我们要做连接了,Observe的,呃,内连接是不是直接draw啊,默认的这个连接方式是不是就是内连接好,然后里边draw应谁是不是predict啊,Draw应完了之后,大家想到得到的是内内连接得到。
08:17
得到的数据格式是不是u ID m midd,然后后边又是它对应的一组值啊,对吧,然后这这一组值应该是它的啊,大家会想到这是它的实际值actual和predict对不对,对吧?所以我们这里边连接完了之后就要做处理了,是不是可以做一个map操作,我们这里边模式匹配得到的值应该是。呃,前边是不是应该是u ID mid啊,后边就应该是actual和predict啊,我们这里边尽量不要定义跟跟前面出现过的这个变量相同的名字,对吧?啊,我们就就给它改一个名字吧,就叫pre吧,呃,然后我们做操作,做什么样的操作呢?后边是不是希望对每一个真实值和预测值去求差,然后然后是不是还要平均,就是还要平方,最后再求平均数啊对吧,求和求平均数对不对?所以大家会想到这里边我们做这样的一个操作join之后有个什么好处呢?是不是这个map之后直接就可以求平均数啊。
09:36
大家想一想是不是这样,里边我们都不用一个一个去叠加求和了,对吧,后边我们是不是,但是大家想到我要想求平均数,可以先把它算起来对不对?大家会想到你既然散起来,最后还要除个数,我是不是直接点命就可以啊。啊,这是不是也是可以的,对吧,对里边诶。命就是平均数对不对?我们当时的KM是不是均值啊,对吧?KK均值聚类,所以我们这里边直接点M,大家就可以认为是点sum,然后又除了一个个数对不对?哎,就是这样的一个计算,大家会想到这里边当然就代表什么,代表我们最后返回的值一定得是一个,呃,得是我们最后要做平均数计算的那个值对不对?我们根据什么做平均数计算呢?
10:31
是不是里边应该就是这个平方的平方差对不对?呃,就是差的平方对吧?差的平方,预测差,误差的平方,然后求和除以N是不是就是平均数啊,所以我们的这个命就把前面这部分都搞定了,里边我们是不是做一个差值计算,然后再平方就完事儿好,所以我们返回的是不是就是啊,我们先做一个误差计算啊,比方说error等于,这是不是就是实际的值减去预测值对不对?那最后我们要返回的内容是什么呢?哦,是不是就是error的平方啊,我们就error乘error,这是不是就是error的平方啊?所以最后一行直接返回,返回来之后求平均数,这是不是就是我们的误差平方的平均数对不对?但我们最后要的RMSE是是不是还有个根号啊,均方根误差对吧,不是均方误差,所以这里。
11:32
我们在外边是不是还得把它做一个求求根的计算,所以我们用什么样的方方法呢?是不是可以直接用script这个引入,大家看引入这个呃,数值计算里边的这个求根方法就可以了,对不对?我们把后边的这一部分都作为它的参数传入。好,那大家看,这样我们就做完了这个RRMSE的一个求解,大家觉得有问题吗?这个大家看这个SQ rt square root,这就代表我们外层的那个开根号对不对?里边的这一部分我们通过一个内连接,很巧妙的把它按照前面的u ID midd做了一个匹配,对不对?那大家想这个内连接之后,我对应的每一个u ID midd是不是后面应该是跟着一组,呃,这个actual和pre这样的一组,这值啊,对吧?大家会想到就是我们这里边每一个,呃,这个u ID mid都对应这样的一组值对不对?
12:49
然后接下来我们要做到要做的事情,其实就是把他们对应的这这一组值里边的误差算出来,然后去做一个平均求和,呃,求求一个平均值,那这里面大家可能会觉得觉得有点奇怪,因为我们好像这里面好像没有针对就是每一个。
13:13
没有针对每一个u ID mid去把它对应的那个误差算出来,最后再挨个求和,对不对?我们这里的计算方式好像有一点简单粗暴,对吧?我们这里面的计算方法是什么?是不是没有做聚合啊,大家看这里边是不是没有一个聚合的操作,我直接把所有的u ID midd对应的那个误差是不是全算了一遍,呃,那个平方,然后全部加起来了,那这个过程大家想跟我们这个公式有没有什么区别呢?有有有问题吗?这样算有问题吗?啊,大家可能想到就是在系数上可能有一些关系,对吧,就是系数上可能会稍有不同,但是大家想我们这里边要计算的时候,是不是也是每一个u ID midd对应的那个值都应该去做一个计算啊,那那大家想这里边如果说我们要做聚合的话,其实是想。
14:15
就是如果有u ID mid对应有不同的值的时候,聚合计算是不是才有效?大家想一下我们一般情况什么样的情况下再去做这个group by,就是不是前面我们的这个key对应有很多个值的时候,我们要去BY对不对?大家想一下,在这里边我们还需要group by吗?U ID midd。如果要是我们只只以UID做K,或者只以midd做K的话,那可能后边是不是还要group一下,现在我们是不是相当于一个u ID midd是不是对应到的就是一个一组真实值和预测值啊,因为我们前面做的是内连接对吧。
15:01
应该没有冗余数据了,对不对,所以大家看这里我们就没有做group这样的操作。大家要理解就是我们为什么这么写,所以直接选出来之后,每一个u ID m midd对应的就是唯一的一组真实值和预测值,然后按照这一组值,我们直接把它算出这一个误差的平方,最后是不是把所有u ID m midd对应的那个误差平方全算一个平均数,这就是我们的公式里边的这个内容啊,我们公式里边是不是也是对每一个预测平分,然后把它最后求和算了平均数,哎,所以这就是按照公式来做的一个方式。大家大家可以看到在呃SC代码里边去实现我们的数学公式,看起来好像确实还是有一点奇怪对吧?呃,就是有一些如果我们不能直接调一些数值计算的库的话,这种实现下来用,特别是结合一些算子去做计算的时候,大家可能感觉理解起来稍微有一点绕,不过没关系,这个相对来讲公式比较简单,应该还是可以理解的啊好,那我们现在已经把这一个代码就已经实现了,接下来我们就来看一看它的效果怎么样,对吧,让一下。
16:15
我们跑完之后看到输出的结果在这里,那我们就能看到这个最后的影特征向量维度还是取得比较多的啊,200个这样的一个级别,那这个拉姆达呢,大概大家看到也没有增长,有比它大的,有比它小的,对不对,最后取到的是0.1这个拉姆达,那如果我们得到这样一个结论的话,是不是应该在这里,我们就应该把对应的参数去做一个改变啊,那这里的rank我们跑的时候其实就应该是用200,那这里是不是就应该用0.1啊啊,当然大家如果要是完整的考虑的话,我们是不是应该把这个重新再run一遍,更新对应的那个推荐列表和相似度矩阵。呃,大家想到应该是这样的一个标准流程对吧,我们这里面节省时间就不需要再去跑一遍了。
我来说两句