00:00
好,那现在我们的主要问题其实就是实现核心算法这一部分了,怎么样用TFIDF得到它的特征向量呢?在这里来做计算,呃,那大家会想到,呃,首先啊,我这里面给大家第一步是要干什么呢?要实例化一个。分词器用来做分词,这个大家很好想,因为我们一开始做Python具体实现的时候,我们是不是也是先做分词,拿到那个所谓的呃,Bow对吧,Bo那个磁磁带模型就是一组词嘛,我们先得得到这样的东西,要不然你一个整个的一个字符串,这个我们没法处理,呃,那这里边我们调用相关的这个组件工具主要是什么呢?呃,大家看啊,有这个叫做tonizer的东西,我们先去拗一个。
01:00
Token neitherr,大家看ML.featureer下边有一个叫做tokenizer分词器这样一个东西,它可以去设置一些内容,可以设置什么呢?大家看set into column就是表示啊,大家看它既然是set into column,所以它的操作是不是都是针对data frame来的呀?前面我们提到过啊,ML下边的这些API其实都是针对的是data frame的操作,那ML lab的下面的API针对的是RDD,我们这里边用ML下边的这这一串啊,大家看看怎么怎么去做,所以这里边input column就是我们要对哪一个字段哪一个列去做它的内容,去做分词,我们现在输入的是cap,对。然后当然有input,就会有output output我们这里定义一个,这就我们自己定义了,因为这是输出嘛,比方说我就叫word吧,给一个这样的东西对吧,用来做分词。
02:05
默认按照空格分。有了这个东西之后,我们怎么样处理呢?呃,就是用分词器。做转换得到增加一个新列的新烈words的data frame,那大家看一下它的这个写法是什么?我我们定一个words data吧,Data frame,它就等于直接用前面定义好的tokenizer点,它有一个方法叫做transfer。那么transform里边传的参数就是。大家能想到是不是就是前面我们的这个product tap df啊,前面定义好的这个,呃,所以我们,呃,这这里我们看一眼它到底长什么样吧,Words data frame df.show我们是不是可以用点show方法来看一眼它具体的效果啊啊,这里边stop是有的啊,应该没有语法错误,我们直接跑一下先看一眼。
03:22
好,这里边我们可以把日志级别调高一点啊呃,我们就直接先在这里看一下这个输出吧,应该能找到,诶大家看到在这里啊,大家看输出的是什么呢?我们本来的data frame是不是应该是product ID name,还有TYPES3列,然后现在他是不是其实就在后边把types这一列。大家看做了一个分子,本身它是一个字符串,对吧,本来是是这个空格分割的字符串,这里边就把它提取成了一个对一个数组,所以这其实就是做了一个简单的转换操作,后面追加了一个叫做words的这一列,就是这样的一些操作啊好大家看一眼就可以了,然后接下来我们继续做操作,做了第一步转换了,那第二步应该做什么呢?啊,我们会。
04:22
定义一个叫做哈声TF的工具,那来看名字,它应该是干什么的,是不是对,就是哈希TF是不是要算TF啊,对吧?用它是来计算TF的,呃,那么同样它的这种定义方式,大家会看到跟前面的这个tonize其实非常相似啊,我们甚至就可以,呃,就是。直接往下写就可以,同样new一个哈声音TF,大家看我们还是选取ML feature下边的哈声音TF,那这个用出来之后,它也可以去set一些东西,大家看有set input column,这里边我们针对哪一列去做转换呢?对,现在是针对words去做转换,然后set output column,我们把这个就呃,这个其实已经可以说转换出来,这个TF统计它的那个,呃,相当于是磁频,对吧,已经可以作为我们的一个原始特征了,对不对?我们这里就把它叫做roll features。
05:37
大家只要知道它是这个算出来的词平就可以,另外这里大家注意一下还有一项叫set number features,这是什么呢?对,从名字上来讲,是不是要这个设定特征数量啊,言下之意,这这是什么意思呢?就是说我们本身你这里边的词汇有可能是非常非常多的,那你如果不设的话,它默认肯定就按一个非常大的数字来算这个特征数,如果我们提前就知道,诶里边想要提取的主要这个特征数有多少的话,我这里边是不是可以指定一个比较小的特征数啊。
06:19
哎,这里边比方说我直接指定一个啊,指定一个300,那大家就会想到我最后得到的那个特征词语的这个数量,考察的词语的数量维度是不是就是300个维度啊,那大家会想到这里为什么叫哈TF呢?它其实映射这个特征的过程其实用的就是哈希算法,所以这个特征数量相当于就是哈希的分筒数量,你如果这个数量设置的很小的话,就会出现什么情况。对,就是有一些词它可能就出现哈希碰撞了,对应到的就变成了一个特征,也有可能我们出现,比方说这个鼠标和电子产品,呃,有可能他就对应到是一个特征,它出现了两次对吧,统计了两次就会出现这种情况,所以大家这里可以稍微注意一下,我们这里的话就能够涵盖这里出现的所有词汇就可以了,比方说取一个300,然后有了这样一个哈行TF之后做什么操作呢?啊,其实非常简单啊,就是得到一个比方说feature rise的data df啊。
07:35
好,然后这里做转换的过程,就是我们定义一个比方说叫feature的data frame。他怎么做呢?直接用hush in TF这个工具去调用他的transfer方法,里边传进来的就应该是前面我们得到的world data df,好,那这里边再给大家看一眼这个feature rise。
08:02
DF应该长什么样,看这里边已经做完了啊,现在就直接可以看到它的结果,得到的是一个什么结果呢?诶哦,这里我们还是给大家多一个内容啊,大家看它是缩略的形式,所以我们可以在show的时候是加上这个窗ET等于false啊,把它完整的显示出来啊,重新让一下。重新来看一下,哎哟,这个展开就有点太大了啊。好,大家看一下吧,呃,最后这个就是我们得到的这个raw features,大家看一下这个形式是什么样的呢。300,然后后边是一个,哎,一个数组对吧,然后边又跟着一个数组,这表示什么意思啊,大家看前面最最开始的这个数,所有的都是对,都是300,所以大家可以想到这相当于代表什么对总特征数量,那么在这个表达的这个形式里边。
09:13
它其实就代表的后边这个数组的。纵长度。那家可以想到,那那为什么说是总长度是300,后边又只有这么几个数呢?而且这个数好像不一定,呃,这个数就不一样了,对吧?可以取这个,可以可以取别的,可以有相同的,可以有不同的,而且数量也也不等,那这是怎么回事呢?诶,对,非常好,大家已经想到了,这是不是只把不为零的这些位置的给我们显示出来,提取出来啊,所以这里显示的就是下标是50的那个数,这数组里边下下标是50的那个数,它是一,下标是138的那个数,它也是一,那除了这几个下标对应的地方有值,别的地方是不是都是零对吧?那大家想这种表达是不是就相当于是我们所说的稀疏矩阵的那种表达形式啊啊,当然这里边不是矩阵,不是二维的。它只。
10:20
这意味的,所以这是一个稀疏向量的表达形式,呃,在这个m ML lab里边是专门对这种数据结构有定义啊,就叫做SPA vector叫做一个稀数向量,所以它其实就是表示大部分都是零有值的地方,诶我把它写出来就是这个对应位置,这几个地方都是零,那大家可以看到就是我们前面,呃,这里边有一个这是个鼠标对不对,一个附勒鼠标,然后后边这个小狗前倩,这是这是一本书儿童儿童图书,呃,那么他共同的这个评分,呃,他的这个标签里边有什么是相同的呢?那是可能我们就是因为总共的这个词汇确实是比300个还要多,所以这里边我们看到的就有可能出现,哎,同样都是50,但实际是两个不同的词映射过来,都映射到50出现哈希碰撞了,对吧?啊,所以只能。
11:20
不是这样的一个解释,才可能出现这样的情况,那我们为了防止这样的情况出现,我们把这个300再调大一点吧,比方说我们给一个500吧,再来跑一下试试。那接下来我们再看一眼这个啊,大家看后边其实是能提取出来400多的这个维度的,对不对?好,我们现在再看一眼,诶,还是有50,说明有可能还不够,是不是,大家看我们把后边的那个分桶数量限制去掉之后,它默认的分桶数量应该是262144,这个大概是多大呀。26万大概是多少?大家估算一下。
12:05
三位这个大概是K对不对?260多K256最接近的是不是?256256K256K是二的多少次?1024K是一兆,是二的20次,对256是不是二的18次,所以大家看到它默认的这个就是大小,其实是二的18次啊,那么按照这个分筒数,大家看这里应该就没有碰撞了,对吧?这几个数看起来好像后边都没有出现过,呃,所以这个情况看起来还是比较呃,比较没有任何问题的一个状态,好,那我们就把后边的这个分组数去掉吧,这个还好理解一些,大家看着那个还有点不知道所以然。好,那么接下来我们已经拿到了原始的这个,这相当于还不是TF,这其实只是一个出现的次数,对吧,计算频次频次。
13:05
然后我们接下来其实就可以去算这个t fidf了,呃,那同样我们是定义。一个IDF工具计算。TFIDF,呃,这里边大家就会看到,其实我们并没有按照公式去先去算这个TF,然后再算IDF,再乘起来,它其实就是我们直接调库的时候,都是矩阵转换的这种,就是data frame转换的这种方式,一步一步把它得到新的特征就完事,那接下来这个IDF工具又是一个什么玩意儿呢?啊,我们直接定义一个new,一个IDF。ML feature里面有IDF这个东西。那么同样我们会想到它可以set column是什么?
14:05
我们现在要对哪一个,呃,为哪一个列去做转换呢?是不是我们应该针对之前统计出来的这个对roll features这样的一个稀疏向量去做转换啊,呃,这是一个稀疏向量,对吧,里边大部分都是零的这样的一个向量,好,那么raw features。然后同样set output,那么这里得到的应该就是最后的features。呃,那这个在在计算的过程当中,他还得多分几步走啊,就是后面我们还得去。呃,这个训练一个IDF模型,呃,这是做了一个什么事情呢?大家会想到这其实所谓的这个训练IDF模型,我们调IDF的fit方法,然后传入前面这个feature rice data frame,对吧?把这个东西传入,大家想到这个fit建创训练这个IDF模型其实是干什么?是不是就是要把那个role features,然后我们做统计,要把那个IDF相关的那些东西都统计出来。
15:28
呃,就是把我们所有的那个文档数量,出现的频次,是不是这些东西都要统计出来啊,这里是把它叫做训练一个模型,但是我们自己知道,它其实就是算IDF相相对应的那些东西而已啊,那么训练完之后我们就可以。呃,对,得到。增加。心烈features的date frame。
16:00
做转换啊,那么现在我们得到的比方说叫就是转换之后的的data frame。他就应该用IDF model调它的transform方法,所以前面跟前面其实也是差不多的,只不过就是直接这个IDF还不能穿我我们先把它这个对应的数据,呃,相关的那些统计的东西先先算出来,对吧,先好像训练模型一样,训练完成之后再去用这个模型做transform,那当然transform的过程还是把featureize的data。Data frame传进来就可以得到我们对应最后输出的这个data frame,当然这里大家感兴趣的可能就是说他这里边得到这个东西到底又是什么呢?呃,这里边这里边这个维度可能有点大啊,我们就试一下吧,里边已经计算完成了,那么他最后得到的结果是什么呢?其实得到的是跟raw feature非常接近的一个东西,是什么东西呢?
17:08
对,大家看到其实之前我们统计的RA feature这里统计的就是它出现的频次,而我们这里就变成了什么,对,就成了最后的t fidf算出来的那个权重,那他会想到这是不是就代表了对应这个词在我们这个文档,也就是整整个标签里边的重要程度,这个重要程度是不是就可以代表,诶这你这个鼠标这个特征,对于它来讲,它的这个特征到底有多大对吧,有多重要,然后这个电子产品这个特征到底有多重要,那么对应的这些东西我们就可以看出来了,这里面我们看一个例子,大家看看能不能有所体会啊,比方说我我们找一找,找一本书吧,呃,这里边大家看到这一串里边有一个评分,就是它的这个权重特别低的,有一项0.46,我们看看能不能把这一项找出来啊。
18:07
诶,这里也有一个0.46的一项。我搜一下直接搜一下这个啊,因为大家会想到,如果要是说做这个计算的话,很可能他们算出来都是一样的值是不是。大家能猜到这个应该是什么样的一个。有有可能是什么吗?这个。对,大家会发现是不是几乎所有的。什么,是不是所有的书都有这样一个特征啊,哎,所以大家会想到有可能它对应的就是书这样的一个特征标签,那么大家会想到这里边如果我们有很多书的话,对于这个商品而言,书是它最重要的一个特征吗?对,相比后边这个育儿类,教育类而言,是不是这个特征其实更明显啊,所以我们要把这个热门的标签,它的权重要去削弱,那最后得到它这个特征其实就不那么明显,有可能只有0.4几,而其他的一些特征有可能就有2.9几,甚至有可能有3.8几,对吧?那比方说像这个什么希尔斯,呃,这有可能是一个一个作者的名名字,他的这个系列丛书,这肯定就是非常明显的一个特征了,我们把它提取出来,这就更能代表这个商品的特征。好,那么接下来。
19:40
休息一下,哦哦,我们时间已有点太长,呃现在我们已经拿到了这个最后得到的数据已经拿到了,相当于这是不是已经是一个特征向量了,大家想,尽管这个表达式我们看着不太舒服,它是一个稀疏矩阵的形式啊,奇疏向量的形式大部分地方都是零,但是这是不是就相当于是一个一个向量啊,呃,它的这个呃形式本来就是呃,有些地方是零,然后有些地方有取值,那得到这个向量之后,我们是不是就可以直接去做运算了,代入到大家想到后边我们这里边两两配对,是不是就可以做计算了?这里主要的问题还在于就是这个features,呃怎么样去转换成跟我们之前这个营运模型这里边的这个飞车一样的形式,就转换成这样的形式,对吧,还可做一步转换,所以这其实就是最后一步。自然我们应该用。
20:40
那就是的data df对吧,这里边是做这个对数据进行转换。得到。RDD形式的。Features,然后就可以直接用下边把这个代码复制过来啊,用这一部分代码去算相似度啊,大家看一下这部分我们应该怎么去把它做处理呢?一个map对吧,Map里边怎么做。
21:20
里边是不是本身这是一个data frame嘛,所以本身拿出来应该都是一个一个肉,那么这个肉我们可以把它做对应的转换,想要拿到的形式是什么呢?是不是前面是一个ID,后边是一个double matrix这样的一个形式啊,呃,对,是特征向量,把它转成一个,呃,Double matrix转成一个矩阵,所以是这样的一个表达式,所以product ID这个从哪里去取?啊,这个简单,是不是肉里边我们就包含有这个product ID啊对,最前面这不就是product ID吗?所以直接肉可以去,哎,我是不是直接可以get as对吧?当然product ID就直接就是int了。
22:15
Product ID把它get出来就可以了,这是我们的前面这一项,后边这一项应该要拿到的是特征向量转成double matrix,呃,那我我先拿到这个特征向量吧,后边那个double matrix我就直接用这边再转一道就可以了,对不对?特征向量从哪里去拿?对还是肉get?Get,哪一个呢?我们拿的是不是就应该是最后的这个features啊,呃,那大家就会想到你这个features应该拿到的是as什么东西呢?哦,这里大家注意它的数据格式,就是我们前面给大家说过的,叫做SPA SPA vector这样的一个数据格式,对,大家看到SPA vector指的就是稀疏向量,它其实也是在ML里面。
23:13
有的这样的一个类,对吧,定义好的这样的一个class,所以我们把它转成这样的一个数据格式,呃,当然了,最后我们想要的其实是要做什么事情呢。是不是想要把它再转成一个正常的一个数组啊,前面我们拿到的是一个稀疏稀疏向量的这样的一个表达式,最后我们把它转成一个正常的数组,是不是就可以带入到这个new double matricx,把它传进去就可以算了,哎,所以后边的话我们是一样的这个点map,用这个形式去做计算就可以。把它抄过来,我这里就不叠加在一起了啊,就在后面把它抄过来就好了,这里大家要注意,就是我们前面本身这里是data frame,这里是把这个肉做了一个转换,转成了这个二元组,那后边是不是还应该把它转成RDD啊对,转成RDD,然后再做对应的这个map操作,跟我们这里边是不是就一模一样了,就就完全没问题了,对吧?呃,得到的最后的结果就是一个product的ID加一个double matrix数据类型,后边是不是就完全可以放开了,好,我们就把这一部分放开。
24:30
大家再梳理一下,后边我们得到这个product features去做迪卡耳机,然后按照过滤条件去筛选,不要把自己跟自己还要算一下余弦相似度,那就那就没意义了啊,就算不同的,然后呢,得到的这个余弦相似度拿出来之后转换成这样的形式,我们最后filter的时候,选取大于0.4的group by key,得到的就是某一个product ID,后边跟着一组这个相似度列表,每一个相似度里边的又是一个product ID,加上一个相似度的分分数值,把它转换成product re,呃,所以如果我们想要让这个前面得到的这个特征向量啊,最后得到的特征向量不要这个维度特别大的话,其实还是可以在这里去把这个分总数做一个限制的啊,我们可以就认为这个在一定的范围内,其实是可以接受的,对吧。
25:31
吧,比方说我这里边给一个前面500应该已经是差不多了,可能其实是再大一点,比方说给一个800应该就差不多了,8000就多了啊,所以我可以在这里把它还是给定一个,你如果给二十二十多万的话,确实这个整个就是对我们整个的性能来讲,可能会就是影响会比较大,呃,大家会想到后边那可是得做什么,做笛卡耳机的对吧,你那个几十万,然后再两两去做笛卡尔机,然后算它那个对应去算那个余弦相似度,肯定这个计算量还是很大的啊,所以我。
26:12
啊,就是这里边用这个哈希TF,它其实有一个什么好处,对于中文来讲,可能这方面,呃,就是因为涉及到UNO编码,这个就可能关联就又又不太不太大了,但是对于英文而言。大家会想到这个做哈希计算的时候,呃,有可能你前面它是它是一组词,作为一个一个词对吧,如果是这样的话,有可能类似的词还会有一些相关的一些情况,有可能他做这个,呃,哈希处理的时候,做分层的时候,即使碰撞的话,有可能是相关的词汇碰撞,碰撞到一类里面去啊,这种情况也是有可能去做的,这里边我们就就可以把这些因素都简化,呃,出于性能考虑,我这里边直接给一个大概差不多涵盖到我们这里边出现过的所有的词就可以了,甚至我们前面就是直接给一个500,就即使前面有一个这个碰撞,大家会想到可能最后出来的结果会不太好,但是其实也没问题,对吧,就是最后总能算到一个特征值,我们总能把它相关的这个相似度计算出来,这是没有问题的。
27:26
好,这里边出于这个最后做呃相似度计算的性能考虑,把这里我们还是设置一个分总数给一个800。然后我们就可以把它运行一下,看看最后的效果怎么样了。好,大家看,现在我们已经把这一部分完成了,计算到mango里边去做一个查看,Show一下当前的tables。诶,是不是很正常的,按照我们的想法就多了一个content based product啊,那么这个看一下里边的东西吧,Content find.pretty。
28:11
啊来看,其实就是这样的一个效果,呃,最后得到的,呃,大家看其实大于0.4的这个相似度好像也并不是太多,对吧?呃,就是有一些多的可能能到0.6的这个相似度,大部分可能也就0.4几,那这个只有一个啊,0.47有一个相似的0.52,所以基于内容的话,可能推出来的是比较相似的,但是呢,按照我们的这个截取标准,0.4以上的其实并不是特别的多,呃,我们这里边可以把它运行起来,再已经有这个表了,我们是不是可以运行起来看看效果啊,把这个业务系统跑起来。现在业务系统已经提起来,我们直接到这里来看一下效果怎么样,好还是登录进去,昨天注册了一个用户ABC,好,登录进来之后,大家可以看到有这个实时推荐,对吧,我们随便点一个商品进去。
29:10
诶,大家看到下边是不是就有一个相似推荐啊,这本身是一个鼠标,它基于内容的这个相似推荐,哎,我们推荐出来还有一个光学鼠标对吧?啊,那如果大家如果想看另外的东西,比方说我们看一本书的话,这个因为痛所以叫青春啊,下面推出来是不是就都是书啊,啊所以其实这就是一个基本的基于它的内容相似度做出来的推荐,这是这一部分内容。
我来说两句