00:00
好,那么我们现在根据备选电影的mid作group,然后呃,根据公式去求最后的。呃,就是我们的这个推荐评分对吧。呃,那这里边我们肯定是要从scores里边去做计算,是不是scores直接可以。呃,大家想这里面我们group什么呢?是不是每个元素应该是按照第一个存储的这个mid去做group就可以了,那这个得到之后,大家想到是不是拿到的东西应该就是说一个mid,后边是不是应该是一组score啊?而且大家会知道这个返回的应该是一组mid score这样的,因为大家看这是一个这个数组的一个group对吧,返回的是一个一组的,我看一眼啊。
01:16
是不是应该是一个imutable map这样的数据类型啊,所以我们返回来的内容应该也是一个mid后边还跟着一个啊SC这样的一个对象,对吧?所以我们这里要做的操作再把它做一个map case啊,我们应该拿到的是什么呢?Mid后边是不是就是一个score list呀,一个评分列表对吧?那接下来我们是不是这个score list里边的所有的评分拿出来,然后去做一个,呃,就是求平均数,或者说我们拿到之后去求一个sum,是不是就可以算出它的那个一开始的那个基基础评分项了,第一项最后这样一个加权平均数对吧?我们前面只是把它列出来,没有把它就是最后还还求出那个加权平均值,所以我们现在是要做这件事情,好,那么对应的这个。
02:16
里边的东西我们怎么去做计算呢?呃,大家会想到我是不是要把最后得到的东西啊,Mid是不是还应该是mid对吧?这是我们最后要返回的,也是一个类型,对不对?呃,Mid还是mid,那后面这个list我们就要做变化了。Score score list score list,呃,大家会想到它里边是不是我们应该去把所有的score做一个求和啊,啊,大家会想到我应该是要做一个sound,但是这里大家注意score list本身拿到的是什么东西呢?他拿到的是在这里给大家写一句啊,Group by之后得到的数据。
03:13
是什么样的,什么样的一个数据结构呢?是一个map对吧,我们刚才是不是已经看到了,然后它得到的是一个mid,对应着什么呢?对应着我们之前这里边的一个。这个瑞buffer对不对,整个的这个数据结构,它是这样做了一个groupd group buffer里边是不是还是一个mid和一个score这样的一个组合啊,所以我们现在score list是不是其实是后面这个re buffer啊。那现在我们怎么做?算第一项,那是不是还是得找到它所有的D,就是每个元素是不是我们要用的是第二个这个score啊,对吧,这个mid其实没什么用,我们要的是这个score啊,那所有的score是不是就直接可以做一个sum求和,然后大家想到如果我们再除以哎,它的个数,那其实就是score list.lesss对不对?这是不是就做了一个加权平均数的求求求解啊,这就是我们的第一项对不对?诶,然后后边加上偏移量,第二项是什么?
04:37
第二项是看公式,是一个log里边是它的那个,呃,求出来的那个count对不对?我们这里边是不是把它放在了increase map里边啊,啊,我们当前的这个m mid对应的那个increase map里边的那个数,是不是就是这里我们要查的那个数,哎,所以我们要找的是increase map里边的啊,大家会想到我如果直接去找m mid的话,也有可能找不到对不对?所以我这里边还是再来一个get or default mid,那如果要是找不到的话,我默认应该给几呢?
05:19
啊,大家会想到我这里默认是不是要求不能为零啊,因为外边我是不是还要有一个log这样的一个计算啊,所以我就把它做这样的一个操作。大家看是不是这样啊,当然了,这个log我这里你要不去引入这个数学相关的函数,要不自己去实现一下对不对啊,这就就就是这样的啊,所以其实我们就是这样的一个表达,那后面大家不要忘记是不是还有一项啊啊对,再减一项,我们把这个直接抄过来啊呃,这一部分是不是大家感觉相对还是有点复杂啊,就是我们实现为了给大家讲这些算子,所以就看起来这个公式还是有点长了啊,就对这个公式的时线有点长了。
06:08
呃,所以在这一个map操作全部做完之后,我们最后是不是已经得到了最后想要的这个结果啊,我们想要的是不是就是一个mid,后边一个double类型的一个评分,这个评分是不是已经完整的算出来了,每一项都算出来了,对不对啊,前面是一个加权平均数,后边就是它对应的一个计数,然后做了一个log。好,那大家注意,最后我们是不是还需要把它再转回成一个AR啊,对,这里再做一个点to RA,对。诶,这里是不是对的啊,是在这里做对吧?呃,那么做到这一步的话,大家就会看到我们的这个函数就完全结束了,就完全实现了,那当然里边我们看着上面这个还在报错呢,一直看着不爽了,对不对?呃,那大会想到这个我们去DeFine一个get movie嗯,这半天好,那大家会想到我们这里是不是就是传进来的是两个mid啊对不对,MID1和mid二传进来,我们是不是就可以从相似度矩阵里边把它找到了啊,当然了,这个相似组矩阵我们还是用这个东西啊。
07:35
呃,这个我们把它单独的提出来,然后大家会想到它的返回是不是应该是一个什么类型。大家忘记这个是做什么了是吗?Get吗?我们要get肯定有返回值对不对?我们是要做什么来着,是不是要获取这是推荐评分吗?这是我们这里定义的这个东西,对不对?是不是要拿到相似度啊,所以我们就是获取两个电影之间的相似度对不对?
08:12
就是做这个操作,呃,所以这里边我们传进来的就是第一个电影的ID,第二个电影的ID,最后是不是还有相似度矩阵啊,尽管看着比较长,但实际上很好理解诶。我们把这个参数有点多,把它反反下来吧,呃,然后后边大家想到是不是这个相似度应该是一个double类型啊好,那大家看一下这个东西怎么实现,应该没问题吧?呃,大家其实想到其实就是从c movies里边是不是直接去对,直接去找就可以了,所以我们就直接get是不是mid啊呃,那大家会想到就是这个get我有可能有可能拿不到对不对,我们重点其实就是想要去去处理它的一些异常对吧?呃,大家如果说这个东西我如果直接能能拿到的话,是不是get.get就可以了呀,继续在get midd2对吧,直接返回就可以了,那我们这里要处理它的一些异常状况的话,我们去做一个这样的模式匹配match一下,那大家会想到假如说它有值的话。
09:26
对吧,SIM这是个列表对不对?有值的话,我是不是应该就返回seems,再去get是不是m mid2啊,对,当然了,这个m mid2是不是也未必有值啊,所以我们是不是再让他match一下来看,我们就写成了这样一个一个过程,对不对?同样下边是不是还是case,如果是拿到了一个具体的score的话,或者叫对不对,我为了区别我就叫score好了,我最后返回什么?对,是不是直接就是返回就可以了,给家看写了这么多,其实很简单,其实就是从这个我们的map里边get一个,再get一个对不对,那大家会想到你这里是case了,这个sum,那如果要没有呢,如果是呢,返回什么?
10:24
相似度没有的话,对返回零,对,大家注意这是个double类型,我们返回一个0.0对不对,好,就是这样的一个过程,那当然了,就是外边这里边有一个kiss,那我们这里也去kiss一个nu对不对。是不是这里也是直接返回零就完了,是不是查不到的话直接返回零,所以这个呃,看起来有点绕,但其实还是很简单的啊好,这个实现完了之后,大家看上面是不是就已经没错了,看起来没问题了啊啊另外还有一个很烦的,这个取对数,这个我们是不是还得再再去把它搞一下啊啊,大家如果要是直接引那个,就是我们ma里边的东西也是可以的,这里边的话我们再给它定义出来,定义出来有什么好处呢?就是我们可以把这个也作为模型的一个参数去调整,对不对。
11:14
哎,大家说这为什么也可以作为模型的参数去调整呢?取对数,你取谁的对数?底数是不是可变啊,大家想到这里边如果给的这一个底数不一样的话,我们的这个增强因子,减弱因子是不是对前面的这个影响就不一样啊,那大家就可以调整它对它的影响大小对不对?所以这其实如果我们把这个看成一个自定义模型的话,这是不是相当于模型的一个超参数啊啊,尽管这里面我们没有把它就是完全这个超参数提出来,但大家知道这里我们其实可以调节这个东西的,那大家就会想到,呃,我这里就定义一个,比方说我们传入一个M,要求它的log,是不是这应该返回一个double类型啊好,呃,这里是求一个数的对数,呃,这个我我们这个底底数默认为啊,默认为十对吧?那大家想到我们要改参数的时候,是不是改这里面的底就可以了啊,这里就。
12:21
不详细,把这个作为参数传进去了,大家知道就可以,那大家会想到我是不是可以直接用SC里边的mass这个库,大家看它本身就有log对不对啊,本来就有这个log这个方法,那么大家知道以谁为底,是不是相当于它对应的这个log啊,大家看它它里边是不是本身就有这个LOG10啊,大家看下面是不是有LOG10啊,对吧?所以大家可以想到我随便去调用这样的话,它其实就是要以自然对数或者是常用位数对数为底的,那我们如果以某个数为底的话,我这里边是不是就传传入进来这个数啊,叭方说我这里边给大家定义一个啊,呃,我们把这个底数叫N,那么这里边N等于十,所以我们这里边就除以log n对不对?那我们如果要是把这个N变了的话,大家想一下,是不是整个的这个求法就不一样了呀。
13:20
大家知道这个对数的底的这个转换是不是,呃,大大大家不记得这个公式了是吗?呃,那那给大家查搜搜一下啊,我们。我们把这个这个删一下啊,呃,对,这个叫对数运算法则,是不是我们看一眼啊。这个应该属于高中数学里面的东西,对不对对吧?呃,这个对数运算法则,诶这里好像不是很全啊。大家看这里边它有一个是说log以A为底M的N次方,可以把这个N次方提到前面来,对不对?另外还有一个大家大家记得吗?是如果要是log以A为底的M除以log以A为底的N等于什么?
14:20
括我我们看看能能能不能找到那个公式啊,呃,哎呦,这个这这个下来之后大家自己找吧,这个确实是,呃,大家大家如果忘记的话,就是我们回忆一下就行,或者是我们这里边大家如果默认是十的话,我们直接叫那个ma log10就可以了,对不对啊,这个大家不要太纠结了啊,这就是一个基本的一个数学问题,好,那接下来我们还还差什么,现在看起来好像都已经实现了,对吧,还差什么?哦,上面还有一个是不是还有一个保存到mongo,这个还没搞定啊,我们最后推出来的这个,呃,Stream ras,这已经是一个,就是一个m mid跟着一个推荐评分,一个score这样的一个列表了,然后我们再结合这个UID,是不是最后把它存到man里面去啊,好,那最后我们再来做一个计算,做一个保存,那这个叫save save什么来着,Data to mongo DB。
15:20
呃,这里大家会想到我是不是前边这里传入的是一个UID对吧,后边这个是一个。是一个stream ras对吧,我传入的是这样一个东西,然后大家想它有返回值吗?没有返回值,那另外我们这里是不是大家想到还会用到跟mango相关的东西啊。为什么呢?因为我们是不是,呃,对,但但大家想到就是在在这个里边啊,就是我们是直接把它直接存进去吗?之前我们是调用data frame writer,那大家想我就得把这个再转成一个data frame,对不对啊,然后保存到对应的那个列表当中去,这里大家注意我们列表里边是不是有可能已经有这个用户的推荐列表了啊,当然我们也可以直接用overri,对吧,定义mode overri,然后直接把它往里边去写,但是大家会想到我们在mango里边ID本身的每一条数据的那个主件是不是也是有一个下划线ID的那个来定义的,它不是按照我们这里的UID定义的,对不对,所以它是不是你再插一条,它认为还是不同的数据啊,所以每一次你往里保存的时候,是不是总会再多增一条数据,不会把之前的复对吧?啊,所以为了实现我们把之前的那个。
16:49
要要处理掉的话,那我们是不是还是得用mongo client相关的一些东西去做处理啊,啊好,那么当然如果我们还要用到这个mongo,大家想到往这个go里边写数的话,我们要用到mongo con里边的一些配置对不对啊,那这个还是按照我们的常规,把这个影视的mongo con也放进来吧,后边诶,大家会想到是不是就没有什么东西啊,不需要有任何的返回对不对,呃,然后接下来我们先。
17:24
先定义定义到呃,这个stream res这个表的连接,我们先相当于把它这个就是DB.class name这步先做完对不对?定义到这个表的连接,那我们先把它写出来,就是这个。呃,Stream res collection,大家会看到这是我们可以定义这个client的一个操作,那要用到连接助手,它里边是不是有monggo client mongo client里边我们给的前一个参数是不是应该用到mongo里边的DB啊,Recommender,对吧?后边是不是?呃,可理化第二个参数mongo DB,把这个表名传进去,大家看这是不是相当于就是DB,点这个表名我们先定义好啊,对吧?
18:30
接下来我们是不是直接就可以用这个表名直接去做find,做呃或者做其他的操作了,接下来我们要做的一步是如果表中已有呃UID对应的数据是不是应该删除啊,先把它删掉好,呃,那我们这里边的做法就是stream,呃,Res collection直接点find,呃,大家看是不是还可以find and remove啊,这是不是就像我们的那个呃,就给大家做的那个点remove操作一样,前面是不是可以加一个query条件啊,查找到然后把它删掉,所以这其实做的是一样的事情,那这里边我们要给的是不是也是一个查找条件,这个查找条件是不是跟前面我们再去查找,他最近评分过一。
19:30
您看过的这个数据的时候,给的这个条件应该一样啊,是不是也应该是UID,等于当前UID把它包成一个mango DB object对吧?是这样的一个过程。好,把它放进去,这样是不是就已经查出来并且删除掉了,呃,接下来我们就是将呃,真正的这个推荐列表,这个Rex数据存入表中,那当然了,这个存的时候我们也可以啊,也可以大家不用这种方法,不用client,呃,那个客户端这个mongo client的方法也可以直接用我们那个data frame writer对吧?呃,我们这里的话,既然已经有现成的这个client了,我们就直接还是调它的insert方法,是不是直接可以把数据插入进去,那这里边insert,我们怎么insert呢?
20:26
是不是还要把它包装成一个monggo object,呃,Monggo DB object这样的一个数据结构啊,它里边就是所有操作的对象都是这样的一个数据结构,那里边我们要插的是什么呢?是不是一开始有一个是UID对不对,这个UID是不是就是这里的UID啊?另外后边我们是不是还有一个字段叫做是不是叫做Rex啊,对,那么这个字段我们要给的是什么东西呢?啊,大家会想到是不是要把stream ras传入进去,Stream ras大家注意这里边的东西是不是还是一个int double这样的一个元组作为类型传进去的,我们要把它传进去的话,里边这个也得转成一个mongo DB object,这样查出来我们在mongo里边才是对应的KY6,对不对啊,要不然的话是不是这个。
21:27
这里边的mid和这个,呃,后边我们的这这个就是SC,是不是就没有办法对应起来了。大家就不知道它的那个本身的那个名字字段名字叫什么了,对不对,所以我们要做一个这样的转换点。里边每一项做什么操作呢?把它转换成一个mongo DB object。里边转换的内容是什么?是不是一个mid这样的一个字段,我们要的是什么呢?X的第一个元素是不是mid,然后还有一个字段是不是叫score,我们要的是X的第二个元素,大家看这样是不是就是我们最后得到的一个东西啊?
22:21
大家如果看着这个太长的话,我们还是把它回车回过来啊,大家看就是这样的一个处理,我们最后插入到表里边的整体的结构就是UID,这个字段对应一个UID,然后后边表示对哪个用户做推荐对不对,后边是整个是一个列表,这个列表里边又是什么样的形式呢?这个列表里边每个元素包含两个字段,一个字段叫mid,对应的是这里边spring ras里边的每一个第一个元素对不对,然后还有一个字段叫SC,对应这里面的第二个元素啊,这就是我们最后写进去的一个状态。我们现在就已经把它彻底完成了,大功告成,那接下来可能就是去我我们做一个测试了,把它提起来对不对?这个测试可能就涉及到跟卡夫卡的一个连接,我们还要先去给它有些数,所以我们还是就是等一下再把它提起来,我们再给大家讲一讲吧。
我来说两句