上个月对一个小项目的效果进行改进,时间紧,只有不到一周的时间,所以思考了一下就用了最简单的方法来做,效果针对上一版提升了5%左右,跟大家分享一下(项目场景用的类似的场景)
项目场景:分析一个产品的竞品,譬如app的竞品、网站的竞品等等
项目分析:简单来说就是竞品分析,竞品分析有很多比较成熟的方法,但是我认为,竞品分析其实和推荐有着很大的相关性。譬如我要分析一个技术网站的竞品有哪些,通俗点说,就是看一个用户经常访问哪些网站、不同类的用户访问网站的偏好是什么、在同类技术网站里与之定位想进,用户人群相似的网站有哪些等等。抽象来看,即可得出两个关键词:用户和物品(或者说物品和竞品)。这个关键词是不是很熟悉?在推荐里我们经常会遇到item和user之间的相似度,那么竞品分析其实也可以同类化于相似度的计算问题。
具体做法:提到相似度计算,会想到很多方法,常见的欧几里得距离,余弦计算,皮尔逊距离等等,对于不同的距离计算,有不同的适用条件,之前总结过一个关于相似度计算的文章,只不过觉得不是很完善,所以一直没有发出来。这次做竞品分析的时候突然想起了Jaccard相似度。那么Jaccard相似度是什么呢?简单说下公式:
给定两个集合A和B,A和B的Jaccard相似度 = |A与B的交集元素个数| / |A与B的并集元素个数|
那么这样一个公式是来应用到竞品分析中的呢?我们假设一个场景:
喜欢博客园的用户也喜欢浏览知乎、CSDN、Github等,喜欢知乎的用户也喜欢浏览Github、InfoQ、V2EX、SegmentDefault、博客园等,假设我们根据浏览次数来进行排序,得到两个集合,那么我们可以简化为博客园和知乎的竞品分别为:
博客园=[知乎、CSDN、Github]
知乎=[Github、InfoQ、V2EX、SegmentDefault、博客园]
此时,第一版计算结果:博客园与知乎的Jaccard相似度为= 1 / 7=0.14
这是最简单的Jaccard相似度计算,然而我们发现,逛博客园的经常逛知乎,且知乎权重很高,但是他们俩的相似度却很低,只有0.14,看起来好像并不符合常理,于是,我做了点修改,将需要计算的竞品本身也加入集合,即:
博客园=[博客园、知乎、CSDN、Github]
知乎=[知乎、Github、InfoQ、V2EX、SegmentDefault、博客园]
这样我们再来计算,得到第二版计算结果:博客园与知乎的Jaccard相似度 = 3 / 7 = 0.42
为什么我们要将竞品本身考虑进去呢?其实很简单,以博客园为例,我们的目的是找到博客园的竞品,分析出经常浏览博客园的用户还会经常浏览哪些同类技术网站,那么博客园的用户肯定是经常浏览博客园的,这点显而易见,一个物品本身也是自身的竞品。将要分析的竞品本身加入集合后就可避免我们第一次计算时出现的不符合常识的结果。
但是,还得思考一个问题,博客园对知乎的Jaccard相似度与知乎对博客园的Jaccard相似度应该是一样的吗?按照前两次计算,我们认为是一样的,因为只是考虑的交集的个数,并没有考虑集合中元素所处的位置因素。然而实际上,集合中的元素位置其实是有先后之分的,按降序排列,即竞品相关度是越来越低的。此时未考虑元素的位置因素似乎也有悖尝试。举个例子:一个经常看博客园的用户,也会经常看知乎,那么一个经常看知乎的用户是否也代表也会经常看博客园呢?这个结论与我们给出的条件是相悖的:一个经常看知乎的用户,相比于博客园,更偏好于Github。所以我们得到结论:两个竞品A和B,A对B的重要性不一定等于B对A的重要性。
所以,我们对此进行进一步改进,
博客园=[博客园、知乎、CSDN、Github] ====》博客园 = [1.0,0.6,0.3,0.1]
知乎=[知乎、Github、InfoQ、V2EX、SegmentDefault、博客园] ====》知乎 = [1.0,0.55,0.15,0.14,0.11,0.05]
(注:竞品本身加入集合我设定权重为1,其他竞品元素总分为1)
此时,计算得到第三版计算结果:
博客园对知乎的Jaccard相似度 = ( 两者交集的权重得分和/ 两者权重总和 ) * 知乎在博客园集合中所占的权重 = ( 1+0.6+0.1+1+0.55+0.05 / (2+2) )* 0.6 = ( 3.3 /4 )* 0.6 = 0.495
知乎对博客园的Jaccard相似度 = ( 两者交集的权重得分和/ 两者权重总和 ) * 博客园在知乎集合中所占的权重 =( 1+0.6+0.1+1+0.55+0.05 / (2+2) )* 0.05 = ( 3.3 /4 )*0.05 = 0.04
由此可得,博客园与知乎的竞品相似度是不相同的,也符合常理
总结:一开始我想到了很多方法来做,但是时间紧,又要有效果提升,所以尝试对最简单的计算公式做改进达到提升效果的目的,针对每一次计算的结果,结合常识,再来进行一步步改进,最后取得了不错的效果。其实最后的方案还可以做一些改进,如:如何设定权重,如何设定计算公式、是否可以用线性模型拟合等等,都可以去尝试,有兴趣的也可以去试一试。如果大家有更好的方法,也可以一起讨论一下:)