推荐系统打散算法--权重
继上一篇轮询打散算法后,本文主要介绍推荐的另一种打散算法,权重打散算法,该算法适用较多维度打散的一种算法,主要的思路大体为,约定按照一类对象的某几个属性,针对特定的某一个属性,对不同的值对应不同的权重,求当前对象计权属性下值对应的权重和,然后降序输出对象。如:对于推荐商品自营商品和非自营商品权重可能不同,价格区间高的和价格区间低的商品权重可能不同,品牌不同,权重可能也不一样。本文主要阐述推荐权重打散的大体逻辑及实现。
比如有如下7个商品
具体计分规则
店铺维度(共计三种AA,BB,CC)对应的权重分别为2,1,3.5
AA:2
BB:1
CC:3.5
===============
品牌维度(11,22,33)对应的权值分别为1,0,-2
11:1
22:0
33:-2
根据以上计分规则计算后商品得分如下:
根据权重得分降序排序后商品序列如下:
该种打散算法相对来说实现思路比较简单。
新建商品实体Goods 新建父类商品权重实体BaseGoods(权重属性统一维护在该实体中)
父类BaseGoods
//店铺标识 public String shopCode; //品牌标识 public String brandCode; //排序权重 public Double weight = 0d;
子类Goods
public Goods(String shopCode, String brandCode) { this.shopCode = shopCode; this.brandCode = brandCode; } //商品编码 private String goodsCode; //商品名称 private String goodsName; //品牌名称 private String brandName; //四级商品组编码 private String groupCode;
初始化商品
public static List<Goods> initGoodsList() { List<Goods> goodsList = new ArrayList<Goods>(); Goods goods1 = new Goods("BB", "11"); //2 Goods goods2 = new Goods("AA", "33"); //0 Goods goods3 = new Goods("AA", "11"); //3 Goods goods4 = new Goods("CC", "33"); //1.5 Goods goods6 = new Goods("BB", "33"); //-1 Goods goods7 = new Goods("BB", "22"); //1 Goods goods8 = new Goods("CC", "11"); //4.5 goodsList.add(goods1); goodsList.add(goods2); goodsList.add(goods3); goodsList.add(goods4); goodsList.add(goods6); goodsList.add(goods7); goodsList.add(goods8); return goodsList; }
权重配置信息获取
public static Map<String,Map<String,Double>> getPropertyWeight(){ Map<String,Map<String,Double>> map = new HashMap<String,Map<String,Double>>(); //店铺类型(店铺提权) Map<String,Double> shopCodeMap = new HashMap<String, Double>(); shopCodeMap.put("AA", 2d); shopCodeMap.put("BB", 1d); shopCodeMap.put("CC", 3.5d); //品牌类型(品牌提权) Map<String,Double> brandCodeMap = new HashMap<String, Double>(); brandCodeMap.put("11", 1d); brandCodeMap.put("22", 0d); brandCodeMap.put("33", -2d); //返回总配置信息 map.put("shopCode", shopCodeMap); map.put("brandCode", brandCodeMap); return map; }
计权方法
public void countWeight(List<? extends BaseGoods> goodsList) throws IllegalArgumentException, IllegalAccessException { if(null == goodsList || goodsList.size() == 0) //CollectionUtil可替代 return; //获取权重配置信息 Map<String,Map<String,Double>> weightMap = getPropertyWeight(); Field[] fields = goodsList.get(0).getClass().getFields();//获取对象属性 for(int i=0; i<goodsList.size(); i++) { if(goodsList.get(i) instanceof BaseGoods) { //计算单个商品的权重 目前仅按照shopCode和priceLevel排序 统一在父类BaseGoods维护权重属性 BaseGoods goods = (BaseGoods) goodsList.get(i); Double totalWeight = 0d; for(Field f : fields) { f.setAccessible(true);//允许访问私有变量 if(weightMap.containsKey(f.getName())) { Double weight = weightMap.get(f.getName()).get(f.get(goods)); totalWeight += weight; } } ((BaseGoods) goodsList.get(i)).setWeight(totalWeight); } } }
调用输出最终结果信息
public static void main(String[] args) { List<Goods> goodsList = initGoodsList(); WeightShuttle weightShuttle = new WeightShuttle(); try { weightShuttle.countWeight(goodsList); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } //排序 goodsList.sort(Comparator.comparing(Goods::getWeight).reversed()); //打印 goodsList.forEach(o->System.out.println(o)); }
控制台打印结果如下
该种方法人工干预意愿比较明显,但是依旧存在干预不均匀,从而导致商品扎堆的情况。