日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

FP-Growth算法的Java實現+具體實現思路+代碼

瀏覽:14日期:2022-08-10 08:07:01
目錄FP-Growth算法的Java實現第一次掃描代碼第二次掃描挖掘頻繁項集總結FP-Growth算法原理

其他大佬的講解

FP-Growth算法詳解

FP-Growth算法的Java實現

這篇文章重點講一下實現。如果看了上述給的講解,可知,需要兩次掃描來構建FP樹

第一次掃描

第一次掃描,過濾掉所有不滿足最小支持度的項;對于滿足最小支持度的項,按照全局支持度降序排序。

按照這個需求,可能的難點為如何按照全局支持度對每個事務中的item排序。我的實現思路

掃描原數據集將其保存在二維列表sourceData中 維護一個Table,使其保存每個item的全局支持度TotalSup 在Table中過濾掉低于閾值minSup的項 將Table轉換為List,并使其按照TotalSup降序排序 新建一個二維列表freqSource,其保留sourceData中的頻繁項,并將每個事務按全局支持度降序排序代碼

/** * 掃描原數據集,生成事務集 * @param path 數據集路徑 * @throws IOException */ private void scanDataSet(String path) throws IOException {if(path.equals('')){ path = filePath;}FileReader fr = new FileReader(path);BufferedReader bufferedReader = new BufferedReader(fr);String str;//int maxLength = 0;while ( (str = bufferedReader.readLine())!=null){ ArrayList<Integer> transaction = new ArrayList<>(); String[] tempEntry ; tempEntry = str.split(' '); for(int i =0;i< tempEntry.length;i++){if(!tempEntry[i].equals('')){ int itemValue = Integer.parseInt(tempEntry[i]); transaction.add(itemValue); if(!similarSingleItemLinkedListHeadsTable.containsKey(itemValue)){similarSingleItemLinkedListHeadsTable.put(itemValue, new SimilarSingleItemLinkedListHead(itemValue,null,1)); }else{//將該項的全局支持度+1similarSingleItemLinkedListHeadsTable.get(itemValue).addSupTotal(); }} }// if(tempEntry.length>maxLength){//maxLength = tempEntry.length;// } sourceDataSet.add(transaction);}//System.out.println(maxLength);deleteNonFreqInSSILLHTAndSort();deleteNonFreqInSDSAndSort();bufferedReader.close();fr.close(); }/** * 去除相似項表(similarSingleItemLinkedListHeadsTable)的非頻繁項,并按全局支持度對similarSingleItemLinkedListHeads降序排序 */ private void deleteNonFreqInSSILLHTAndSort() {Hashtable<Integer,SimilarSingleItemLinkedListHead> copyOfSSILLHT =(Hashtable<Integer, SimilarSingleItemLinkedListHead>) similarSingleItemLinkedListHeadsTable.clone();Set<Integer> keySet = copyOfSSILLHT.keySet();//刪除非頻繁項for(int key: keySet){ if(similarSingleItemLinkedListHeadsTable.get(key).getSupTotal()<minSupCnt){//低于支持度閾值similarSingleItemLinkedListHeadsTable.remove(key); }}//按全局支持度排序similarSingleItemLinkedListHeadList = new ArrayList<>(similarSingleItemLinkedListHeadsTable.values());similarSingleItemLinkedListHeadList.sort(new Comparator<SimilarSingleItemLinkedListHead>() { @Override public int compare(SimilarSingleItemLinkedListHead o1, SimilarSingleItemLinkedListHead o2) {return o2.getSupTotal() - o1.getSupTotal(); }}); }/** * 去除事務集(sourceDataSet)的非頻繁項,并且按全局支持度對每個事務的item進行降序排序 * 其結果保存在freqSourceSortedDataSet */ private void deleteNonFreqInSDSAndSort(){freqSourceSortedDataSet = (ArrayList<ArrayList<Integer>>) sourceDataSet.clone();for(int i =0;i<sourceDataSet.size();i++){ for(int j = 0;j<sourceDataSet.get(i).size();j++){int item = sourceDataSet.get(i).get(j);// 由于此時SSILLHT里的項都是頻繁項,只需要確定item是否存在在其中即可,存在即代表頻繁.if(visitSupTotal(item)==-1){ //將非頻繁項標記為最小整數值 freqSourceSortedDataSet.get(i).set(j,Integer.MIN_VALUE);} } //將標記的項移除. freqSourceSortedDataSet.get(i).removeIf(e->e == Integer.MIN_VALUE); insertSort(freqSourceSortedDataSet.get(i));}freqSourceSortedDataSet.removeIf(e->e.size() == 0); }第二次掃描

第二次掃描,構造FP樹。參與掃描的是過濾后的數據,如果某個數據項是第一次遇到,則創建該節點,并在headTable中添加一個指向該節點的指針;否則按路徑找到該項對應的節點,修改節點信息

這里比較簡單,因為已經有過濾、排序好的數據freqSourceSortedDataSet。我們只需要

遍歷freqSourceSortedDataSet的每一個事務trans,遍歷trans中的每一個item構建FP樹和相似項鏈表 如果某item第一次遇到,則需要創建該節點并在相似項鏈表中鏈接它。 鏈表不用多說。 這里的FP樹的子節點是不定個數的,需要用特殊的數據結構。我這里使用了HashTable

/** * 構建FP樹 */ private void buildFPTree(){for(ArrayList<Integer>trans:freqSourceSortedDataSet){ Node curTreeNode = fpTree.root; for(int item :trans){if(!curTreeNode.children.containsKey(item)){ Node node = new Node(item,1); curTreeNode.children.put(item,node); node.father = curTreeNode; buildSimilarSingleItemLinkedList(item,curTreeNode);}else{ curTreeNode.children.get(item).sup++;}curTreeNode=curTreeNode.children.get(item); }} } /** * 構建相似項鏈表 */ private void buildSimilarSingleItemLinkedList(int item,Node curTreeNode){//找到該item在相似項鏈表中的位置int index = searchForItemInHeadsList(item,(ArrayList<SimilarSingleItemLinkedListHead>) similarSingleItemLinkedListHeadList);if(similarSingleItemLinkedListHeadList.get(index).next == null){ similarSingleItemLinkedListHeadList.get(index).next = curTreeNode.children.get(item);}else{ Node visitNode = similarSingleItemLinkedListHeadList.get(index).next; while (visitNode.nextSimilar!=null){visitNode = visitNode.nextSimilar; } if(visitNode != curTreeNode.children.get(item))visitNode.nextSimilar = curTreeNode.children.get(item);} } /** * 在HeadList中搜索某項的位置 * @param item 項 * @param similarSingleItemLinkedListHeads 頭結點鏈表 * @return 位置,-1表示未找到 */ private int searchForItemInHeadsList(int item, ArrayList<SimilarSingleItemLinkedListHead> similarSingleItemLinkedListHeads) {for(int i =0;i<similarSingleItemLinkedListHeads.size();i++){ if(similarSingleItemLinkedListHeads.get(i).getItemValue() == item){return i; }}return -1; }挖掘頻繁項集

這一部分個人覺得是實現上最困難的部分。但是我在B站或其他地方一涉及到這個地方都講得很快(B站也沒兩個視頻講這玩意兒,吐)。還有不同的概念,比如在黑皮書上講的是前綴路徑,在其他地方有條件模式基等概念。接下來的代碼均按照前綴路徑的說法來實現。

我們來捋一捋思路,挖掘頻繁項集需要干什么。

首先需要從后向前遍歷相似項鏈表的列表(這一列表已經在第一次掃描中按全局支持度排過序了)的每一項。 對每一項遞歸地進行如下步驟:

①記錄前綴路徑。我使用的方法是用一個HashSet記錄前綴路徑中出現的所有節點。

②記錄該FP樹的每一item的支持度。類似于前面的第一次掃描。

③根據記錄的支持度,如果item頻繁,則該item和當前的后綴為頻繁項集。

④再根據record構建該FP樹的相似項鏈表列表,去除掉非頻繁項(類似第一次掃描)和當前item構成條件FP樹。這里并不需要重新建立一個FP樹的結構來構成條件FP樹,因為記錄前綴路徑只需要訪問相似項和父項。

⑤對相似項鏈表列表的剩余項再進行①步驟,直到相似項鏈表列表中沒有項,為終止。

/** * 算法執行函數 * @param minSupCnt 最小支持度計數 * @param path 文件路徑 * @param pT 輸出結果的項集大小閾值 */ public void run(int minSupCnt,String path,int pT) throws IOException {this.printThreshold = pT;this.minSupCnt = minSupCnt;scanDataSet(path);buildFPTree();for(int i = similarSingleItemLinkedListHeadList.size()-1;i>=0;i--){ genFreqItemSet(similarSingleItemLinkedListHeadList.get(i).getItemValue() ,fpTree,similarSingleItemLinkedListHeadList,new TreeSet<>());}//genFreqItemSet(14,fpTree,similarSingleItemLinkedListHeadList,new TreeSet<>());System.out.println('頻繁項集個數:t'+cntOfFreqSet); }/** * 生成頻繁項集 * @param last 最后項 * @param fPTree 條件FP樹 * @param fatherSimilarSingleItemLinkedListHeads 父樹的相似項頭結點鏈表 * @param freqItemSet 頻繁項集 */ private void genFreqItemSet(int last,FPTree fPTree,List<SimilarSingleItemLinkedListHead>fatherSimilarSingleItemLinkedListHeads,TreeSet<Integer>freqItemSet) {FPTree conditionalFPTree = new FPTree();List<SimilarSingleItemLinkedListHead>similarSingleItemLinkedListHeads = new ArrayList<>();TreeSet<Integer>localFreqItemSet = (TreeSet<Integer>) freqItemSet.clone();int index ;index = searchForItemInHeadsList(last,(ArrayList<SimilarSingleItemLinkedListHead>) fatherSimilarSingleItemLinkedListHeads);Node firstNode = fatherSimilarSingleItemLinkedListHeads.get(index).next;HashSet<Node>record = new HashSet<>(); //用于記錄前綴路徑上出現的節點//記錄前綴路徑if(firstNode!=null){ record.add(firstNode); Node nodeToVisitFather = firstNode; Node nodeToVisitSimilar = firstNode; while (nodeToVisitSimilar!=null){nodeToVisitSimilar.supInCFP = nodeToVisitSimilar.sup;nodeToVisitFather = nodeToVisitSimilar;while (nodeToVisitFather!=null){ // 計算supInCFT if(nodeToVisitFather!=nodeToVisitSimilar)nodeToVisitFather.supInCFP += nodeToVisitSimilar.supInCFP; record.add(nodeToVisitFather); nodeToVisitFather = nodeToVisitFather.father;}nodeToVisitSimilar = nodeToVisitSimilar.nextSimilar; } //記錄在子樹中的支持度 Hashtable<Integer,Integer> supRecord = new Hashtable<>(); record.forEach(new Consumer<Node>() {@Overridepublic void accept(Node node) { int item = node.item; if(item == -1 ){ //根節點return; } if(supRecord.containsKey(item)){supRecord.put(item,supRecord.get(item)+ node.supInCFP); }else{supRecord.put(item,node.supInCFP); }} }); //輸出結果 if(supRecord.get(last)>=minSupCnt){localFreqItemSet.add(last);if(localFreqItemSet.size()>=printThreshold && !result.contains(localFreqItemSet)){ cntOfFreqSet++;// for(int i = localFreqItemSet.size()-1;i>=0;i--){//System.out.print(localFreqItemSet.get(i)+' ');// } localFreqItemSet.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) { System.out.print(integer+' ');} }); result.add(localFreqItemSet); System.out.println('');} } //構建相似項鏈表 record.forEach(new Consumer<Node>() {@Overridepublic void accept(Node node) { if(node.item == -1){ //根節點Node visitNode = node;buildConditionalFPTree(conditionalFPTree.root, visitNode,record,(ArrayList<SimilarSingleItemLinkedListHead>) similarSingleItemLinkedListHeads,supRecord,last); }} }); //按支持度降序排序 similarSingleItemLinkedListHeads.sort(new Comparator<SimilarSingleItemLinkedListHead>() {@Overridepublic int compare(SimilarSingleItemLinkedListHead o1, SimilarSingleItemLinkedListHead o2) { return o2.getSupTotal() - o1.getSupTotal();} }); if(similarSingleItemLinkedListHeads.size()>=1){//遞歸搜索頻繁項for(int i =similarSingleItemLinkedListHeads.size()-1;i>=0;i--){ genFreqItemSet(similarSingleItemLinkedListHeads.get(i).getItemValue(), conditionalFPTree,similarSingleItemLinkedListHeads,localFreqItemSet); // similarSingleItemLinkedListHeads.remove(i);} }} }/** * 遞歸構建條件FP樹 * @param rootNode 以該節點為根向下建立條件FP樹 * @param originalNode rootNode對應在原樹中的節點 * @param record 前綴路徑 * @param similarSingleItemLinkedListHeads 相似項表頭鏈表 * @param supRecord 支持度計數的記錄 * @param last 最后項 */ private void buildConditionalFPTree(Node rootNode,Node originalNode,HashSet<Node>record ,ArrayList<SimilarSingleItemLinkedListHead>similarSingleItemLinkedListHeads,Hashtable<Integer,Integer>supRecord,int last){if(originalNode.children!=null){ for(int key:originalNode.children.keySet()){ //遍歷originalNode的所有兒子節點,檢查其是否在前綴路徑中Node tempNode = originalNode.children.get(key);if(record.contains(tempNode)){ Node addedNode = new Node(tempNode.item, tempNode.supInCFP); if(last == key){ //去除last的所有節點tempNode.supInCFP = 0;continue; } if(supRecord.get(key)>=minSupCnt){//addedNode 拷貝 tempNode除兒子節點外的屬性addedNode.supInCFP = tempNode.supInCFP;rootNode.children.put(tempNode.item, addedNode);addedNode.father = rootNode;//構建相似項表int i = searchForItemInHeadsList(tempNode.item,similarSingleItemLinkedListHeads);if(i==-1){ similarSingleItemLinkedListHeads.add(new SimilarSingleItemLinkedListHead(key,addedNode, addedNode.supInCFP));}else{ similarSingleItemLinkedListHeads.get(i).setSupTotal(similarSingleItemLinkedListHeads.get(i).getSupTotal()+addedNode.supInCFP); Node visitNode = similarSingleItemLinkedListHeads.get(i).next; while (visitNode.nextSimilar!=null){visitNode = visitNode.nextSimilar; } if(visitNode!=addedNode){visitNode.nextSimilar= addedNode; }}buildConditionalFPTree(addedNode,originalNode.children.get(key),record,similarSingleItemLinkedListHeads,supRecord,last);addedNode.supInCFP = 0; //將supInCFP重置為0; }else{buildConditionalFPTree(rootNode,originalNode.children.get(key),record,similarSingleItemLinkedListHeads,supRecord,last); }} }} }總結

這篇文章就到這里,希望能給你帶來幫助,也希望你可以多多關注好吧啦網的其他精彩內容!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美国产91| 国产精品视频一区二区三区四蜜臂 | 视频一区在线播放| 免费日韩av片| 蜜桃视频一区二区三区在线观看| 日韩精品亚洲专区在线观看| 欧美亚洲网站| 91亚洲成人| 欧美日韩中文一区二区| 国产亚洲激情| 97精品久久| 久久精品国产网站| 久久久久久久久久久9不雅视频| 欧美高清一区| 中文无码日韩欧| 国产精品一区二区美女视频免费看 | 日韩在线精品| 老鸭窝毛片一区二区三区| 青青在线精品| 久久久国产精品一区二区中文| 日韩精品免费一区二区夜夜嗨| 激情综合五月| 99国产成+人+综合+亚洲欧美| 日本色综合中文字幕| 久久精品系列| 国产美女精品| 老司机精品视频网| 91精品国产91久久久久久黑人| 亚洲一区国产一区| 欧美国产先锋| 日韩午夜在线| 精品日产乱码久久久久久仙踪林| 91久久中文| 精品国产18久久久久久二百| 香蕉久久夜色精品国产| 久久精品网址| 亚洲啊v在线免费视频| 欧美激情国产在线| 亚洲欧洲美洲国产香蕉| 电影亚洲精品噜噜在线观看| 视频一区日韩精品| 久久精品国语| 国产毛片一区二区三区| 久久精品青草| 欧美xxxx性| 久久xxxx精品视频| 国产精品国产三级国产在线观看| 国产亚洲激情| 国产videos久久| 婷婷成人av| 国户精品久久久久久久久久久不卡 | 久久av免费| 丝袜美腿亚洲色图| 精品一区二区三区四区五区| 亚洲精品第一| 亚洲二区在线| 久久精品国产一区二区| 日韩影片在线观看| 9色国产精品| 神马久久午夜| 精品香蕉视频| 日韩福利视频一区| 伊人久久婷婷| 人人精品亚洲| 美女精品视频在线| 日韩精品导航| 久久亚洲欧洲| 夜久久久久久| 99精品网站| 成人福利av| 国产精品美女在线观看直播| 日韩午夜视频在线| 蜜桃av一区二区| 亚洲一区欧美二区| 不卡视频在线| 91精品国产自产在线观看永久∴| 国产一区二区三区四区| 国产精品成人国产| 国产精品欧美日韩一区| 日韩va欧美va亚洲va久久| 亚洲精品欧美| 日韩精品亚洲专区| 日韩国产欧美视频| 欧美日韩亚洲一区在线观看| 日本欧美一区二区| 中文字幕av一区二区三区人 | 欧美专区在线| 久久亚洲视频| 午夜性色一区二区三区免费视频| 中文无码久久精品| 日本不卡不码高清免费观看| 日韩精品视频网站| 日韩va亚洲va欧美va久久| 日韩av成人高清| 国产精品毛片久久久| 久久99偷拍| 国产成人在线中文字幕| 中国字幕a在线看韩国电影| 国精品产品一区| 亚洲深夜视频| 91久久久精品国产| 中国女人久久久| 亚洲区欧美区| 国产精品一区二区三区美女 | 国产亚洲久久| 久久中文字幕一区二区三区| 国产一区二区三区四区二区| 日韩在线免费| 好看的亚洲午夜视频在线| 亚洲专区欧美专区| 日韩欧美2区| 国产精品美女久久久久久不卡| 成人在线观看免费视频| 999久久久免费精品国产| 美女黄网久久| 欧美日韩视频免费看| 麻豆国产91在线播放| 秋霞影视一区二区三区| 亚洲天堂日韩在线| 国产极品久久久久久久久波多结野| 精品一区二区三区免费看| 成人精品中文字幕| 伊人国产精品| 国产在视频一区二区三区吞精| 蜜臀av免费一区二区三区| 一区二区电影在线观看| 欧美日韩夜夜| 久久久久久久久久久9不雅视频| 免费不卡在线观看| 美女久久精品| 久久国产中文字幕| 日韩中出av| 亚洲国产福利| 综合激情网...| 国内自拍视频一区二区三区| 99在线|亚洲一区二区| 国产精品流白浆在线观看| 婷婷成人在线| 国产精品一区二区99| 国产麻豆久久| 日韩激情中文字幕| 成人一区不卡| 伊人久久一区| 日韩国产欧美一区二区| 视频一区二区三区入口| 精品一区视频| 免费久久精品视频| 国产精品伦理久久久久久| 日韩中文字幕不卡| 国产一二在线播放| 日韩av网站在线免费观看| 欧美不卡高清| 精品少妇av| 亚洲精品日本| 99精品在线免费在线观看| 国产精品一区二区精品视频观看| 美女网站一区| 精品美女在线视频| 综合日韩在线| 麻豆91小视频| 欧美精品导航| 日本h片久久| 国产伊人精品| 国产精品亚洲片在线播放| 欧美日韩精品一本二本三本| 欧美专区一区| 亚洲一区二区免费看| 另类专区亚洲| 国产精品久久久久9999高清| 噜噜噜躁狠狠躁狠狠精品视频| 四虎成人av| 日韩精品免费观看视频| 激情久久五月| 岛国av免费在线观看| 国产麻豆精品| 午夜精品福利影院| 黄色亚洲大片免费在线观看| 国产黄大片在线观看| 国产精品一区二区三区www | 日韩在线观看不卡| 美女久久久久久| 国产日韩在线观看视频| 亚洲人妖在线| 麻豆亚洲精品| 尤物在线精品| 亚洲调教视频在线观看| 日韩一区亚洲二区| 水蜜桃精品av一区二区| 国产精品久久777777毛茸茸| 日韩欧美精品一区二区综合视频| 视频一区二区不卡| 亚洲欧美日韩专区| 欧美在线亚洲| 欧美日韩国产探花| 久久亚洲国产| 99久久精品国产亚洲精品| 中文一区一区三区高中清不卡免费| 精品国产一区二| 丁香婷婷久久| 大香伊人久久精品一区二区|