程序猿成长之路之数据挖掘篇——频繁项集挖掘介绍

2024-04-07 11:52

本文主要是介绍程序猿成长之路之数据挖掘篇——频繁项集挖掘介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

频繁项集挖掘可以说是数据挖掘中的重点,下面我们来分析以下频繁项集挖掘的过程和目标

如果对数据挖掘没有概念的小伙伴可以查看上次的文章
https://blog.csdn.net/qq_31236027/article/details/137046475

什么是频繁项集?

在回答这个问题之前,我们可以看一个例子:
小明、小刚、小红三人去同一家商店购物,小明、小刚两人购买了鸡蛋,牛奶和面包,小红购买了鸡蛋和牛奶,这时候一位聪明的店员便推荐小红购买面包,并且说这个面包很适合购买了鸡蛋和牛奶的客户,小红心动了。
在这个例子中,我们可以看到小明、小刚和小红都有去购买商品的行为,而其中的每一个商品可以称为一个,小明、小刚、小红所购买的商品的集合就成为项集。那么什么是频繁项集呢?所谓的频繁项集理解起来也相对容易了,就是用户频繁购买的商品的集合,也就是说会被大部分用户购买的商品的集合。显而易见,在例子中鸡蛋、牛奶可以称为一个频繁项集。

频繁项集有啥用处?

再次回到之前的那个例子中,那个聪明的店员根据小明和小刚的购买记录进行商品的推荐,这个就利用到了频繁项集的一个优势:允许系统(店员)利用已有的频繁项集(顾客的购买记录) 针对某一客户进行商品推荐。那么为什么可以这么做呢?这么做的依据是什么呢?下面让我们来看一下频繁项集挖掘的过程。

频繁项集挖掘过程

先上个例子(基于Apriori):
已知
用户B收藏了物品A、B、C,
用户C收藏了物品A、D,
用户D收藏了物品A、B、C、D,
用户E收藏了物品A、B、E
用户A收藏了物品A、B,现在需要针对用户A进行物品推荐。

  1. 首先我们选取一个集合,就设置为{物品A}
  2. 我们不难发现购买了物品A的用户3/4都收藏了物品B,这时候我们可以设定一个阈值,只有频率(出现次数)超过这个值的项集才会被保留,这个值又称作最小支持度(min_support)。假设最小支持度为0.5, 也就是说物品D不会被推荐,因为只有一个用户在收藏了物品A后收藏了物品D(是用户C), 收藏D的后验概率为1/3 < 0.5。
  3. 于是集合扩容为{物品A,物品B}
  4. 之后而我们推出收藏了物品A、B后收藏物品C的概率为 1/2,也就是{用户B,用户D}/ {用户B,用户C,用户D、用户E},而用户收藏A、B、E的概率为1/4 < 0.5 因此不被保留
  5. 集合扩容为{物品A,物品B,物品C}
  6. 因为购买物品A,物品B,物品C后购买物品D的项集只出现1次,1/4 < min_support = 0.5 因此,该项集非频繁项集,因此最大频繁项集为{物品A,物品B,物品C}
  7. 之后针对用户A进行推荐,这时候需要逐层进行筛选,不难得出{物品A,物品B} => {物品A,物品B,物品C} 的概率为2/3,超过了我们设定的第二个阈值,称为最小置信度(也就是最小关联度),而{物品A,物品B} = > {物品A,物品B,物品E} 的概率为1/3 < 0.5 。不推荐。因此会向用户A推荐物品C,

Apriori算法

好了,朋友们,看到了现在这一步可以恭喜你已经初步了解频繁项集的挖掘过程了。
下面我们来看一下Apriori的算法:

package apriori;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** apriori算法* @author zygswo**/
public class Apriori {/*** 最小支持度*/private static final double MIN_SUPPORT = 0.5;/*** 最小置信度*/private static final double MIN_FAITH = 0.5;/*** 算法核心* @param trainDataSet 训练集* @param usersCollection 用户喜好* @return*/private static List<String>getResult(Map<String,String[]> trainDataSet,String[] usersCollection) {//1.训练集训练Map<String,Double> res = new ConcurrentHashMap<String,Double>();res = trainData(res,trainDataSet);System.out.println(res.toString());//2.推荐return recommend(res, usersCollection);}/*** 推荐* @param res* @param usersCollection* @return*/private static List<String> recommend(Map<String, Double> res, String[] usersCollection) {// TODO Auto-generated method stubString key = "";List<String> list = new ArrayList<>();for (String str: usersCollection) {key += str;}double countNb = res.get(key);for (String str: res.keySet()) {if (str.length() != key.length() + 1) {continue;}boolean contains = true;for (char ch : key.toCharArray()) {if (str.indexOf(ch) == -1) {contains = false;break;}}if (contains){if (res.get(str) /countNb * 1.0 >= MIN_FAITH) {System.out.println(key + " -->"  + str + " faith = " +  res.get(str) / countNb * 1.0);list.add(str.replace(key, ""));}	}}return list;}/*** 训练训练集* @param res* @param trainDataSet* @return*/private static Map<String, Double> trainData(Map<String, Double> res,Map<String, String[]> trainDataSet) {res.putAll(trainData(trainDataSet.size(),0, res, trainDataSet));return res;}/*** 训练训练集* @param initSize 初始数组长度* @param roundNb 轮数* @param res 结果map* @param trainDataSet 训练数据集* @return*/private static Map<String, Double> trainData(int initSize,int roundNb,Map<String,Double> res,Map<String,String[]> trainDataSet) {//统计
//		System.out.println("roundNb = " + roundNb);for (String[] itemArr : trainDataSet.values()) {//获取当前用户的收藏item集合,也就是获取项集String tempStr = "";for (String item:itemArr) {tempStr += item;}//针对项集统计频率if (roundNb == 0) {for (String item:itemArr) {if (res.get(item) == null) {res.put(item, 1.0);} else {res.put(item, res.get(item) + 1.0);}	}} else {for (String resStr : res.keySet()) {//如果字符串长度不为roundNb+1就说明不是当前的那层项集if (resStr.length() != roundNb + 1) {continue;}boolean contains = true;for (char ch : resStr.toCharArray()) {if (tempStr.indexOf(ch) == -1) {contains = false;break;}}if (contains){res.put(resStr, res.get(resStr) + 1.0);}}}}//筛选for (String str:res.keySet()) {if (res.get(str) < MIN_SUPPORT * initSize) {res.remove(str);}}//新增Map<String,Double> newRes = new ConcurrentHashMap<String, Double>();for (String str:res.keySet()) {if (str.length() != roundNb + 1) {continue;}for (String substr:res.keySet()) {//每次获取一位,之后叠加if (substr.length() != 1) {continue;}String lastChar = str.charAt(str.length() - 1) + "";//判断大小,只允许字符串递增排列,如AC,AB,AD,CDif(substr.compareTo(lastChar) > 0) {newRes.put(str+substr, 0.0);}}}if (newRes.isEmpty()) {return res;} else {res.putAll(newRes);return trainData(initSize,roundNb+1,res,trainDataSet);}}public static void main(String[] args) {Map<String,String[]> trainDataSet = new ConcurrentHashMap<>();trainDataSet.put("userB", new String[]{"A","B","C"});trainDataSet.put("userC", new String[]{"A","D"});trainDataSet.put("userD", new String[]{"A","B","C","D"});trainDataSet.put("userE", new String[]{"A","B","E"});trainDataSet.put("userF", new String[]{"A","B","C","E"});System.out.println("推荐结果为" + getResult(trainDataSet,new String[]{"A","B"}));}
}

运行截图
在这里插入图片描述

—————————————未完待续,代码解析之后再讲—————————————————————

这篇关于程序猿成长之路之数据挖掘篇——频繁项集挖掘介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/882535

相关文章

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

如何用java对接微信小程序下单后的发货接口

《如何用java对接微信小程序下单后的发货接口》:本文主要介绍在微信小程序后台实现发货通知的步骤,包括获取Access_token、使用RestTemplate调用发货接口、处理AccessTok... 目录配置参数 调用代码获取Access_token调用发货的接口类注意点总结配置参数 首先需要获取Ac

JAVA SE包装类和泛型详细介绍及说明方法

《JAVASE包装类和泛型详细介绍及说明方法》:本文主要介绍JAVASE包装类和泛型的相关资料,包括基本数据类型与包装类的对应关系,以及装箱和拆箱的概念,并重点讲解了自动装箱和自动拆箱的机制,文... 目录1. 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱2. 泛型2

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

将java程序打包成可执行文件的实现方式

《将java程序打包成可执行文件的实现方式》本文介绍了将Java程序打包成可执行文件的三种方法:手动打包(将编译后的代码及JRE运行环境一起打包),使用第三方打包工具(如Launch4j)和JDK自带... 目录1.问题提出2.如何将Java程序打包成可执行文件2.1将编译后的代码及jre运行环境一起打包2

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb