你的位置是:网站首页--- 技术文章---计算机技术

Fp增长算法的.Net实现的编码分析



【 字体:


作者:ChakMan Kwan
联系邮件:jingle_guan(at)163.com
最后修改时间:2008-4-29

写在前面:Fp增长算法的关键是建立一棵Fp树,和对Fp树的挖掘。下面就是介绍在.Net平台上Fp增长算法的具体实现。而这一份作品的科学依据是《数据挖掘概念与技术》,(加)JiaweiHan,Micheline Kamber著中5.2.4节的FP增长算法。

效果图
 

整个项目最重要的三个类是FormFPTree,FPTree和FPGrowthFacade,FormFPTree是一个窗体类型的类,它主要是将用户的要求传达到程序,而FPTree就是FP树的抽象,如果你手头上有《数据挖掘概念与技术》,(加)JiaweiHan,Micheline Kamber著,FPTree真表达的对象就是5.2.4的图5-7,“存放压缩的频繁模式信息的FP树”。而FPGrowthFacade类就是FP树的挖掘类,它需要传入一个FP树。除这三个主要的类外,还有好几个类,它们是用来表达一个个的事实,程序上面说就是实体。
 

FormFPTree是一个以窗体形式展示的界面,通过ReadFile方法读取项目下面的数据文件而取得事务的集合,数据文件中,第一行是一份事务数据,如I1,I4,I5,它表示这三个项目会同时发生。FormFPTree窗体要求先进行预处理,也就是分析事务的数量,这样,可以一下子计算出最小支持度计数的大小,于是在下面的代码中就出来了_count > MinSupCount – 1的判断,意思是,如果项集的计数大于最小支持度计数,就应该被放入到频繁一项集中。下面是对FP树的建立,但最主要是频繁一项集的建立。最后FP树的成型是通过调用_fpTree.InitializeFPTree();实现的。

                //读取当前行
                sLineString = sr.ReadLine();
                //提取当前行的数组
                _arrItemName = sLineString.Split(new Char[] { ' ' },
                    StringSplitOptions.RemoveEmptyEntries);
                //将数组放到内存中
                //_arrStrList.Add(_arrItemName);
                List _listItemName = new List();
                //将频繁项集合放到Hashtable中
                for (int i = _start; i < _arrItemName.Length; i++)
                {                   
                    _itemName = _arrItemName[i];                    
                    _listItemName.Add(
                        new ItemInfo(_itemName,0));
                    int _count = 1;
                    if (_hashTable.ContainsKey(_itemName))
                    {
                        _count = Convert.ToInt32(_hashTable[_itemName]) + 1;
                        _hashTable[_itemName] = _count;                      
                    }
                    else
                        _hashTable.Add(_itemName, _count);
                    //频繁
                    if (_count > MinSupCount - 1)
                    {
                        _fpTree.BuildFrequentItemList(_itemName, _count);
                    }
                }
                _listStrList.Add(_listItemName); //对FPTree传参

FPTree类的InitializeFPTree方法
这一个方法是在事务都加载完成之后使用的,加载完成的意思是数据已经从文本中读到内存中,并且已经选出了频繁一项集。
方法主要是建立了一棵树。       

        ///
        /// 建立FPTree
        ///
        public void InitializeFPTree()
        {
            // 每个频繁项,按频繁项集列表(L)次序排序
            //生成FPTree           
            //将事务数据库压缩到树中
            BuildFPTree(_listStrList, _hashFrequentItemLinkTable, _indexToId);
        }


FPTree类的另一个重要的功能就是建立条件FP树,条件FP树与FP树略有不同,它是在挖掘FP树的时候临时使用的FP树,但它的主要特性还是普通的FP树。在这里,笔者的处理是增加一个方法, 

        ///
        /// 建立条件FPTree
        ///      
        private void BuildConditionFPTree(List> _listStrList,  Hashtable _hashFrequentItemLinkTable, Hashtable _indexToId)
        {
            //冒泡排序,排列频繁项集列表     
            int count = _hashFrequentItemTable.Count;
            for (int bubble = 0; bubble < count; bubble++)
            {
                for (int lookup = bubble + 1; lookup < count; lookup++)
                {
                    //小的计数往下排
                    if ((int)_hashFrequentItemTable[_indexToId[bubble]] <
                        (int)_hashFrequentItemTable[_indexToId[lookup]])
                    {
                        object temp = _indexToId[bubble];
                        _indexToId[bubble] = _indexToId[lookup];
                        _indexToId[lookup] = temp;
                        temp = _idToIndex[_indexToId[bubble]];
                        _idToIndex[_indexToId[bubble]] = _idToIndex[_indexToId[lookup]];
                        _idToIndex[_indexToId[lookup]] = temp;
                    }
                }
            }
            ......
        }

FPGrowthFacade类
这个类的作用主要是调用挖掘方法对FP树进行挖掘。FPGrowth就是这个方法,初始化时,α传入的参数是null。
要了解这个挖掘的过程,难免要了解一下原始的实现过程的描述。
标准的实现过程
Procedure  FP_growth(Tree, α)
(1) if Tree 含单个路径P then
(2)   for each路径P中节点的每个组合(记作β)
(3)      产生模式β∪α,其支持度度数support_count等于β中节点的最小支持度计数,
(4) else for Tree的头表中的每个αi{
(5)   产生模式β=αi∪α,其支持度计数support_count =αi.support_count;
(6)   构造β的条件模式基,然后构造β的条件FP树Treeβ;
(7)   if Treeβ ≠⊙ then
(8)      调用FP_growth(Treeβ, β);}

代码的实现

        ///
        /// 在频繁一项集表中,从后到前遍历
        /// 生成条件FPTree
        ///
        ///
        public void FPGrowth(FPTree _fpTree, List _itemSet)
        {
            if (_fpTree.SinglePath)
            { 
                //返回所有组合,用_itemSetList保存
                List _itemSetList = new List();
                CombineNodes(_fpTree, _itemSetList);
                //产生模式 β∪α,_itemSetList是β的集合               
                AddPattern(_itemSet, _itemSetList);
               
                _itemSet.Clear();
            }
            else
            {
                for (int i = _fpTree.FrequentItemCount - 1; i > -1; i--)
                {                   
                    //头表中的每个a(i)
                    TreeNodeItem _treeNodeItem = _fpTree.GetLinkNode(i);                   
                    //产生模式β = a(i)∪α
                    List _itemSetConbine = new List();
                    if (_treeNodeItem != null)
                    {
                        if (_itemSet == null)
                            _itemSet = new List();
                        TreeNodeItem[] _arrTreeNodeItem = new TreeNodeItem[_itemSet.Count];
                        _itemSet.CopyTo(_arrTreeNodeItem);
                        _itemSetConbine.AddRange(_arrTreeNodeItem);
                        _itemSetConbine.Insert(0,_treeNodeItem);                       
                    }
                    //构造条件FPTree(1)
                    FPTree _conditionFPTree = new FPTree();
                    _conditionFPTree.MinSupCount = _fpTree.MinSupCount;
                    List> _listStrList = new List>();                   
                    Hashtable _hashTable = new Hashtable(); 
                    bool _doLoop = (_treeNodeItem != null);
                    while (_doLoop)
                    {
                        //构造条件模式基,支持度计数由小到大放入List
                        List _treeNodeItemList = new List();
                        GetParentPath(_treeNodeItem.CloneNode(), _treeNodeItemList, _hashTable, _conditionFPTree);
                        //如果模式已经产生并且不是频繁一项集
                        if (_treeNodeItemList.Count == 0 && _itemSetConbine.Count >1)                       
                            //产生模式
                            AddPattern(_itemSetConbine,_fpTree);                           
                       
                        //构造条件FPTree(2)
                        if(_treeNodeItemList.Count>0)                           
                        _listStrList.Add(_treeNodeItemList);                   
                       
                        //多个条件模式基
                        if (_treeNodeItem.NextNode != null)
                            _treeNodeItem = _treeNodeItem.NextNode;
                        else
                            _doLoop = false;
                    }                  
                    //构造条件FPTree(3)
                    if(_listStrList.Count >0)
                    _conditionFPTree.InitializeConditionFPTree(_listStrList);
               
                    //检查树是否为空
                    if (_conditionFPTree.TopNode.Nodes.Count > 0)
                        FPGrowth(_conditionFPTree, _itemSetConbine);  
                    else
                        _itemSetConbine = _itemSet;
                }               
            }
        }

项目源代码下载

注意:当前源代码是由笔者经过50个小时的奋斗而完成的,虽然这说明了笔者资质一般,水平不高外,也说明了作品是经过努力才完成的.暂时不授权任何人对源代码进行转载或修改.只授权查看.
由于笔者没有充分准备,而这篇文章又极其重要,于是匆匆发布.


出处:小作坊网ChakMan原创
Copyright © 2006-2008 小作坊网 All rights reserved.
备案号:粤ICP备09058104号          电子信箱: jingle_guan#163.com