河南科技大学数据挖掘课程设计报告

河南科技大学

课 程 设 计 说 明 书

课程名称  __软件项目综合实践   __

题    目   超市商品销售数据挖掘系统  

学    院         信息工程学院           

班    级          计科113             

学生姓名           彭逸帆             

学    号          111404060319          

指导教师        白秀玲、赵海霞、张蕾   

日    期        2014.9.22~2014.9.30    

目录

第1章 数据挖掘基本理论.... 1

§1.1 数据挖掘的概念... 1

§1.2 数据挖掘的步骤... 1

第2章 系统分析... 1

§2.1 系统用户分析... 1

§2.2 系统功能分析... 2

§2.3 系统算法分析... 2

第3章 数据管理... 3

§3.1 数据管理的方法... 3

§3.2 数据管理的具体实现过程... 3

第4章 数据采集... 3

§4.1 数据采集的方法... 3

§4.2 数据采集的具体实现过程... 3

第5章 数据预处理... 3

§5.1 数据预处理的方法... 3

§5.2 数据预处理的具体实现过程... 4

第6章 数据挖掘... 4

§6.1 算法描述与流程图... 5

§6.2 数据结构的设计... 5

§6.3 算法的具体实现... 6

第7章 结果显示与解释评估... 6

§7.1 参数设置... 11

§7.2 结果显示界面的具体实现... 11

§7.3 解释评估... 11

学习体会      15

参考文献      15

致    谢      15


§第1章 数据挖掘基本理论

§1.1 数据挖掘的概念

     数据挖掘又称为数据库中知识发现,它是一个从大量数据中抽取挖掘出来未知的、有价值的模式或规律等知识的复杂过程。

§1.2  数据挖掘的步骤

     首先进行数据预处理,从数据库里提取数据,使其形成集合列表形式,以便在程序中扫描数据库的时候,可以直接遍历此集合列表,即达到扫描数据的目的。然后生成K项频繁集。最后通过K项频繁集与最小信任度比较获得关联规则。并显示关联规则。生成K项频繁集的过程,首先是生成1项频繁集,之后利用递归方法,直到不能再生成频繁集为止。

§第2章 系统分析

§2.1 系统用户分析

利用数据挖掘技术可以帮助获得决策所需的多种知识。在许多情况下,用户并不知道数据存在哪些有价值的信息知识,因此对于一个数据挖掘系统而言,它应该能够同时搜索发现多种模式的知识,以满足用户的期望和实际需要。此外数据挖掘系统还应能够挖掘出多种层次(抽象水平)的模式知识。数据挖掘系统还应容许用户指导挖掘搜索有价值的模式知识。比如:作为一个商场主管,肯定想要知道商场顾客的购物习惯;尤其是希望了解在(一次)购物过程中,那些商品会在一起被(顾客所)购买。为帮助回答这一问题,就需要进行市场购物分析,即对顾客在商场购物交易记录数据进行分析。所分析的结果将帮助商场主管制定有针对性的市场营销和广告宣传计划,以及编撰合适的商品目录。比如:市场购物分析结果将帮助商家对商场内商品应如何合理摆放进行规划设计。其中一种策略就是将常常一起购买的商品摆放在相邻近的位置,以方便顾客同时购买这两件商品;如:如果顾客购买电脑的同时常也会购买一些金融管理类软件,那么将电脑软件摆放在电脑硬件附近显然将有助于促进这两种商品的销售;而另一种策略则是将电脑软件与电脑硬件分别摆放在商场的两端,这就会促使顾客在购买两种商品时,走更多的路从而达到诱导他们购买更多商品的目的。比如:顾客在决定购买一台昂贵电脑之后,在去购买相应金融管理软件的路上可能会看到安全系统软件,这时他就有可能购买这一类软件。市场购物分析可以帮助商场主管确定那些物品可以进行捆绑减价销售,如一个购买电脑的顾客很有可能购买一个捆绑减价销售的打印机。

§2.2 系统功能分析

我们组所开发的超市销售记录数据挖掘系统是采用关联规则挖掘的方法来挖掘出商家希望得到的销售信息。关联规则挖掘就是从大量的数据中挖掘出有价值描述数据项之间相互联系的有关知识。我们开发的超市销售记录数据挖掘系统主要应用就是市场购物分析。根据被放到一个购物袋的(购物)内容记录数据而发现的不同(被购买)商品之间所存在的关联知识无疑将会帮助商家分析顾客的购买习惯。如图- 所示。发现常在一起被购买的商品(关联知识)将帮助商家制定有针对性的市场营销策略。比如:顾客在购买牛奶时,是否也可能同时购买面包或会购买哪个牌子的面包,显然能够回答这些问题的有关信息肯定会有效地帮助商家进行有针对性的促销,以及进行合适的货架商品摆放。如可以将牛奶和面包放在相近的地方或许会促进这两个商品的销售。

将商场所有销售商品设为一个集合,每个商品(item)均为一个取布尔值(真/假)的变量以描述相应商品是否被(一个)顾客购买。因此每个顾客购物(袋)就可以用一个布尔向量来表示。分析相应布尔向量就可获得那些商品是在一起被购买(关联)的购物模式。如顾客购买电脑的同时也会购买金融管理软件的购物模式就可以用以下的关联规则来描述:

computer=>financial_management_software[support=2%,confidence=60%]

关联规则的支持度(support)和信任度(confidence)是两个度量有关规则趣味性的方法。它们分别描述了一个被挖掘出的关联规则的有用性和确定性。规则的支持度为2%,就表示所分析的交易记录数据中有交易记录同时包含电脑和金融管理软件(即在一起被购买)。规则的60%信任度则表示有60%的顾客在购买电脑的同时还会购买金融管理软件。通常如果一个关联规则满足最小支持度阈值(minimum support threshold)和最小信任度阈值(minimum confidence threshole),那么就认为该关联规则是有意义的;而用户或专家可以设置最小支持度阈值和最小信任度阈值。

§2.3系统算法分析

超市商品销售数据挖掘系统采用关联规则算法,主要进行数据管理。对数据

库中的数据进行管理和维护工作。 数据采集。从数据库中采集数据,形成事务

集合。数据预处理。将采集到的数据转换为可进行数据挖掘的形式。数据挖掘。

采用关联规则中的Apriori算法对超市销售事务集合进行数据挖掘。结果显示与

解释评估。把挖掘出的结果以一种直观的方式显示出来,并对挖掘出的结果进行

评价。

§第3章 数据管理

§3.1数据管理的方法

数据管理是利用计算机硬件和软件技术对数据进行有效的收集、存储、处理和应用的过程。其目的在于充分有效地发挥数据的作用,而实现数据有效管理的关键是数据组织,在数据库系统中所建立的数据结构,更充分地描述了数据间的内在联系,便于数据修改、更新与扩充,同时保证了数据的独立性、可靠性、安全性与完整性,减少了数据冗余,故提高了数据共享程度及数据管理效率。

       我们在数据库中建立了一张表,用于存放所有的销售记录,每条销售记录都存放于这一张表中,用于后面的数据挖掘。并在录入数据库的过程中检查了数据的正确性,把异常数据剔除在外,确保了数据库的正确性、一致性。

§第4章 数据采集

§4.1数据采集的方法

数据采集在数据挖掘的过程中是必不可少的,毕竟只有采集到了大量的、正确的、完整的数据,才能够为后面数据挖掘提供良好的基础,得到有价值的信息。本次课程设计中,我们通过走访超市向他们征询销售记录,在网上搜索相关的超市销售记录的方式收集到了两份数据,通过去除异常数据、冗余数据把两份数据合并到一张表里,为后面数据挖掘提供必要的条件,确保得到有价值的信息。

本软件在开发中,数据采集主要是借用程序和人工来实现的。通过人工的录入来输入超市的销售记录数据,然后再借用所编写的程序来筛选出所要挖掘的销售物品的信息,以备后期数据预处理和数据挖掘所使用。

§第5章 数据预处理

§5.1 数据预处理的方法

    实世界中数据大体上都是不完整,不一致的脏数据,无法直接进行数据挖掘,或挖掘结果差强人意。为了提高数据挖掘的质量产生了数据预处理技术。数据预处理有多种方法:数据清理,数据集成,数据变换,数据归约,数据离散化等。这些数据处理技术在数据挖掘之前使用,大大提高了数据挖掘模式的质量,降低实际挖掘所需要的时间。

    本次课程设计中主要用到了前四种方法即数据清理,数据集成,数据变换,数据归约完成数据入库前的数据预处理过程,由于种种原因最后选取的数据量不是很大,所以在这里并没有使用全部的数据预处理方法。

§第6章 数据挖掘

§6.1算法描述与流程图

§6.1.1 算法描述

Apriori算法是挖掘产生布尔关联规则所需频繁项集的基本算法;它也是一个很有影响的关联规则挖掘算法。Apriori算法就是根据有关频繁项集特性的先验知识(prior knowledge)而命名的。该算法利用了一个层次顺序搜索的循环方法来完成频繁项集的挖掘工作。这一循环方法就是利用k-项集来产生(k+1)-项集。具体做法就是:首先找出频繁1-项集,记为L1;然后利用L1来挖掘L2,即频繁2-项集;不断如此循环下去直到无法发现更多的频繁k-项集为止。每挖掘一层Lk就需要扫描整个数据库一遍。为提高按层次搜索并产生相应频繁项集的处理效率。Apriori算法利用了一个重要性质,又称为Apriori性质来帮助有效缩小频繁项集的搜索空间。

Apriori性质:一个频繁项集中任一子集也应是频繁项集。

Apriori性质是根据以下观察而得出结论。根据定义:若一个项集I不满足最小支持度阈值s,那么该项集I就不是频繁项集,即P(I)<s;若增加一个项A到项集I中,那么所获得的新项集I∪A在整个交易数据库所出现的次数也不可能多原项集I出现的次数,因此I∪A也不可能是频繁的,即P(I∪A)<s。这样就可以根据逆反公理:即若一个集合不能通过测试,该集合所有超集也不能通过同样的测试。因此很容易确定Apriori性质成立。

为了解释清楚Apriori性质是如何应用到频繁项集的挖掘中的,这里就以用 Lk-1来产生Lk为例来说明具体应用方法。利用Lk-1来获得Lk主要包含两个处理步骤,即连接和删除操作步骤。

                         

(1) 连接步骤。为发现Lk,可以将Lk-1中两个项集相连接以获得一个Lk的候选集合Ck。设l1和l2为Lk-1中的两个项集(元素),记号表示li[j] 中的第j个项;如li[k-2]就表示li中的倒数第二项。为方便起见,假设交易数据库中各交易记录中各项均已按字典排序。若Lk-1的连接操作记为Lk-1?Lk-1 ,它表示若l1和l2中的前(k-2)项是相同的,也就是说若有(l1[1]=l2[1])∧…∧(l1[k-2]=l2[k-2]) ∧(l1[k-1]<l2[k-1]),则Lk-1中l1和l2的内容就可以连接到一起。而条件(l1[k-1]<l2[k-1])可以确保不产生重复的项集。

(2) 删除步骤。Ck是Lk的一个超集,它其中的各元素(项集)不一定都是频繁项集,但所有的频繁-项集一定都在Ck中,即有Lk包含于Ck。扫描一遍数据库就可以决定Ck中各候选项集(元素)的支持频度,并由此获得Lk中各个元素(频繁k-项集)。所有频度不小于最小支持频度的候选项集就是属于Lk的频繁项集。然而由于Ck中的候选项集很多,如此操作所涉及的计算量(时间)是非常大的,为了减少Ck的大小,就需要利用Apriori性质:“一个非频繁(k-1)-项集不可能成为频繁k-项集的一个子集”。因此若一个候选k-项集中任一子集((k-1)-项集)不属于Lk-1,那么该候选k-项集就不可能成为一个频繁k-项集,因而也就可以将其从Ck中删去。

§6.1.2 算法流程图

图6-1 算法流程

§6.2数据结构的设计

因为挖掘过程中始终都是对项集进行操作,所以主要是对数据项集的数据结构设计,采用如下设计:

     class AprioriSet

    {string _TID;

        List<string> _Item;

        public string TID

        {

            get

            { return _TID; }

             set

            {_TID = value; }  

        }

        public List<string> Item

        {

            get

            { return _Item; }

              

             set

            { _Item = value;}          

                    }

        public AprioriSet(string tID, List<string> item)

        {

            _TID = tID;

            _Item = item;

        }}

§6.3算法的具体实现

public Apriori()

        {

            try

            {

                originDataList = DBHelper.getList("select productsID from record");

                originDataList=DBHelper.transOriginListToStringList(originDataList);

            }

            catch

            {

                throw;

            }

        }

        #region "工具"

        #endregion

        /// <summary>

        /// 得到所有的频繁项集

        /// </summary>

        /// <returns></returns>

        public Dictionary<string, int> getFrequentItems()

        {

            Dictionary<string, int> frequentCollectionMap = new Dictionary<string, int>();//所有的频繁项集

            DBHelper.DictionaryAddAll(ref frequentCollectionMap, getNewFrequentItems());

            Dictionary<string, int> itemkFcMap = new Dictionary<string, int>();

            DBHelper.DictionaryAddAll(ref itemkFcMap, getNewFrequentItems());

            while (itemkFcMap != null && itemkFcMap.Count() != 0)

            {

                Dictionary<string, int> candidateCollection = getCandidateCollection(itemkFcMap);

                foreach (string trans in originDataList)

                {

                    for (int j = 0; j < candidateCollection.Count; j++)

                    {

                        KeyValuePair<string, int> kvp = candidateCollection.ElementAt(j);

                        bool flag = true;    //用来判断交易中是否出现候选项,如果出现计数加1

                        string[] candidateItems = kvp.Key.Split(new string[] { ITEM_SPLIT }, System.StringSplitOptions.RemoveEmptyEntries);

                        for (int i = 0; i < candidateItems.Length; i++)

                        {

                            if (trans.IndexOf(candidateItems[i] + ITEM_SPLIT) == -1)

                            {

                                flag = false;

                                break;

                            }

                        }

                        if (flag)

                        {

                            int count = kvp.Value;

                            candidateCollection.Remove(kvp.Key);

                           

                            candidateCollection.Add(kvp.Key, kvp.Value + 1);

                        }

                    }

                }

                itemkFcMap.Clear();

                foreach (KeyValuePair<string, int> kvp in candidateCollection)

                {

                    int count = kvp.Value;

                    if (count >= SUPPORT)

                    {

                       

                        itemkFcMap.Add(kvp.Key, kvp.Value);

                    }

                }

                //合并所有频繁集

                DBHelper.DictionaryAddAll(ref frequentCollectionMap, itemkFcMap);

            }

            return frequentCollectionMap;

        }

       

        /// <summary>

        /// 得到满足支持度的频繁项集

        /// </summary>

        /// <returns></returns>

        private Dictionary<string, int> getNewFrequentItems()

        {

            Dictionary<string, int> FIDictionary1 = new Dictionary<string, int>();

            Dictionary<string, int> FIDictionary2 = new Dictionary<string, int>(); //频繁1项集

            foreach (string originItems in originDataList)

            {

                string[] items = originItems.Split(new string[] { ITEM_SPLIT }, System.StringSplitOptions.RemoveEmptyEntries);

                foreach (string item in items)

                {

                    int count = 0;

                    bool result = FIDictionary1.TryGetValue(item + ITEM_SPLIT, out count);

                    if (!result)

                    {

                        FIDictionary1[item + ITEM_SPLIT] = 1;

                    }

                    else

                    {

                        FIDictionary1[item + ITEM_SPLIT] = count + 1;

                    }

                }

            }

            Dictionary<string, int>.KeyCollection keySet = FIDictionary1.Keys;

            foreach (string key in keySet)

            {

                int count = FIDictionary1[key];

                if (count >= SUPPORT)

                {

                    FIDictionary2[key] = count;

                }

            }

            return FIDictionary2;

        }

        /// <summary>

        /// </summary>

        /// <param name="itemkFcMap"></param>

        /// <returns></returns>

        private Dictionary<string, int> getCandidateCollection(Dictionary<string, int> itemkFcMap)

        {

            Dictionary<string, int> candidateCollection = new Dictionary<string, int>();

            Dictionary<string, int>.KeyCollection itemkSet1 = itemkFcMap.Keys;

            Dictionary<string, int>.KeyCollection itemkSet2 = itemkFcMap.Keys;

            foreach (string itemk1 in itemkSet1)

            {

                foreach (string itemk2 in itemkSet2)

                {

                                       string[] tmp1 = itemk1.Split(new string[] { ITEM_SPLIT }, System.StringSplitOptions.RemoveEmptyEntries);

                                      string[] tmp2 = itemk2.Split(new string[] { ITEM_SPLIT }, System.StringSplitOptions.RemoveEmptyEntries);

                    string c = "";

                    if (tmp1.Length == 1)

                    {

                        if (tmp1[0].CompareTo(tmp2[0]) < 0)

                        {

                            c = tmp1[0] + ITEM_SPLIT + tmp2[0] + ITEM_SPLIT;

                        }

                    }

                    else

                    {

                        bool 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;

                        }

                    }

                    bool hasInfrequentSubSet = false;

                    if (!c.Equals(""))

                    {

                        string[] tmpC = c.Split(new string[] { ITEM_SPLIT }, System.StringSplitOptions.RemoveEmptyEntries);

                        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;

                                }

                            }

                            int mValue = 0;

                            if (!itemkFcMap.TryGetValue(subC, out  mValue))

                            {

                                hasInfrequentSubSet = true;

                                break;

                            }

                        }

                    }

                    else

                    {

                        hasInfrequentSubSet = true;

                    }

                    if (!hasInfrequentSubSet)

                    {

                        candidateCollection[c] = 0;

                    }

                }

            }

            return candidateCollection;

        }

    }

}

§第7章 结果显示与解释评估

§7.1 参数设置

本系统所用参数包括:最小支持度、最小置信度。最小支持度用于筛选出商品的频繁项集集合,从而算出支持度;最小置信度用于筛选出符合要求的商品集合之间信任度集合。通过最小支持度和最小置信度用户可以根据实际需要来决定筛选的程度。

§7.2 结果显示界面的具体实现

§7.2.1 数据呈现的具体实现

数据呈现界面主要使用的组件有:ADOConnection, ADOQuery, DataSource, DBGrid, Button.

各个组件的功能:

ADOConnection的功能是建立与数据库的连接;

ADOQuery的功能是用于检索和操作由合法的SQL语句产生的数据集,也可以执行一条SQL命令;

DataSource的功能是作为数据控制组件DBGrid,DBEdit的数据传送通道;

DBGrid的功能是为前端应用程序提供浏览数据库数据的表格,这些表格操作者编辑数据;

Button(刷新)的功能是执行重新输出销售记录表的所有数据的命令;

§7.2.2 数据挖掘的具体实现

数据挖掘界面主要使用的组件有:ADOConnection, ADOQuery, DataSource, Label,edit,GroupBox,ListBox,Button。

各个组件的功能:

ADOConnection的功能是建立与数据库的连接;

ADOQuery的功能是用于检索和操作由合法的SQL语句产生的数据集,也可以执行一条SQL命令;

DataSource的功能是作为数据控制组件DBGrid,DBEdit的数据传送通道;

Label(最小支持度,最小置信度)的功能是显示文字符号作为标签使用;

Edit的功能是显示、修改数据库表中当前记录的字段数据;

GroupBox的功能是组合框,把一些相关组件组合一起;

ListBox显示数据库表中一个指定字段的数据;

Button(开始挖掘)的功能是执行输入数据最小支持度和最小置信度到表中;

§7.3 解释评估

用可视化的形式显示出数据挖掘的成果,固然为用户提供了使用上的方便,尤其是我们利用了极简的操作界面和很少的操作按钮,避免的用户在使用中的复杂,但是正是由于这种简单的界面和操作,屏蔽了内部处理的细节和步骤,使用户只是单单使用程序而不是理解程序,对程序本身而言是安全的,但对用户而言是隐秘的。

学习体会

通过这次的课程设计,然我对数据挖掘技术有了一个整体的认识。同样在编写程序的时候也遇到了这样或那样的问题。但在老师及同学们的帮助下,艰难的完成了这个系统。这让我对数据挖掘技术以后的深入学习打下了良好的基础。通过课程设计,既复习了以前的旧知识,又学到了一些新的知识。当然我们也遇到了各种问题,这些问题,又都是课本上很少提到的、更深一层的实践与知识相结合的问题,这并不是我们平时只靠课本,就可以轻易解决的。所以,锻炼了我们面对难题,学会用已掌握的知识去解决具体问题的能力,进一步培养了独立思考问题和解决问题的能力。

但是在整个课程设计阶段,自己还有很多不足的地方,一旦遇到很难解决的问题,陷入困境后,很难自己独立的解决问题,常常需要老师的引导。在今后的学习工作过程中还要加强独立解决问题的能力。总而言之,这次数据挖掘程序设计实践让我们收获很大。

所以尽管遇到了一些问题,但是却学到了很多知识,同时也找到了自己的不足和其他同学的优点,明白了团结合作的重要性,总之很感谢这次课程设计以及指导老师和小组成员们。

参考文献

[1] 萨师煊,王珊. 数据库系统概论. 高等教育出版社 20##-5 第五版

[2] Margarent H.Dunham. 数据挖掘教程. 清华大学出版社 20##-1 第一版

[3] 陈文伟. 数据仓库与数据挖掘. 人民邮电出版社 20##-4第一版

致谢

感谢白秀玲、赵海霞、张蕾老师的悉心指导,感谢同组同学对我的帮助,正是由于我们齐心协力,同策同力才使得这次课程设计成功完成,并让我学到了很多东西。

相关推荐