關聯規則association rule mining是眾多“規則類”資料採礦方法中的一種,對於關聯規則的基本理論(假定讀者已經瞭解)不在這裡詳細敘述,下面主要就演算法的設計進行描述。
Apriori演算法的主要思想: 1、根據Apriori性質“頻繁項集的子集一定是頻繁項集,非頻繁項集的超集一定是非頻繁項集”構造候選項集,然後通過遍曆交易資料庫來計算候選項集的支援度,得到頻繁項集; 2、由頻繁項集產生關聯規則。 我認為,關聯規則在理論上是比較簡單的,相信很多人都會有這種感覺,但要真正做演算法的設計與實現,反而是相當有難度的。問題的關鍵是:無法設計出頻繁項集(一種適合1-項集、2-項集...n-項集的通用的資料結構)、規則的合理的資料結構。沒有這兩個資料結構,要實現關聯規則就是“紙上談兵”、或許是“霧裡看花”也說不準。 規則的資料結構比較好設計,一條規則無非就是包含這麼幾個成員(規則的條件、結論,支援度,可信度,提升度),因此一條規則可以用一個結構體(rule)表示:typedef struct{ char condition[80]; char conclusion[80]; double sup; double conf; double lift;}rule; 所有的規則,可以看作是這個結構體的列表(list<rule> lst_rule)或可變數組(vector<rule> vt_rule)。/* anything,send me email datamining@163.com my QQ 275869936It comes from http://blog.sina.com.cn/dataminer321 */ 項集的資料結構就比較複雜了。先對項集的結構和用處描述一下,讓我們對它有一個整體瞭解。 項集和每個事務的項的集合是類似的,都是幾個項的集合{a,b,c,d,e,g...},元素(項)的個數為1...n(n-項集的情況)。 項集的用處: 1、由兩個頻繁n項集串連為一個侯選n+1項集 2、在計算候選項集的支援度的時候,判斷某個候選項集是否在當前的事務中(輔助函數2)。 這就要求項集的資料結構必須能夠容納n個,同時也能容納n+1個項,即項集的資料結構必須適應項個數的變化. 在這裡,我給出項集的一種資料結構包含兩部分:一、儲存項的集合的字串(同時也適合事務);二、支持度計數。 可以採用map<string,int> 儲存,第一個參數為字串,即STL中的string,項集(或事務)以字串形式儲存,其中項與項之間以符號"|"間隔,如由項a,b,c構成的項集,表示為string m_Itemset="a|b|c" 格式。使用的時候,由輔助函數1,可根據"|"對字串m_Itemset進行拆分,將每一個項儲存到 vector<string> vt_itemset中,vector中的每個元素為一個項。 第二個參數為支持度計數。 下面我們來討論一下第二步,即由頻繁項集建置規則,這一步的程式實現在論文中很少提及,大家都主要討論第一步,即產生頻繁項集,可能是因為改進第一步對於提高apriori效能是至關重要的。 一個n-項集可以產生2的n次方減2條規則(每一條規則的條件和結論的項的集合是整個項集中的項,即n個項)【方法1】,在這裡不要考慮多了,如每一個n-項集包含n個n-1項集,每一個n-1項集也可以產生2的n-1次方減2條規則。原因是我們的頻繁項集中包含頻繁1-項集、頻繁2-項集...直到頻繁n-項集(而不是只儲存最大長度頻繁項集),只要我們按照【方法1】對每一個頻繁項集都產生其對應的規則,就得到了所有的規則。 輔助函數1:/*函數調用舉例:m_strSource="a|b|c";//輸入參數substr="|"; //輸入參數vector<string> vItem;GetItemsFromString(m_strSource,vItem,substr);vItem[0]="a"; //輸出參數vItem[1]="b";vItem[2]="c";*/void GetItemsFromString(string &m_strSource,vector<string> &vItem,string substr)
{
vItem.clear();
int j;
int i=m_strSource.find(substr,0);
if (i==-1)
{
//m_strSource is a Item
vItem.push_back(m_strSource);
}
else
{
string m_strTemp=m_strSource.substr(0,i);
vItem.push_back(m_strTemp);
while(i!=-1)
{
j=m_strSource.find(substr,i+1);
if(j==-1)
{
m_strTemp=m_strSource.substr(i+1,m_strSource.size()-i-1);
vItem.push_back(m_strTemp);
}
else
{
m_strTemp=m_strSource.substr(i+1,j-i-1);
vItem.push_back(m_strTemp);
}
i=j;
} //end of while
}//end of else
}
輔助函數2:判斷候選項集v1是否在事務v2中
bool IsIn(const vector<string> &v1,const vector<string> &v2)
{
int nSize1=v1.size();
int nSize2=v2.size();
for(int i=0;i<nSize1;i++) //for1
{
bool m_bFlag1=false;
for(int j=0;j<nSize2;j++) //for2
{
if(v1[i]==v2[j])
{
m_bFlag1=true;
break;
}
}// end of for2
if (!m_bFlag1)
return false;
}// end of for1
return true;
}
有了這兩個資料結構和輔助函數,相信你能夠設計出你的關聯規則挖掘演算法。