背景打碎是根据推荐、广告、搜索系统的结果,提升用户视觉体验的过程。主要方法是将结果按呈现顺序重新排序,使相似类别的对象分散,避免用户疲劳。算法端的推荐结果往往存在以下痛点:同类商品容易混在一起。显然,如果商品的特性相似,那么它们得到的推荐分数很可能也相似,同样的商品肯定不是用户所期望的结果。对用户偏好的捕捉太强了。在用户的心理层面,他们对自己的隐私或偏好被完美捕获这一事实很敏感。过于精准的结果不仅容易引起用户反感,也容易限制用户潜力的转化。由此产生的错误很容易被放大。对于几乎没有使用痕迹的用户来说,很容易将仅有的特征放大,从而容易产生错误的推荐。分散算法通过改变呈现顺序,将相似类别分离,缓冲推荐系统与用户的交互,提升用户体验,是实现算法赋能的最后一步。问题定义首先,我们澄清分解算法的定义。输入是算法根据用户喜好程度排列的有序列表,每个对象都有一个或多个属性需要区分,输出要求是相似属性分散的列表。这些细节将涉及:碎片化程度。是尽量保持同一个类别分开,还是只要分开一定距离就可以满足要求?分散基础的维度。是按照一个属性分开就够了,还是需要考虑的因素很多分开?分手的表现。作为一个被频繁调用的接口,性能优化越多越好。值得注意的是,我们不想失去算法端系统带来的用户个性因素,所以如何在散点的基础上充分利用原有对象的顺序也是一个非常值得权衡的问题。解决方案从三个不同的维度,我们将讨论三种更通用的分手方法。三种方法中,分散最彻底的是柱分散法;权重分配方法可以综合考虑多个维度;滑动窗口方法只需要本地计算以提高性能。由于逐列的方式是为了避免属性相似的内容在呈现的时候相邻,所以很直接的思路就是我们把不同的属性放在不同的桶中,每次想要获取的时候尽量选择不同的桶。这样,元素就可以尽可能的分散。如下图所示,在这个例子中,初始列表有三个类别(蓝色,黄色,红色):将它们按顺序放入桶中(通常是HashMap):此时,我们按列取出每个桶中的元素,这可以保证元素最大程度的分散,最后的结果是,为了保证原始算法结果的保存,我们有一个将每一列按照原来的顺序进行排序的过程。该算法的优点是:简单直接,容易达到很好的分散效果,虽然排序可能会导致元素在列的首尾相邻,但是在末尾之前,最相邻的元素是2,不影响体验,性能比较稳定,不易受输入结构影响。缺点是:端断无效,容易聚拢。对原序列的尊重不强,即使有推荐系数很低的对象,也强行出现在最前面。只能考虑分类的一个维度,不能考虑其他因素,也可以看出该算法对类别数的依赖性很强。如果类别足够详细,可以部分掩盖该算法的不足。在性能方面,时间和空间消耗是O(n)的权重分配方法当我们要综合考虑多个因素时,不可能直接对每个产品直接进行分类。这时候就可以采用权重分配的方法。首先,我们为每个物体定义一个新的权重:W是人为分配给每个属性的系数,代表分散的优先级,Count代表物体在这个属性上的表现(同一个属性已经出现了多少次)).直观上来说,相似属性出现的次数越多,权重值就越大,而在函数计算的过程中,自然会考虑到原来顺序的因素,所以计算出权重后,不需要再做其他处理,只需按重量排序即可。以下图为例,如果我们规定字体颜色权重系数为2,色块颜色权重系数为1,那么在1日和2日,它们的字体颜色和色块都没有出现过,那么权重为0,到第3个,出现过一次,则权重为2*1+1*1=3,以此类推,当数字为8时,它的字体颜色出现了两次,色块颜色出现了三次次,则权重为2*2+1*3=7这样只需要一次排序操作,按权重分散。可以看出,通过设置较重的权重系数,我们实现了字体颜色先被打乱,色块信息由于系数低,可以容忍它们有限的邻接。该算法的优点是:实现不同因素的分散也简单直接,分散的倾向可以很容易地通过调整权重系数来调整。通过修改权重计算函数,可以很方便的纳入其他考虑,如果想更加尊重原始排序,也可以将原始序列加入到权重计算中。缺点是:由于权重计算的累积效应,该算法最后还是容易失败。最后,整体排序性能为O(nlogn),相对有一个优化空间窗口以上两种滑动方式都是我们通盘考虑全局后产生的算法。复杂度计算中的变量n也是整个原始序列的大小。但在实际场景中,用户并不会一下子看到整个序列,往往是一次性返回。topN,填满用户窗口即可。这时候我们应该发现一个只针对本地的方法。基本思想是滑动窗口。如下图,我们开一个大小为3的窗口类比用户的接收窗口,规定窗口中不能有重复的元素,即模拟用户看到的一个显示页面是不重复。如果在窗口中发现重复的元素,则检测一个合适的元素并与当前元素交换。第一步,我们检测到2和3是同一类型,所以取出3,后来检测到4符合3的要求,所以我们交换了3和4,窗口向后滑了一格。第二步,发现窗口中还有同类的2和3,然后交换3和5,窗口向后滑动一个空格,窗口没有冲突,并且然后滑动另一个空间。第三步,发现5和6是同类,将6和7交换,把窗口滑到最后。虽然也找到了同种的7、8个,但当时没有可交换的元素,就不处理了。该算法的优点是只需要局部计算,不需要完全打散,适应topN的需要;但缺点也很明显,鲁棒性不好,受序列分布影响大,无法避免最后的积累。缺点。综合考虑根据前面的讨论,我们对这些方法有如下结论:其中,为了直观地比较三种方法的性能,我们生成了100,000条完全随机的数据,并在notebook环境中进行了测试。三种算法在不同尺度下的性能。横坐标表示输出数据的大小,纵坐标表示运行时间(单位:ms)。可以看出,在一定的数据范围内,滑动窗口的方法具有很大的优势,但性能也与窗口大小有很大关系。如果窗口范围太大的话,冲突会比较多,交换速度也会大大降低。综上所述,三种算法的适用场景如下:如果在常用场景中使用单维打散,按列打散是完全可以的。如果追求性能,原本的排列分布已经比较稀疏,选择小单元的滑动窗口比较好。如果要引入多维度,权重分配方法是必不可少的。本文提出的所有算法都在O(n)、O(nlogn)的层次上,并且由于实际场景往往极小,所以不一定不会成为应用中的性能瓶颈,同时也留有很大的修改和权衡空间。之后我们可以从全局和局部和谐、尾部堆积等方面进一步讨论这个问题。一定要明确需求,然后再结合需求进行分析,做到三者各取所长。这次在解决闲鱼Mach选品系统打散需求时,了解到以下特点:产品列表长度在2000左右,用户获取一条消息的对象数量有限,一般情况下只有一位或两位数分散要求:需要将同一用户发布的产品与同一类别的产品分开,前者优先于后者。最佳系数也可以调整。类别极其有限,我们可以有针对性地选择自己的解决方案。从特征2可以看出,需要综合多个因素,所以需要选择权重分配方式;为了解决性能问题,结合特征1和特征3,一次获取的消息很少,商品的类别也极其有限,所以决定选择Slidingwindow方式。我们结合权重分配法和滑动窗口法,使用窗口大小为4的滑动窗口,然后使用权重系数13和7(均为质数,便于排序)计算用户的权重函数和类别,并将窗口中的权重约束更改为,与所有其他对象的权重差异小于某个阈值。最终实现多因素统计与绩效的统一。稍有不足??的是,这次的参数选择(窗口大小,权重系数)没有经过反复的实验和比较。之后计划在实际场景中使用ABtest等方法对参数进行优化调整,使算法的性能表现更好。小结本文讨论了分散算法的几种实现方法,从实现方法到优缺点进行了详细阐述。通过本文的方法,可以将特定类别的结果以去中心化的顺序呈现,从而提高用户的视觉体验。可见,实际打散的效果与尊重原算法的顺序特性之间存在着一对不可避免的矛盾。如何在实际复杂的需求情况下更好地把握两者的平衡点,从而适用于更多的场景,是我们未来需要继续探索的;是技术人永恒的命题。
