关联推荐算法

基于关联规则的推荐(Association Rule-based Recommendation)是以关联规则为基础,把已购商品作为规则头,规则体为推荐对象。关联规则挖掘可以发现不同商品在销售过程中的相关性,在零售业中已经得到了成功的应用。管理规则就是在一个交易数据库中统计购买了商品集X的交易中有多大比例的交易同时购买了商品集Y,其直观的意义就是用户在购 买某些商品的时候有多大倾向去购买另外一些商品。比如购买牛奶的同时很多人会同时购买面包。

算法的第一步关联规则的发现最为关键且最耗时,是算法的瓶颈,但可以离线进行。其次,商品名称的同义性问题也是关联规则的一个难点。

 

以apriori算法为例,其挖掘步骤:

1.依据支持度找出所有频繁项集(频度)

2.依据置信度产生关联规则(强度)

 

主要代码如下:

package apriori;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.jolly.bi.aglorithm.conf.AprioriUnit;

public class AprioriUtils {

    private final static String ITEM_SPLIT = ";"; // 项之间的分隔符
    
    private static HashSet<String> getItem1FC(String trans) {
        HashSet<String> rItem1FcSet = new HashSet<String>();// 频繁1项集
        String[] items = trans.split(ITEM_SPLIT);
            for (String item : items) {
                rItem1FcSet.add(item+ITEM_SPLIT);
        }
        return rItem1FcSet;
    }
    
    public static HashSet<String> getFC(String trans){
        
        HashSet<String> frequentCollectionSet = new HashSet<String>();// 所有的频繁集
        HashSet<String> tmp_1fc=getItem1FC(trans);
        frequentCollectionSet.addAll(tmp_1fc); //导入一项集
        
        HashSet<String> itemkFcSet = new HashSet<String>();
        itemkFcSet.addAll(tmp_1fc);
        
        int a=0;
        while (itemkFcSet!=null&&itemkFcSet.size()!=0&&a<=3) {
            HashSet<String> candidateCollection = getCandidateCollection(itemkFcSet);
            itemkFcSet.clear();
            Iterator<String> it_cd= candidateCollection.iterator();
            while (it_cd.hasNext()) {
                itemkFcSet.add(it_cd.next());
            }
            frequentCollectionSet.addAll(itemkFcSet);
            a++;
        }
        
        return frequentCollectionSet;
    }
    
    public static HashSet<String> getCandidateCollection(HashSet<String> itemkFcSet){
        
        HashSet<String> candidateCollection=new HashSet<String>();
        Iterator<String> is1= itemkFcSet.iterator();
        while (is1.hasNext()) {
            String itemk1=is1.next();
            Iterator<String> is2= itemkFcSet.iterator();
            while (is2.hasNext()) {
                String itemk2=is2.next();
                String[] tmp1 = itemk1.split(ITEM_SPLIT);
                String[] tmp2 = itemk2.split(ITEM_SPLIT);
            
                String c = "";
                if (tmp1.length == 1) {
                    if (tmp1[0].compareTo(tmp2[0]) < 0) {
                        c = tmp1[0] + ITEM_SPLIT + tmp2[0] + ITEM_SPLIT;
                    }
                } else {
                    boolean flag = true;
                    for (int i = 0; i < tmp1.length - 1; i++) {
                        if (!tmp1[i].equals(tmp2[i])) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag
                            && (tmp1[tmp1.length - 1]
                                    .compareTo(tmp2[tmp2.length - 1]) < 0)) {
                        c = itemk1 + tmp2[tmp2.length - 1] + ITEM_SPLIT;
                    }
                }
                
                // 进行剪枝
                boolean hasInfrequentSubSet = false;
                if (!c.equals("")) {
                    String[] tmpC = c.split(ITEM_SPLIT);
                    for (int i = 0; i < tmpC.length; i++) {
                        String subC = "";
                        for (int j = 0; j < tmpC.length; j++) {
                            if (i != j) {
                                subC = subC + tmpC[j] + ITEM_SPLIT;
                                
                            }
                        }
                    }
                } else {
                    hasInfrequentSubSet = true;
                }

                if (!hasInfrequentSubSet) {
                    candidateCollection.add(c);
                }
            }    
        }
        return candidateCollection;
        
    }
    
    private static void buildSubSet(List<String> sourceSet, List<List<String>> result) {
        // 仅有一个元素时,递归终止。此时非空子集仅为其自身,所以直接添加到result中
        if (sourceSet.size() == 1) {
            List<String> set = new ArrayList<String>();
            set.add(sourceSet.get(0));
            result.add(set);
        } else if (sourceSet.size() > 1) {
            // 当有n个元素时,递归求出前n-1个子集,在于result中
            buildSubSet(sourceSet.subList(0, sourceSet.size() - 1), result);
            int size = result.size();// 求出此时result的长度,用于后面的追加第n个元素时计数
            // 把第n个元素加入到集合中
            List<String> single = new ArrayList<String>();
            single.add(sourceSet.get(sourceSet.size() - 1));
            result.add(single);
            // 在保留前面的n-1子集的情况下,把第n个元素分别加到前n个子集中,并把新的集加入到result中;
            // 为保留原有n-1的子集,所以需要先对其进行复制
            List<String> clone;
            for (int i = 0; i < size; i++) {
                clone = new ArrayList<String>();
                for (String str : result.get(i)) {
                    clone.add(str);
                }
                clone.add(sourceSet.get(sourceSet.size() - 1));

                result.add(clone);
            }
        }
    }


    public static Map<String, Double> getRelationRules(
            String key,Map<String, Integer> frequentCollectionMap) {
        Map<String, Double> relationRules = new HashMap<String, Double>();
        
        double countAll = frequentCollectionMap.get(key);
        String[] keyItems = key.split(ITEM_SPLIT);
        if (keyItems.length > 1) {
            List<String> source = new ArrayList<String>();
            Collections.addAll(source, keyItems);
            List<List<String>> result = new ArrayList<List<String>>();

            buildSubSet(source, result);// 获得source的所有非空子集

            for (List<String> itemList : result) {
                if (itemList.size() < source.size()) {// 只处理真子集
                    List<String> otherList = new ArrayList<String>();
                    for (String sourceItem : source) {
                        if (!itemList.contains(sourceItem)) {
                            otherList.add(sourceItem);
                        }
                    }
                    String reasonStr = "";// 前置
                    String resultStr = "";// 结果
                    for (String item : itemList) {
                        reasonStr = reasonStr + item + ITEM_SPLIT;
                    }
                    for (String item : otherList) {
                        resultStr = resultStr + item + ITEM_SPLIT;
                    }

                    double countReason = frequentCollectionMap
                            .get(reasonStr);
                    double itemConfidence = countAll / countReason;// 计算置信度
                    if (itemConfidence >= AprioriUnit._CONFIDENCE) {
                        String rule = reasonStr + AprioriUnit._CON + resultStr;
                        relationRules.put(rule, itemConfidence);
                    }
                }
            }
        }
        return relationRules;
    }

}

 

应用场景举例:

(1)数据输入为订单下的所有商品id

125403,185733,196095,117965,201975,212841,181789
149693,210991,13992,64312,54796,194527

(2)计算所有频繁项集,依据支持度过滤

(3)根据公式,得到符合置信度条件的所有推荐

104138,196705,0.1875

104138,196705,0.1800

结论是 购买了商品104138中购买196705的最多

 

转载于:https://www.cnblogs.com/novakjo/p/5368616.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值