00:00
那我们就讲基于英语翼模型的协同过滤推荐,那这一部分代码我们还是首先来梳理一下我们大概的一个想法吧,大概的一个想法大家会想到我们是不是就要用评分矩阵把它进行引语翼模型的训练之后得到两个小矩阵啊呃,在我们这里边,我们是叫做用户特征和电影特征,对不对,这是我们分解开的两个小矩阵,那么这两个矩阵如果我们拿到之后再把它乘回去,是不是就得到的是预测评分,哎,我们的思路就是根据这个预测评分就可以找到,诶给一个用户应该推荐哪些电影评分高的就推荐,对不对?诶,这是一个基本的思想,所以大家看其实这个算法整体还是比较简单的,就整个程序的架构还是比较简单的,那我们具体实现的过程当中,用什么样的思路来实现呢?大家看这里用文字已经给。
01:00
大家写在这里了,呃,这里一开始呢,我们就还是做了一个笛卡耳机,为什么要做一个笛卡尔机呢?就是我们要得到一个u ID mid的一个元组,因为大家会想到我们针对用户要去计算这个预测评分的话,是一个评分矩阵,对不对?那我们一开始是不是先得有一个空矩阵啊,相当于。大家想一下是不是这样,就是有一个有一组用户,有一组电影,他们构成一个空矩阵,然后我们把预测的评分往里填,这是不是就得到了一个预测评分啊,每一个用户对每一个电影的预测评分对不对?那这个空矩阵怎么得到呢?那大家会想到,其实这就是两个向量维度的一个。一一对应对不对?这其实就是一个笛卡尔机的求求笛卡尔基的一个过程,那大家也有可能会觉得,哎,这个过程是不是它又会这个耗费的资源会比较多呢?呃,当然就是本身求笛卡尔机大的数据量,做笛卡尔机的时候肯定会有这个问题,但是好在大家会想到我们这里边其实相对之前的评分数据而言,评分数据是我们有,呃,应该是几万条还是十几万条,对吧,那个数据是比较多的,那相对应评分数据而言,用户数量和电影数量是不是相对较少啊,这两个维度啊,或许我们还是可以接受的,那当然如果要是说他这个本身特别大的话,我们可能还需要做一些优化,呃,对于我们真正想要做的这个预测评分,大家能够想到是不是确实是的,对每一个用户和每一个电影都便利一遍去预测出来啊,然后我们再做最后的这个,呃。
02:46
就是筛选,然后截取出来预测评分高的这些电影,做出一个推荐,所以这一部也是不可避免的一部,那大家能够想到我们就是做这个事情,然后通过模型,我们把这个模型训练完了之后,你只要输入一组u ID mid,是不是就就应该产生一个评分啊,就应该得到它对应的一个评分,对不对啊,这其实就就已经是我们直接可以拿到的东西了,那接下来就是通过预测评分,拿到预测评分进行排序,那从高到低排出来的,我们要选取多少个,截取多少个,这就作为当前用户的一个推荐,对不对?那最后我们保存的数据结构,大家会想到应该保存成一个什么样的数据结构呢?
03:34
我们想着把这个推荐列表全保到保存到一张表里面对吧,一张表里边,那大家想这一张表里边我们的数据应该还是一条一条的啊,我们不能把整个一个矩阵保存进去嘛。大家想到本身推荐出来最后的结果应该是一个评分矩阵,截取一部分之后,是不是针对一个UID,就应该后面跟着一个推荐的电影列表啊,应该是这个样子对不对?那如果我们讲这样的一个一个数据结构的话,大家能够想到我们刚刚今天上午已经实现过的哪个数据结构啊。
04:13
大家想是不是跟这个top ten这个有点像啊,只不过我们top ten这里边是一个类别,后面跟了一组推荐列表对不对,这个列表里边是一个mid,然后跟一个它的那个平均评分,那我们现在是不是也可以类似啊,只不过前面就不是类别了,变成了UID对不对?然后后边同样跟上它的一组评分列表啊,那我们这个数据数据类型其实都可以不变的,对吧?里边的这个对象还是一个recommendation m mid score都拿出来就可以了啊,所以这是我们的一个基本的想法,然后除了这个推荐列表之外,我们跟大家说过,就是还有一个,还有一个副产品要做什么呢?就是为我们以后实时推荐打下基础,我们要找出电影之间的相似度对不对,因为我们说在这个电商,或者说电影的这种网站业务体系里边物品。
05:13
就是电影商品他们是相对比较稳定的,所以我们可以离线的把他的相似度直接全部算出来,然后我们实时如果来了,哎,用户看了一个电影评论,一个分数,我们是不是就可以根据电影的相似度直接给他做推荐了,这个就反应会很快,对吧?你如果来了一个推荐,我在线去算谁跟它相似的话,这个就很麻烦,所以我们希望在离线这部分直接把相似度计算出来,那根据什么去算相似度呢?矩,对,大家会想到之前我们不是分解出的两个矩阵里边有一个电影特征矩阵吗?那是不是根据它的每一个电影的特征,特征向量就可以两两去算它们之间的相似度啊?哦,那大家就想到最后我们存相似度矩阵,又通过什么方式去存呢?
06:06
这又是一个矩阵,我们最后应该不能说是把一个矩阵全存起来,对吧,我们最后还是存成一个表,一个表的话,那一行数据,一条数据应该是一个什么样的数据呢?呃,大家想到一个简单的想法是,我一条数据就是一个电影跟跟另外一个电影,然后还有他们俩之间的一个相似度。但是大家想到如果这么存的话,那最后这个表可相当大了,对不对,相当于是我们做过笛卡尔机之后的那个维度对不对,两边乘起来之后,两两匹配的那一个相似度都要列出来,而且大家会想到我们到时候去如果要选的时候,是不是也不太好选,我们到时候筛选做查询的时候,我们是一个什么样的场景呢?是不是来了一个电影,我想直接选出来。
07:00
跟他最接近的几个电影啊,诶,那大家想根据这个思路的话,我们是不是可以就针对某一个电影给他一行数据对不对,后边跟着的是不是就是跟他相似的一组电影,一个列表啊,大家想想是不是这样设计数据结构会比较合理?如果这么说的话,大家就又回过头来看,是不是跟这个还是很类似啊,哎,我们最后是不是这里的这个种类别就同样更换一下,更换成不是UID了,是不是变成一个mid啊。一个电影后边跟上它的一个,也有点像一个推荐列表一样,只不过是跟他最相似的列表,对不对,那里边的内容也是一个,呃,大家想到首先是应该有有一个mid,这是电影对吧?那是不是相似度还应该有一个计算值啊,哎,那大家想刚好嘛,你这里scar,我就把那个相似度填成这个评分,是不是一样的数据结构都可以重复利用啊。
08:01
啊,所以大家就会看到,这就是为什么我们之前单独把这两个定义出来,因为后边其实我们都可以重复使用啊,这是我们整体的思路,当然最后我们要把它对应的写到呃,Mango DB里边,好,那既然这个思路都已经有了,接下来我们新建一个模块对不对?这个模块我们就叫做啊,我们跟文档里边写的一样吧,就是把这个跟因为它都是个性化的一个推荐,我们就把这一部分跟后边的实时推荐做一个对比,这一部分叫offline recommender,尽管我们知道前面讲到的统计推荐也是离线的,也是offline的,对吧?啊,只不过我们这里或者大家叫一个复杂一点的名字,就是基于英语一模型的协同过滤,对吧,也是可以的,我们这里就简写了啊,Offline,好,我们把这个项目子项目创建出来。
09:00
然后创建出来之后,首先我们要考虑的就是依赖了,大家想一想这个基于盈运一模型的其通过率推荐,它需要哪些部分呢?哪些这个依赖呢?首先我们大家想到你既然都是推荐嘛,那这个本身在在这个统计推荐里边,我们已经引入的一些依赖,很可能这里边很可能很多东西都要有,对不对?大家想一下这里边Spark号要吗?要对吧,Spaq也要对吧?因为大家会想到这里边如果我们用到了,呃,前面我们给大家提到这个,我们往里边写数据的时候可以直接调用,呃,Data frame writer对不对,Data frame writer是在哪里的,这大家知道吧。我们这个这个write方法,这里是不是data frame writer啊,这是在哪里的?这是不是就是在Spark CQ里边的啊,对,所以大家注意这些其实都是Spark CQ下面的,呃,这个类啊,好,所以我们现在如果说大家考虑的话,Spark call Spark CQ都要,那大家想想还要引入什么东西吗?跟Spark相关的,对,大家想到我们既然在里面要训练营语翼模型,那要调用as算法对不对?我们难道准备手写一个as算法吗?啊,显然我们不会这么做,所以我们当然是要电调这个线程的库,对吧?那么从哪里调呢?大家已经想到了,是不是Spark ML lab啊,机器学习库对吧?所以这一下我们终于把ML lab用起来了,呃,然后大家想到这个skyla library要吗?
10:43
啊,这个常规的我们就一般来讲都是要的,对吧,然后接下来大家想这个mongo相关的这个驱动,还有这个呃,Mongo Spark connect connector这些需要吗?啊,我们都要跟mongo去做交互,对吧,读数据写数据,所以说这个这些都是需要的,好那么我们先把这部分先直接copy过来。
11:06
所以就是大家抄这个内容的时候,我们也要也要会抄啊,我把这个data loader先关掉吧。Recommend,关掉offline这里啊。好,那么大家会想到我这里边还需要一个什么呢?我直接从这里边copy啊。是不是还需要一个Spark ML live啊,我把这个拷贝过来。另外大家其实呃,如果比较仔细的话,大家会看到在这里边还多引入了一个依赖,引入了一个什么呢。大家看到这里引入了这个啊,Plus就是我们一开始给大家,呃,这个定版本的时候是不是把它也写在里边了,对,这个是什么来着?Java里边的一个跟线性代数相关的一个库,对不对啊,那里边我们要做矩阵运算的时候,是不是需要用到这里边的内容啊,大家想到这里边我们是不是要算相似度矩阵的时候,是不是两个向量要去做相似度计算啊,那是不是很有可能用到这里边的东西,诶,所以我们把这一部分也要引入,那剩下我们再看一看啊,Spark Co spaicq skyla library,还有mongo相关没了对吧?好,所以我们要引入的就是这些dependency。
12:37
这部分做完的话,接下来我们就准备要呃这个真正的写代码了,在写代码之前,我们还是跟之前的这个套路一样,是不是这个resources下边把这个log for properties文件copy过来对不对?好,先放过来,然后大家会想到还有呃,这个Java目录看着不爽,对吧?每次我们都改一下吧,当然大家可以可以去自己新建一样的,对吧?你去指定一下这个south folder就可以了,呃,然后我们是不是在这里边就可以去新建一个skyla class拉,同样大家想一下我们这个class应该是什么样的呢?是不是还是object objective啊呃,所以我们这里边其实离线的这部分,这部分程序其实就是离线的跑一遍,然后就就完事儿,也不会有任何的地方去引用到它,对吧?也不会有任何的地方去调用它里边的方法,所以它完全就是一个单例对象,我们同样把它定义出来,当然了,这里边我们还是加上包名at硅谷到呃,Sta,诶,这这不是statistics了,Offline,对吧,我们就用它的本身的这个前缀名字作为它。
13:55
呃,报名的这个最后一集,然后recommendation recommend,好,OK,所以我们现在创建了这样的一个单立对象,接下来按照我们之前的路数,那还是是不是先去看看有哪些样例类可以抄过来,对吧?大家想一下我们这个基于英语义模型的这个推荐这一部分我们需要什么样的样例类呢?我们先看一眼这个统计这里用到了哪些吧,统计这里我们需要用评分数据啊去做统计,需要电影的那个类别信息,所以把movie和RA全加载进来了,对不对?那这里我们需要什么?
14:47
大家想我们做这个盈余模型的协同过滤,协同过滤我们基于的数据就是平分,对不对,那movie数据有用吗?嗯。
15:02
大家会想到如果要有用的话,那可能我们就是从里边看到底有多少个电影获许有用对不对?嗯,就其实它里边的其他字段看起来好像一点用都没有对吧?哎,所以我们其实可以不引入它,但是大家引入也可以啊,就是大家可以看到文档里面如果没改的话,是不是这里还引入了,对offline这里还引入了对吧?那这里边大家其实可以想到我的核心是RA数据,那其实movie我不引入也是可以的,好,那我就直接把RA copy过来。当然了,这里大家可以想到我们的原因就是说呃,就是基于评分数据的盈余模型对吧?呃,那只需要只需要呃评分数据RA数据,这里大家要稍微注意一下,大家会看到,呃,如果有同学细心的话,大家会看到我们这里边定义的评分数据不一样了,对吧?改改改名了叫movie rating,这是为什么呢?
16:21
稍后我们其实会遇到,呃,就是这里先给大家提一句,因为本身在ML lab里边,之前跟大家说过就有一个叫做RA的一个类,对不对,就有这样的一个数据结构,这是他为了做,呃,就是as算法里边,我们是不是要传入一个标准的一个评分对象啊,所以它是用这个rating本身就作为这个标准的评分对象呢,所以我为了跟他做一个区别,当当然也可以加上这个这个引入的包名什么的去去命名空间指定,对吧?但是我们为了更明确一点,我们很简单嘛,给它加一个前缀,把它区分开就可以了,所以大家知道这是我们自己的这个定义好的样例类,Rating的这个样例类,而不是ML lab里边定义的那个rating类型,对不对啊,这个大家知道就好了,好,那除了这个rating之外,我们还需要什么东西呢?下面是一个mongo的。
17:21
这个样吗?Mongo的配置,哎,我们既然要操作mongo,那大家想到这个是不是应该需要啊,保留,然后接下来看看还有什么可以抄的啊,诶大家看这里边是不是有这个recommendation这个基准推荐对象啊,前面我们是不是已经想到我最后推出来的那个用户推荐列表啊,基于英云模型预测评分之后,推荐列表是不是跟下面这个很像啊,那这个里边是不是也应该基本的每一个元素是这个recommendation啊,诶,所以我们就照着这个先抄一遍,然后我把这个改改名是不是就差不多了?好,我直接把它抄过来啊。
18:02
所以这个代码是可以抄的,但是我们一定要会抄上面的recommendation这个不变,那下边这里我们就不应该叫他这个了,对吧?我们这里边定义的是呃,用户定义基于预测评分的用户推荐列表啊,那大家会想到这里边我们给一个名字也也不要叫这个了,是吧?我就直观的叫了啊,就叫user res recommendations对吧,用户给用户的一个推荐列表,那大家想到前面这个就不应该是类别,而应该是对UID了,对吧,那UID就是一个int类型,后边诶同样一个推荐列表,是不是这个可以不变啊,然后里边每一个元素它它是一个列表啊,里边每一个元素都是一个recommendation啊,这没问题对不对?好,那然后接下来大家会想到。
19:07
我是不是还有另外一个副产品啊,对另外一个副产品是电影相似度,我们相似度前面已经想好了,它的形式是不是跟这个很类似啊,我们是不是可以把它当成对每一个电影推出来跟它相似的一组电影啊,哎,所以我们就直接把这个再抄一遍。基于。基于呃影羽翼模型里边电影特征的特征向量对吧,向量的电影相似度列表对不对?哎,这是我们要要做的另外一件事情,那这个我就简单改一下吧,你前面这个不是叫user recommendations吗?我下面是不是相当于是对电影做了一个推荐啊,相似的推出来了对不对?哎,我们直接定义成这个就可以,那前面不是UID了,换成m midd,后边是不是还是一样这样一个recommendations里边每一个都是一个recommendation啊啊,所以大家看到这其实就是我们在基于引语翼模型的协同过滤推荐里边定义好的一些样例类,都是借鉴了我们之前已经做过的这些,呃,这个数据结构的定义,好,那定义好了这些之后,我们进入到这个单立对象里边来。
20:32
一开始是不是还需要定义一些表名啊,大家会想一下我们这里边需要定义什么表名呢?看一下movie rating这两个药吗?Rating是不是肯定需要对吧?Rating肯定需要movie的话,呃,不好说,说不准,说不准我们不需要对吧?呃,所以我们可以是不是先把这个rating拿过来就可以了,然后接下来我们在这个统计这一部分是定义了几个统计表的表名,那大家会想到这里我们需要去定义什么呢?不需要定义统计表的表名了,对吧?我们是不是要把最后写入到mango里边来的这这两个列表。
21:19
对应的表名要写要要定义出来啊,那这里边我们就跟前面的那个,呃,定义类似吧,我们就叫user好了。呃,这个变量就定成这个名字,我们也就叫userx,就是针对用户的推荐列表,对不对,然后另外我们定义一个叫movie res。Movie Rex,好,呃,另外大家会想到这里边可能还涉及到一些常量,比如说什么常量呢?看一眼文档里边给了什么定义。
22:03
啊,大家看到这里边是不是定义了一个叫做user max recommendation啊,这代表什么啊,对,是不是就是我们,诶最后不是有一个推荐列表吗?你到底给推荐出多少来对不对啊,所以诶,那他想到那我是不是可以那个movie的那个相似度也可以做一个选取呢?啊当然也可以,我们这里边的话可能就是到时候我们根据大于多少的选出来,是不是也算一种筛选,对吧,就不按数量来筛选,按相似度大于多少来筛选,好那这里边我们把这一步copy过来,定义出这样一个常量,这是定义表明和常量,当然了,表明对于我们而言也是一个常量,对吧?接下来就可以写我们的入口方法了,一个main函数,按照套路,一开始是不是先把这个配置相关的信息copy过来啊,大家想这一次我们的配置跟它。
23:03
有需要改的地方没有?首先这几个要不要Spark call Spark需要对吧?然后mango UI mongo DB是不是都要啊,所以这些照抄,那大家会想一下还有别的东西需要吗?配置相关的一些东西,可能这个相关的一些东西,好像现在能想到的也也没什么了,对吧?啊,能想到别的的话,那再说,所以现在我们直接照抄过来就没事了,那然后接下来我们是不是应该去创建Spark的配置啊啊,当然这里边就是还是Spark conflict对不对啊,大家如果要是对这个已经已经写的太熟悉的话,就直接照抄也是没什么问题的,当然这里边后边肯定就是set,呃,Name set master对不对,我们直接从这边抄过来吧,不用。浪费时间写这个,当然我们得知道哪里需要改,对吧?诶,这里边我们刚才看到的这里好像没改,对不对,大家看这个APP name正常来讲我们是不是应该改一下啊,对吧?一般用的就是当前的这个类名statistics recommend。
24:25
好,那这里我们直接把这个copy过来好了,这个写太费劲啊,好把这个Spark f先创建出来,然后下边大家会想到这个其实都一样,对不对,我是不是创创建Spark session,然后呃,该引入这个,这个影视的类还是要包,还是要引入,对吧,后边这个mongo是不是可以照样传入啊啊,所以这些东西其实都是一样的,我们就直接copy过来好了。
25:00
哦,这里边我们要引入这个哦,这里大家注意,我们前面的这一步当然是需要去引入了,后边这个从statistics里边去引入monggo是不是就没有必要啊啊大家稍微注意一下啊,不要很简单的直接全把它copy过来,那上面就报错了,所以我把这个删掉,因为我们自己这里是不是定义了这个猫conig啊,当然大家如果要是觉得我们可以在另外一个比方说公共类里边去定义,把这些东西全抽出来是不是也可以啊啊,那样的话整个代码的抽象性会更好一点,我们这里的话就各自为正,因为它们互相之间没有和关系嘛,所以我们就直接把它这个呃,各自抽出来就可以了。接下来按照之前的。过程我们是不是应该加载数据,然后就是接下来这个推荐的过程了,对不对,大家看这个图度我们就可以删掉了啊。所以在这里我们接下来也是需要去加载数据。
26:06
加载数据这这一步大家想一下我们需要加载哪个数据呢?我们最重要的是不是就是rating数据啊啊,那这里边大家看我们借鉴这个统计推荐里边的内容,它加载数据的时候,诶是不是最后转成了DF啊啊,但是我们这里边大家也可以把这个直接先copy过来类似对不对。呃,大家看这里边又有这个RA statistics里边的一些一些配置,对不对,我把这两个要这个要删掉啊。那大家会想到,首先我们,呃,在读取数据的时候,我们还是要传入这个option,我们调用这个space session的read方法,对吧?然后给他传进来这个option uri collection name collection name是不是还是这个reading collection啊,这些东西都没变,然后我们下面format是不是还是mon DB Spark CQ啊,下面点漏数据加载进来,接下来我们as是不是就不是RA了,因为这里边我们做了一个改变,对吧,是不是这里叫做movie rating啊,好,然后当时我们是把它转成了一个DF。
27:22
那现在我们可能不是要把它转成DF,而是要把它转成RDD,为什么呢?这个主要就是我们后边调用als算法的时候,参数数据,参数要求传入的是一个RDD啊,所以我们要按照后面需要的这个要求来,对不对?所以这里可以直接是不是点RDD把它转过来啊,当然了,转完了之后我们还可以去对它做一个操作,Map成最后自己想要的一个一个状态,对不对?那么我们把它map成什么样子呢?大家会想到这里边每一个都是一个评分数据,对吧?我们最后想要的是一个什么状态?
28:05
其实只需要u ID mid,还有一个评分对不对,那大家想一下,我们现在的这个movie rating里边是不是不止这三项啊,后面还有一个时间戳对吧?哎,所以我们的转换就是把不需要的东西先给它去了啊就完了对吧,先做一个就是数据的精简清洗。RA点,呃,第一个是不是应该是UID啊,第二个是mid,最后是一个score对吧?诶这就是我们转换之后的一个数据,做一个在这里写一条注释啊。呃,转化成RDD,并且。呃,去掉时间戳。
29:06
好,那么大家看到在这里我们已经做完了这个转换,最后如果说我们需要这个基于这个性能的考虑的话,大家会考虑到我们前面讲的时候,后边是不是要做大量的就是这个求笛开耳机的过程啊,这一步可能对于性能而言,我们需要加一些缓存,做一个性能提升,对吧?啊要不然的话,呃,有些东西这个就到时候我们肯定会出现一些内存不足的状况,或者说GC的时候就会出现问题,对吧?所以我们加一个点catch把它呃持久化在内存里面,RDD持久化在内存可以直接点catch,对吧?这些大家应该之前都是讲过的内容,那当然了,我们这里既既然是已经转成了RDD,这里就不要DF了,对吧?RARDD,这样,这是不是就是我们的原始的评分数据啊,好,这一部分就已经搞定了,然后接下来大家会想到我们后面不是还要做预测评分吗?预测评分的时候是不是要user和。
30:06
Mid,所有的user,所有的mid,呃,就是所有的UID,所有的mid,它们之间是不是要做一个底卡耳机两两配对传进去一个空矩阵对不对?那么这样一个空矩阵,我们一开始其实拿到的是不是也应该是user的一个RDD和movie的一个RDD啊,里边就是只要UID和mid对不对?而那大家会想到这这个东西我们从哪里去取呢?User从哪里取呢?我们又没有user表。呃,大家会想到,哎,你没有没有user表,但是我们评分数据里边有UUID啊,对吧?而且我们关心的最后要预测的是不是就是已经评过分的那些人我们才关心啊,因为没有评过分的那些人,大家想到你如果带进去是不是就他就没有特征向量啊,对吧?那他如果没有,我们之前也说过,本身这一套系统基于盈余模型的协同过滤,它是依赖于历史评分数据的,如果要是来一个新用户没有从来没有评过分的话,那是不是就没有办法对它做出预测啊,这是我们讲的冷启动问题,所以这里既然是这样,那我们所有的用户是不是从RARDD里边把那个UID筛出来就可以了呀?好,那么我们这里,呃,RDD就比较简单,可以直接user r DD等于对大家知道RARDD,我们是不是做一个map就可以了,我们要。
31:39
选的是它里边的哪个元素呢?是不是它里边的啊,UID是不是第一个元素啊,对我们把第一个元素拿出来啊,当然我们本身这个评分数据里边一个用户是不是有可能给很多个对movie movie都都做过一个都做过一个评分啊,那我们这里是不是想要做一个去重的操作。
32:03
对,是不是有一个这个distinct可以做驱虫啊,对吧?啊,当然大家如果要是觉得这个也很大,想要去做一个catch的话也可以,那我们这里边的话,呃,正常来讲应该是没问题的啊,因为这个用户没有太多,同样我们是不是想到movie,每一个所有的mid从哪里去取呢?我们是不是也可以直接从评分数据里边的mid类似的做一个操作啊,把它全拿出来是不是就可以了,那大家可能会想到,诶,那有些movie它本身没有评分,但是在我们的那个movie表里边有那个需要拿出来吗?因为没有评分的movie,你是不是也没办法对对它做预测啊,哎,我们依赖于历史评分数据对不对,所以这一部分我们也也可以不考虑,当然大家也可以说我把那个movie表读进来,然后再把movie表里面的所有的那个movie全算一遍,呃,就是全全提取出所有的那个mid来,那大家会想到可能比这里边的mid要多,对吧。
33:09
那得到最后那个表可能会更大一点,但是大家想这个是不是没有太大必要啊,因为我们多出来那部分都没有评分,那你最后肯定都是,呃,都都是零对吧,都没什么意义,所以说我们可以把这一部分简化,RA r DD map,取它的哪个值,我们现在要的是不是mid mid是第二个值,同样我们做一个distinct。所以这两步是从rating。数据中提取所有所有的UID和mid,并且去重,对吧?这是我们做的事情,呃,这一部分做完之后,大家就会想到我们的需要的数据是不是就都已经搞定了呀?
34:10
哎,我们到时候做模型训练是不是需要这个评分历史的评分数据,然后做模型预测的时候,是不是需要这个空矩阵啊,对吧,把这个user r DD和M,呃,Movie r DD做一个笛卡尔机是不是就可以做预测了,诶所以我们想要的东西都已经有了。
我来说两句