資料採礦之關聯規則挖掘之Apriori演算法實現

來源:互聯網
上載者:User

演算法細節見論文:Fast Algorithm for Mining Association Rules

 圖形化版本工程+測試案例下載戳這http://download.csdn.net/detail/michealtx/4266155

控制台版本C++代碼如下:

#include <iostream>#include <sstream>#include <fstream>#include <vector>#include <set>#include <map>#include <ctime>using namespace std;//讀取檔案擷取整個資料庫儲存在database中,fileName必須為char*型,要是用string會報錯,in()不認bool ObtainDatabase(vector<set<int> > &database,char *fileName){/*set<int> data;data.insert(1);data.insert(2);data.insert(5);database.push_back(data);data.clear();data.insert(2);data.insert(4);database.push_back(data);data.clear();data.insert(2);data.insert(3);database.push_back(data);data.clear();data.insert(1);data.insert(2);data.insert(4);database.push_back(data);data.clear();data.insert(1);data.insert(3);database.push_back(data);data.clear();data.insert(2);data.insert(3);database.push_back(data);data.clear();data.insert(1);data.insert(3);database.push_back(data);data.clear();data.insert(1);data.insert(2);data.insert(3);data.insert(5);database.push_back(data);data.clear();data.insert(1);data.insert(2);data.insert(3);database.push_back(data);*/ifstream in(fileName);if(!in){cout<<"檔案開啟失敗!"<<endl;return false;}string s="";unsigned int i=0;while(getline(in,s)){//讀取一行記錄i++;set<int> transaction;int len=s.length();string str="";for(int i=0;i<len;i++){//將記錄中的數提取出來if(s[i]!=' '){str+=s[i];}else if(s[i]==' '||i==len-1){//字串轉intstringstream stoi(str);int item=0;stoi>>item;transaction.insert(item);str="";}}database.push_back(transaction);s="";}cout<<i<<endl; //system("pause");return true;}//遍曆一遍資料庫,建立1-項大項集void CreateItemset(vector<set<int> >&database,vector<set<int> > &largeItemset,unsigned int minSupport,map<set<int>,int> &lm1){map<int,int> dir;map<int,int>::iterator dirIt;vector<set<int> >::iterator databaseIt;set<int> temp;set<int>::iterator tempIt;//根據資料庫建立字典,字典形式為<item,count>for(databaseIt=database.begin();databaseIt!=database.end();databaseIt++){temp=*databaseIt;for(tempIt=temp.begin();tempIt!=temp.end();tempIt++){int item=*tempIt;dirIt=dir.find(item);if(dirIt==dir.end()){//item不在字典dir中dir.insert(pair<int,int>(item,1));}else{//item在字典dir中,則將其count值加1(dirIt->second)++;}}}//從字典中選出支援度超過minSopport的itemfor(dirIt=dir.begin();dirIt!=dir.end();dirIt++){if(dirIt->second>=minSupport){set<int> large;large.insert(dirIt->first);largeItemset.push_back(large);lm1.insert(pair<set<int>,int>(large,dirIt->second));}}}//輸出大項集void OutputLargeItemset(vector<set<int> > &largeItemset,unsigned int i){cout<<"包含 "<<largeItemset.size()<<" 項的 "<<i<<"-項大項集:"<<endl;vector<set<int> >::iterator largeItemsetIt;int j=0;for(largeItemsetIt=largeItemset.begin();largeItemsetIt!=largeItemset.end();largeItemsetIt++){set<int> temp=*largeItemsetIt;cout<<"{ ";for(set<int>::iterator tempIt=temp.begin();tempIt!=temp.end();tempIt++){cout<<(*tempIt)<<" ";}cout<<"}";j++;if(j%4==0){cout<<endl;}}cout<<endl<<endl;}//串連步驟,若it1和it2符合串連條件,則把它們串連為temp,返回true,否則返回falsebool Joint(set<int> &recordI,set<int> &recordJ,set<int> &temp){if(recordI.size()!=recordJ.size()){//倆集合大小不一樣,立馬返回!return false;}set<int>::iterator it1=recordI.begin();set<int>::iterator it2=recordJ.begin();unsigned int size=recordI.size()-1;for(int i=0;i<size;i++){if(*it1!=*it2){return false;}temp.insert(*it1);it1++;it2++;}if(*it1==*it2){return false;}temp.insert(*it1);temp.insert(*it2);//cout<<"串連"<<*it1<<" "<<*it2<<endl;return true;}//剪枝步驟,若temp的k-1項集有不在L[k-1]中,則剪掉,返回false,否則返回truebool Prune(set<int> &temp,vector<set<int> > &largeTemp){unsigned int size=temp.size();//擷取temp的全部k-1項子集,並判斷每個子集是否在L[k-1]中for(int i=0;i<size;i++){set<int>::iterator tempIt=temp.begin();set<int> tempMinusOne;//盛放k-1項子集for(int j=0;j<size;j++){if(j!=i){tempMinusOne.insert(*tempIt);}*tempIt++;}//判斷tempMinusOne是否在L[k-1]中vector<set<int> >::iterator largeTempIt;bool flag=false;//temp是否被剪掉的標識for(largeTempIt=largeTemp.begin();largeTempIt!=largeTemp.end();largeTempIt++){//對大項集集合largeTemp中的大項集*largeTempIt逐個與tempMinusOne進行比對,看相不相同,相同就會保證flag=true,否則為falseflag=true;set<int> large=*largeTempIt;set<int>::iterator tempMinusOneIt=tempMinusOne.begin();for(set<int>::iterator largeIt=large.begin();largeIt!=large.end();largeIt++){if(*largeIt!=*tempMinusOneIt){flag=false;break;}tempMinusOneIt++;}if(flag==true){//存在了,不用再和其它大項集比較了,浪費時間return true;}}}return false;}//利用L[k-1],通過串連和剪枝兩個步驟,產生候選集集合candidatevoid AprioriGen(vector<set<int> > &largeTemp,vector<set<int> > &candidate){unsigned int largeTempSize=largeTemp.size();unsigned int sizeTemp=largeTempSize-1;vector<set<int> >::iterator largeTempIt=largeTemp.begin();//L[k-1]中的大項集兩兩串連,求候選集集合for(int i=0;i<sizeTemp;i++,largeTempIt++){//system("pause");cout<<largeTempSize<<" "<<i<<endl;set<int> recordI=*largeTempIt;for(int j=i+1;j<largeTempSize;j++){//cout<<j<<endl;set<int> recordJ=*(largeTempIt+(j-i));set<int> temp;//cout<<"進行串連"<<endl;if(Joint(recordI,recordJ,temp)){//recordI和recordJ能串連成temp,則對temp進行剪枝//cout<<"串連成功,進行剪枝"<<endl; if(Prune(temp,largeTemp)){//temp沒有被剪掉,則把它加到候選集的集合中if(!temp.empty())//cout<<"temp不為空白,沒有被剪掉,成為到候選集"<<endl;candidate.push_back(temp);}//else{cout<<"被剪掉了"<<endl;} }//else{cout<<"不符合串連條件"<<endl; } }//system("pause");}}//對比資料庫中的每條交易,計算每個候選集的支援度,選出大於等於最小支援度的候選集來構成L[k]void Subset(vector<set<int> > &database,vector<set<int> > &candidate,vector<set<int> > &largeK,unsigned int minSupport,map<set<int>,int> &lm){vector<set<int> >::iterator databaseIt;vector<set<int> >::iterator candidateIt;for(candidateIt=candidate.begin();candidateIt!=candidate.end();candidateIt++){//對於每個候選集can//bool cunzai=true;set<int> can=*candidateIt;//cout<<"cannnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"<<endl;unsigned int canCount=0;for(databaseIt=database.begin();databaseIt!=database.end();databaseIt++){//對於資料庫中每條交易,查看can是否在其中set<int> data=*databaseIt;if(can.size()>data.size()){continue;//候選集大小大於交易大小,肯定不在這個交易中}set<int>::iterator canIt;for(canIt=can.begin();canIt!=can.end();canIt++){//對於can中每個項,看它是否在交易data中if(data.find(*canIt)==data.end()){break;}}if(canIt==can.end()){//cout<<"在"<<endl;//system("pause");canCount++;                                //cout<<canCount<<endl;}}if(canCount>=minSupport){//canCount只要大於等於最小支援度,我們就退出迴圈,不再對該候選集進行計數了,浪費時間largeK.push_back(can);lm.insert(pair<set<int>,int>(can,canCount));}}}int main(int argc,char *argv[]){char name[200];string file="";char *fileName="retail.dat";int minSupport=5000;//最小支援度/*string ctl="";cout<<"手動輸入檔案路徑和最小支援度(Y/N)?";cin>>ctl;if(ctl=="Y"||ctl=="y"){cout<<"請依次輸入檔案路徑和最小支援度,用空格隔開。(檔案路徑要用雙斜杠):\n";cin>>file>>minSupport;strcpy(name,file.c_str());fileName=name;}*/vector<map<set<int>,int> > liss;    clock_t start=clock();vector<set<int> > database;//資料庫ObtainDatabase(database,fileName);vector<set<int> > large1;map<set<int>,int> lm1;CreateItemset(database,large1,minSupport,lm1);liss.push_back(lm1);int k=1;vector<set<int> > largeTemp=large1;while(!largeTemp.empty()){OutputLargeItemset(largeTemp,k);k++;vector<set<int> > candidate;AprioriGen(largeTemp,candidate);vector<set<int> > largeK;map<set<int>,int> lm;Subset(database,candidate,largeK,minSupport,lm);largeTemp=largeK;if(largeTemp.empty()){cout<<"L["<<k<<"]為空白"<<endl;} else{liss.push_back(lm);}}clock_t end=clock();cout<<"Finish!共用時:"<<(end-start)<<"ms"<<endl;system("pause");}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.