1. 程式人生 > >關聯規則淺談以及Apriori演算法matlab實現

關聯規則淺談以及Apriori演算法matlab實現

關聯規則分析也叫做購物籃分析,最早是為發現超市銷售資料庫中不同商品之間的關聯關係。例如一個超市的經理想要更多的瞭解顧客的購物習慣,比如“哪組商品可能會在一次購物中同時被購買?”或者“某顧客購買了個人電腦,那該顧客三個月後購買數碼相機的概率有多大?”他可能會發現如果購買了麵包的顧客同時非常有可能會購買牛奶,這就匯出了一條關聯規則“麵包->牛奶”,其中麵包稱為規則的前項,而牛奶則稱為規則的後項。通過對面包降低售價進行促銷,而適當提高牛奶的售價,關聯銷售出的牛奶就有可能增加超市整體的利潤。

關聯規則分析是資料探勘中最活躍的研究方法之一,目的是在一個數據集中找出各項之間的關聯關係,而這種關係並沒有在資料中直接表示出來。

1、常用的關聯規則演算法
這裡寫圖片描述

以下重點介紹Apriori演算法。

2、Apriori演算法
以超市銷售資料為例,提取關聯規則的最大困難在於當存在很多商品時,可能的商品的組合(規則的前項和後項)的數目會達到一種令人望而卻步的程度。因而各種關聯規則分析的演算法從不同方面入手減小可能的搜尋空間的大小,以及減小掃描資料的次數。Apriori演算法是最經典的挖掘頻繁項集的演算法,第一次實現了在大資料集上可行的關聯規則提取,其核心思想是通過連線產生候選項與其支援度,然後通過剪枝生成頻繁項集。

3、關聯規則和頻繁項集
1)關聯規則的一般形式
項集A、B同時發生的概率稱為關聯規則的支援度(也稱相對支援度):

這裡寫圖片描述

項集A發生,則項集B發生的概率為關聯規則的置信度:

這裡寫圖片描述

2)最小支援度和最小置信度
最小支援度是使用者或專家定義的衡量支援度的一個閾值,表示專案集在統計意義上的最低重要性;最小置信度是使用者或專家定義的衡量置信度的一個閾值,表示關聯規則的最低可靠性,同時滿足最小支援度閾值和最小置信度閾值的規則稱作強規則。

3)項集
項集是項的集合。包含k個項的項集稱為k項集,如集合{牛奶,麥片,糖}是一個3項集。

項集的出現頻率是所有包含項集的事務計數,又稱做絕對支援度或支援度計數。如果項集I的相對支援度滿足預定義的最小支援度閾值,則I是頻繁項集。頻繁k項集通常記作這裡寫圖片描述

4)支援度計數
項集A的支援度計數是事務資料集中包含A的事務個數,簡稱為項集的頻率或計數。

已知項集的支援度計數,則規則這裡寫圖片描述的支援度和置信度很容易從所有事務計數、項集A和項集這裡寫圖片描述的支援度計數推出:

這裡寫圖片描述
這裡寫圖片描述

也就是說,一旦得到所有事務的個數,A、B和這裡寫圖片描述的支援度計數,就可以匯出對應的關聯規則這裡寫圖片描述這裡寫圖片描述,並可以檢查該規則是否是強規則。

4、Apriori演算法——使用候選產生頻繁項集
Apriori演算法的主要思想是找出存在於事務資料集中最大的頻繁項集,利用得到的最大頻繁項集與預先設定的最小置信度閾值生成強關聯規則。

1)Apriori的性質
頻繁項集的所有非空子集也必須是頻繁項集。根據該性質可以得出:向不是頻繁項集I的項集中新增事務A,新的項集這裡寫圖片描述一定也不是頻繁項集。

2)Apriori演算法實現的兩個過程
a)找出所有的頻繁項集(支援度必須大於等於給定的最小支援度閾值),在這個過程中連線步和剪枝步互相融合,最終得到最大的頻繁項集這裡寫圖片描述

連線步:連線步的目的是找到K項集。對給定的最小支援度閾值,分別對1項候選集這裡寫圖片描述,剔除小於該閾值的項集得到1項頻繁項集這裡寫圖片描述;下一步由這裡寫圖片描述自身連線產生兩項候選集這裡寫圖片描述,保留這裡寫圖片描述中滿足約束條件的項集得到兩項頻繁集,記為這裡寫圖片描述;再下一步由這裡寫圖片描述這裡寫圖片描述連線產生三項候選集這裡寫圖片描述,保留這裡寫圖片描述中滿足約束條件的項集得到三項頻繁集,記為這裡寫圖片描述,等等。這樣迴圈下去,得到最大頻繁項集這裡寫圖片描述

剪枝步:剪枝步緊接著連線步,在產生候選項這裡寫圖片描述的過程中啟到減小搜尋空間的目的。由於這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述連線產生的,根據Apriori的性質頻繁項集的所有非空子集也必須是頻繁項集,所以不滿足該性質的項集將不會存在於這裡寫圖片描述中,該過程就是剪枝。

b)由頻繁項集產生強關聯規則:在過程a)可知未超過預定的最小支援度閾值的項集已被剔除,如果剩下這些規則又滿足了預定的最小置信度閾值,那麼就挖掘出了強關聯規則。

下面根據例項來講解Apriori關聯規則演算法挖掘的實現過程。

資料如下所示

a,c,e
b,d
b,c
a,b,c,d
a,b
b,c
a,b
a,b,c,e
a,b,c
a,c,e

以上有10個事務資料集,設支援度為0.2(支援度計數為2),則Apriori演算法的實現過程如下。

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

過程一:找最大k項頻繁集

a)Apriori演算法簡單地掃描所有的事務,事務中的每一項都是候選1項集的集合這裡寫圖片描述的成員,計算每一項的支援度。比如這裡寫圖片描述

b)對這裡寫圖片描述中各項集的支援度與預先設定的最小支援度閾值作比較,保留大於或等於該閾值的項,得一項頻繁集這裡寫圖片描述

c)掃描所有事務,這裡寫圖片描述這裡寫圖片描述連線得候選2項集這裡寫圖片描述,並計算每一項的支援度。如
這裡寫圖片描述
接下來是剪枝步,由於這裡寫圖片描述的每個子集(即這裡寫圖片描述)都是頻繁集,所以沒有項集從這裡寫圖片描述中被剔除;

d)對這裡寫圖片描述中各項集的支援度與預先設定的最小支援度閾值作比較,保留大於或等於該閾值的項,得兩項頻繁集這裡寫圖片描述

e)掃描所有事務,這裡寫圖片描述這裡寫圖片描述連線得候選3項集這裡寫圖片描述,並計算每一項的支援度,如
這裡寫圖片描述
接下來是剪枝步,這裡寫圖片描述這裡寫圖片描述連線的所有項集為:這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述,根據Apriori演算法,頻繁集的所有非空子集也必須是頻繁集,因為這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述不包含在b項頻繁集這裡寫圖片描述中,即不是頻繁集,應剔除,最後的這裡寫圖片描述中的項集只有這裡寫圖片描述這裡寫圖片描述

f)對這裡寫圖片描述中各項集的支援度與預先設定的最小支援度閾值作比較,保留大於或等於該閾值的項,得三項頻繁集這裡寫圖片描述

g)這裡寫圖片描述這裡寫圖片描述連線得候選四項集這裡寫圖片描述,易得剪枝後為空集。最後得到最大三項頻繁集這裡寫圖片描述這裡寫圖片描述

由以上過程可知這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述都是頻繁項集,這裡寫圖片描述是最大頻繁項集。

過程二:由頻繁集產生關聯規則。

置信度的計算公式為:

這裡寫圖片描述

其中這裡寫圖片描述是包含項集這裡寫圖片描述的事務數;這裡寫圖片描述是包含項集A的事務數;根據該公式,可以計算關聯規則的置信度。

生成的24條關聯規則的支援度和置信度如下所示。

這裡寫圖片描述

在這裡我們把最小置信度設為50%,則關聯規則變為16條,如圖所示。

這裡寫圖片描述

在這裡舉例說明置信度的計算,如

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

Matlab程式碼如下

首先建立資料來源
menu_orders.txt

a,c,e
b,d
b,c
a,b,c,d
a,b
b,c
a,b
a,b,c,e
a,b,c
a,c,e

然後是具體的程式
cal_apriori.m

%% 使用Apriori演算法挖掘關聯規則
clear;
% 引數初始化
inputfile = 'menu_orders.txt'; % 銷量及其他屬性資料
outputfile='as.txt';% 輸出轉換後0,1矩陣檔案
minSup = 0.2; % 最小支援度
minConf = 0.5;% 最小置信度
nRules = 1000;% 輸出最大規則數
sortFlag = 1;% 按照支援度排序
rulefile = 'rules.txt'; % 規則輸出檔案

%% 呼叫轉換程式 ,把資料轉換為0,1矩陣,自定義函式
[transactions,code] = trans2matrix(inputfile,outputfile,','); 

%% 呼叫Apriori關聯規則演算法,自定義函式
[Rules,FreqItemsets] = findRules(transactions, minSup, minConf, nRules, sortFlag, code, rulefile);

disp('Apriori演算法挖掘菜品訂單關聯規則完成!');

trans2matrix.m

function [ output,code] = trans2matrix( inputfile,outputfile,splitter )
%% 把輸入事務轉換為0、1矩陣;每行代表一個事務

% 輸入引數:
% inputfile:輸入檔案,空格分隔每個專案;
% outputfile:輸出檔案,轉換後的0,1矩陣檔案;
% splitter: 輸入檔案專案的間隔符,預設為空格

% 輸出引數:
% output : 轉換後的0,1 矩陣
% code:編碼規則;

if nargin<3
   splitter=' '; 
end

%% 讀入檔案, 獲得編碼規則
code={};
fid= fopen(inputfile);
tline = fgetl(fid);
lines=0;
while ischar(tline)
    lines=lines+1; % 記錄行數
    tline = deblank(tline);
    tline = regexp(tline,splitter,'split');
    code=[code tline]; % 合併 
    code = unique(code); % 去除重複記錄
%     disp(code)
    tline = fgetl(fid);
end
disp('編碼規則為:')
disp(num2str(1:size(code,2)))
disp( code);
fclose(fid); % 關閉文件

%% 讀取檔案,根據編碼規則對原始資料進行轉換
itemsnum= size(code,2);
output=zeros(lines,itemsnum);
fid= fopen(inputfile);
tline = fgetl(fid);
lines=0;
while ischar(tline)
    lines=lines+1; % 記錄行數
    tline = deblank(tline);
    tline = regexp(tline,splitter,'split');
    [~,icode,~] = intersect(code,tline);% 尋找下標
    output(lines,icode')=1;
    %disp(output(lines,:))
    tline = fgetl(fid);
end
fclose(fid);

%% 把轉換後的矩陣寫入檔案
fid = fopen(outputfile, 'w');
for i=1:lines
   fprintf(fid,'%s\n',num2str(output(i,:))); 
end
fclose(fid);
end

findRules.m

function [Rules,FreqItemsets] = findRules(transactions, minSup, minConf, nRules, sortFlag, code, rulesfile)
%
% This function performs Association Analysis (Apriori Algorithm):  Given a set of transactions,
% find rules that will predict  the occurrence of an item based on the occurrences of other
% items in the transaction
% 
% Rules are of the form  A-> B (e.g., {milk, diaper} - > {Coke}), where
% support = minSup (minimum support threshold)
% confidence = minConf (minimum confidence threshold)
% 
% Support is the fraction of transactions that contain both A and B:
% Support(A,B) = P(A,B)
% 
% Confidence is the fraction of transactions where items in B appear in transactions  that contain A:
% Confidence(A,B) = P(B|A)
%
%
% INPUT:
%          transactions:  M x N matrix of binary transactions, where each row
%                                  represents one transaction and each column represents
%                                  one attribute/item
%          minSup:          scalar value that represents the minimum
%                                  threshold for support for each rule
%          minConf:        scalar value that represents the minimum
%                                  threshold for confidence of each rule
%          nRules:           scalar value indicating the number of rules
%                                  the user wants to find
%          sortFlag:         binary value indicating if the rules should be
%                                  sorted by support level or confidence level
%                                  1: sort by rule support level
%                                  2: sort by rule confidence level
%          code (labels): 編碼規則            optional parameter that provides labels for
%                                  each attribute (columns of transactions),
%                                  by default attributes are represented
%                                  with increasing numerical values 1:N
%           
%          fname:            optional file name where rules are saved
%
% OUTPUT:
%          Rules:             2 x 1 cell array, where the first cell (Rules{1}{:})
%                                 contains the itemsets in the left side of the rule and second
%                                 cell (Rules{2}{:}) contains the itemsets
%                                 in the right side of the rule (e.g., if
%                                 the first rule is {1, 2} -> 3,
%                                 Rules{1}{1} = [1,2], Rules{2}{1} = [3])
%         FreqItemsets: A cell array of frequent itemsets of size 1, 2,
%                                 etc., with itemset support >= minSup,
%                                 where FreqItemSets{1} represents itemsets
%                                 of size 1, FreqItemSets{2} itemsets of
%                                 size 2, etc.
%         fname.txt:      The code creates a text file and stores all the
%                                 rules in the form left_side -> right_side.
%
% author: Narine Manukyan 07/08/2013

% Number of transactions in the dataset
M = size(transactions,1);
% Number of attributes in the dataset
N = size(transactions,2);

if nargin < 7
    fname = 'default';
end

if nargin < 6
    labels = cellfun(@(x){num2str(x)}, num2cell(1:N));
end

if nargin < 5
    sortFlag = 1;
end

if nargin < 4
    nRules = 100;
end

if nargin < 3
    minConf = 0.5;
end

if nargin < 2
    minSup = 0.5;
end

if nargin == 0
    error('No input arguments were supplied.  At least one is expected.');
end

% Preallocate memory for Rules and FreqItemsets
maxSize = 10^2;
Rules = cell(2,1);
Rules{1} = cell(nRules,1);
Rules{2} = cell(nRules,1);
FreqItemsets = cell(maxSize);
RuleConf = zeros(nRules,1);
RuleSup = zeros(nRules,1);
ct = 1;

% Find frequent item sets of size one (list of all items with minSup)
T = [];
for i = 1:N
    S = sum(transactions(:,i))/M;
    if S >= minSup
        T = [T; i];
    end
end
FreqItemsets{1} = T;

%Find frequent item sets of size >=2 and from those identify rules with minConf

for steps = 2:N

    % If there aren't at least two items  with minSup terminate
    U = unique(T);
    if isempty(U) || size(U,1) == 1
        Rules{1}(ct:end) = [];
        Rules{2}(ct:end) = [];
        FreqItemsets(steps-1:end) = [];
        break
    end

    % Generate all combinations of items that are in frequent itemset
    Combinations = nchoosek(U',steps);
    TOld = T;
    T = [];

    for j = 1:size(Combinations,1)
        if ct > nRules
            break;
        else
            % Apriori rule: if any subset of items are not in frequent itemset do not
            % consider the superset (e.g., if {A, B} does not have minSup do not consider {A,B,*})
            if sum(ismember(nchoosek(Combinations(j,:),steps-1),TOld,'rows')) - steps+1>0

                % Calculate the support for the new itemset
                S = mean((sum(transactions(:,Combinations(j,:)),2)-steps)>=0);
                if S >= minSup
                    T = [T; Combinations(j,:)];

                    % Generate potential rules and check for minConf
                    for depth = 1:steps-1
                        R = nchoosek(Combinations(j,:),depth);
                        for r = 1:size(R,1)
                            if ct > nRules
                                break;
                            else
                                % Calculate the confidence of the rule
                                Ctemp = S/mean((sum(transactions(:,R(r,:)),2)-depth)==0);
                                if Ctemp > minConf

                                    % Store the rules that have minSup and minConf
                                    Rules{1}{ct} = R(r,:);
                                    Rules{2}{ct} = setdiff(Combinations(j,:),R(r,:));
                                    RuleConf(ct) = Ctemp;
                                    RuleSup(ct) = S;
                                    ct = ct+1;
                                end
                            end
                        end
                    end
                end
            end
        end
    end

    % Store the freqent itemsets
    FreqItemsets{steps} = T;
end

% Get rid of unnecessary rows due to preallocation (helps with speed)
FreqItemsets(steps-1:end) = [];
RuleConf = RuleConf(1:ct-1);
RuleSup = RuleSup(1:ct-1);

% Sort the rules in descending order based on the confidence or support level
switch sortFlag
    case 1 % Sort by Support level
        [V ind] = sort(RuleSup,'descend');
    case 2 % Sort by Confidence level
        [V ind] = sort(RuleConf,'descend');
end

RuleConf = RuleConf(ind);
RuleSup = RuleSup(ind);

for i = 1:2
    temp = Rules{i,1};
    temp = temp(ind);
    Rules{i,1} = temp;
end

disp(['關聯規則演算法完成,規則數為:' num2str(size(RuleSup,1))]);

% Save the rule in a text file and print them on display
fid = fopen(rulesfile, 'w');
fprintf(fid, '%s   (%s, %s) \n', 'Rule', 'Support', 'Confidence');

for i = 1:size(Rules{1},1)
    s1 = '';
    s2 = '';
    for j = 1:size(Rules{1}{i},2)
        if j == size(Rules{1}{i},2)
            s1 = [s1 code{Rules{1}{i}(j)}];
        else
            s1 = [s1 code{Rules{1}{i}(j)} ','];
        end
    end
    for k = 1:size(Rules{2}{i},2)
        if k == size(Rules{2}{i},2)
            s2 = [s2 code{Rules{2}{i}(k)}];
        else
            s2 = [s2 code{Rules{2}{i}(k)} ','];
        end
    end
    s3 = num2str(RuleSup(i)*100);
    s4 = num2str(RuleConf(i)*100);
    fprintf(fid, '%s -> %s  (%s%%, %s%%)\n', s1, s2, s3, s4);
end
fclose(fid);
disp(['儲存規則到檔案‘' rulesfile '’完成'])
end

執行完程式後,會生成rules.txt和as.txt。
我們主要關心rules.txt,裡面的內容就是關聯規則、支援度和置信度,如下所示。

這裡寫圖片描述