Thuật toán do Agrawal đề nghị năm 1994, được Cheung đánh giá mang tính chất lịch sử trong lĩnh vực KPLKH, vì đã vượt xa tầm của các thuật toán quen thuộc trong lĩnh vực này. Thuật toán dựa trên một nhận xét khá đơn giản là bất kỳ tập hợp con nào của tập xuất hiện – thường xuyên cũng là tập xuất hiện – thường xuyên. Do đó, trong quá trình đi tìm các tập ứng cử viên, nó chỉ cần dùng đến các tập ứng cử viên vừa xuất hiện ở bước ngay trước đó, chứ không cần dùng đến tất cả các tập ứng cử viên (cho đến thời điểm đó). Nhờ vậy, bộ nhớ được giải phóng đáng kể.
1/ Bước 1: cho trước ngưỡng độ hỗ trợ 0 1. Tìm tất cả các mặt hàng xuất hiện – thường xuyên. Để ý rằng, một siêu thị có thể có tới 100.000 mặt hàng. Tập hợp tìm được ký hiệu là L1.
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 38 2/ Bước 2: Ta tiến hành ghép đôi các phần tử của L1 (không cần để ý đến thứ tự), được tập C2, tạp gọi là tập các ứng cử viên có 2 phần tử. Sở dĩ chỉ gọi là “ứng cử viên”, vì chưa chắc chúng đã là – thường xuyên. Sau khi kiểm tra (dùng định nghĩa), ta lọc ra được các tập hợp – thường xuyên có 2 phần tử. Ký hiệu tập hợp này là L2.
3/ Bước 3: Với chứ ý đã nêu (về tính chất tăng dần của các tập hợp – thường xuyên ), ta tiến hành tìm các ứng cử viên có 3 phần tử (lấy từ L1). Gọi nó là tập C3. Lưu ý là nếu {A, B, C} muốn là “ứng cử viên” thì các tập 2 phần tử {A, B},{B,C},{C, A } đều phải là – thường xuyên, tức là chúng đều là phần tử của tập L2. Ta đi “kiểm tra tư cách đại biểu” trong tập C3 và lọc ra được tập các tập hợp – thường xuyên có 3 phần tử. Tập hợp này được ký hiệu là L3.
4/ Bước 4: Ta tiến hành tìm các ứng cử viên có n phần tử. Gọi tập của chúng là tập Cn và từ đây, lọc ra Ln là tập tập các tập hợp – thường xuyên có n phẩn tử.
Thuật toán này có giúp ích được gì, ta cùng nhau xem xét ví dụ sau:
Câu lệnh SQL sau đây tạo cặp, xử lý 10 triệu giỏ mua hàng, mỗi giỏ mua hàng trung bình có 10 mặt hàng, với giả thiết siêu thị có khoảng 100.000 mặt hàng:
SELECT b1.item b2.item COUNT(*) FROM Baskets b1, Baskets b2
WHERE b1.BID = b2.BID AND b1.item <b2. item GROUP BY b1.item , b2. item
HAVING COUNT(*) >= s;
Câu lệnh WHERE đảm bảo các cặp ghép không bị đúp 2 lần (vì ta không cần để ý đến tứ tự các phần tử).
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 39
Nhận xét: Khi ghép Baskets với chính nó, mỗi giỏ ta có 45 cách chế ra các cặp ứng viên [do (10*9)/2=45], và do có 10 triệu giỏ mua hàng, nên ta phải xét 45x107trường hợp để lọc ra các cặp – thường xuyên.
Trong khi đó nếu sử dụng Thuật toán Apriori, trước hết ta giảm được đáng kể kích thước của Baskets, vì ở bước 1 ta đi tìm các phần tử (mặt hàng) xuất hiện – thường xuyên.
SELECT * FROM Baskets GROUP BY item
HAVING COUNT (*) >= s;
Sự giảm kích thước của Baskets chưa phải là điểm cốt yếu. Điểm cốt yếu là khi ta kết hợp để tìm cặp, ta sẽ giảm được bình phương lần.
Cốt lõi của thuật toán Apriori là hàm apriori_gen() do Agrawal đề nghị năm 1994. Hàm này hoạt động theo 2 bước, bước 1- tập hợp Lk-1 tự kết nối (join) với chính nó để tạo ra tập ứng cử viên Ck. Sau đó hàm apriori_gen()
loại bỏ các tập hợp có một hợp con (k-1) phần tử không nằm trong Lk-1 (vì chúng không thể là tập hợp xuất hiện – thường xuyên, theo như nhận xét ban đầu).
Method: apriori_gen() [Agrwal1994]
Input: Lớp các tập hợp xuất hiện – thường xuyên có (k-1) phần tử, ký hiệu là Lk-1
Output: Lớp các tập hợp xuất hiện – thường xuyên có k phần tử, ký hiệu là Luật kết hợp
// Bước tự kết nối Ii = Items i
Insert into Ck
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 40 From Lk-1 is p, Lk-1 is q
Where p.I1 = q.I1 and….and p.Ik-2 = q.Ik-2 and p.Ik-1 < q.Ik-1
//Bước tỉa bớt
Forall itemsets c Ck do
Forall (k-1)- subsets s of c do If (s is not of Lk-1) then
Delete c from Ck
Hàm sau đây có nhiệm vụ rà soát từng tính chất và đo đếm xem giá đỡ của nó bằng bao nhiêu. Nói cách khác, ở bước đầu tiên Agrawal dùng hàm
count() để tìm ra các tập hợp xuất hiện – thường xuyên có 1 phần tử. Function count(C:a set of itemsets, D: database)
begin
for each transaction T D = Di do begin
forall subsets x T do if x C then x.count++; end
end
Dưới đây là toàn bộ Thuật toán Apriori
Thuật toán 3- Apriori [Agrawal1994]
Input: I, D,
Output: L
Algorithm:
//Apriori Algorithm prposed by Agrawal R., Srikant, R. [Agrawal1994] //procedure LargeItemsets
1) C1: = I; // Tập ứng cử viên có 1 phần tử
2) Sinh ra L1 bằng cách tính tần số xuất hiện của mặt hàng trong các giao dịch;
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 41 3) for (k=2; Lk-1 ; k++) do begin
//Tạo ra các tập ứng cử viên
// Các tập ứng cử viên có k phần tử được sinh ra từ các tập (k-1)- phần tử xuất hiện – thường xuyên.
4) Ck = apriori-gen( Lk-1 ); // Tính độ hỗ trợ cho Ck 5) Count (Ck, D) 6) Lk = {c Ck| c.count } 7) end 8) L:= k Lk
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 42 C1 C1 L1 Tập 1 phần tử {Bánh mì} {Bơ} {Trứng} {Sữa} Quét toàn bộ CSDL để tính độ hỗ trợ Tập hợp {Bánh mì} {Bơ} {Trứng} {Sữa} Độ hỗ trợ 50% 100% 50% 25% Tập hợp {Bánh mì} {Bơ} {Trứng} Độ tin cậy 50% 100% 50% C2 C2 L2 Tập 2 phần tử {Bánh mì, Bơ} {Bánh mì, Trứng} {Bơ, Trứng} Tập hợp {Bánh mì, Bơ} {Bánh mì, Trứng} {Bơ, Trứng} Độ hỗ trợ 50% 25% 50% Tập hợp {Bánh mì, Bơ} {Bơ, Trứng} Độ tin cậy 50% 50% C3 Quét toàn bộ CSDL để tính độ hỗ trợ C3 L3 Tập 3 phần tử Tập hợp Độ hỗ trợ Tập hợp Độ tin cậy Bảng 3.1.
Dùng thuật toán Apriori tính ra các tập hợp xuất hiện – thường xuyên
Bản thân Agrawal đưa ra nhận xét: thuật toán Apriori hiệu quả hơn so với AIS và SETM. Trong một ví dụ minh họa, ở bước thứ tư, thuật toán Apriori lược bỏ hết, chỉ còn giữ lại một tập ứng cử viên duy nhất, trong khi cả hai thuật toán kia vẫn đề nghị tới 5 ứng cử viên. Do đó, để đạt được kết quả như Apriori, hai thuật toán kia chắc chắn phải cần đến những tính toán bổ trợ.
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 43 Thuật toán Apriori cải tiến cũng giải quyết 2 tình huống “xấu”, đó là khi Ck hoặc Lk-1 to quá, không chứa đủ trong bộ nhớ tính toán. Khi đó, cần tu chỉnh lại hàm apriori_gen() một chút.
*Thuật toán Apriori nhị phân:
Thuật toán Apriori nhị phân sử dụng các vector bit cho các thuộc tính, vector nhị phân n chiều ứng với n giao tác trong cơ sở dữ liệu. Có thể biểu diễn cơ sở dữ liệu bằng một ma trận nhị phân trong đó dòng thứ I tương ứng với giao tác (bản ghi) ti và cột thứ j tương ứng với mục (thuộc tính ) ij. Ma trận biểu diễn cơ sở dữ liệu ví dụ cho bảng dưới:
TID A B C D E 1 1 1 0 1 1 2 0 1 1 0 1 3 1 1 0 1 1 4 1 1 1 0 1 5 1 1 1 1 1 6 0 1 1 1 0
Bảng 3.2. Ma trận biểu diễn cơ sở dữ liệu
Các vector biểu diễn nhị phân cho các tập 1 thuộc tính có dạng sau: {A} Vector {B} Vector {C} Vector {D} Vector {E} Vector
1 1 0 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 44 Các vector biểu diễn nhị phân cho các tập 2 thuộc tính có dạng sau:
{A,B} {A,C} {A,D} {A,E} {B,C} {B,D} {B,E} {C,D} {C,E} {D,E} 1 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 1 0 0
Bảng 3.4. Vector biểu diễn nhị phân cho các tập 2 thuộc tính
Các vector biểu diễn cho thấy {A,C}, {C,D} có độ hỗ trợ 33% nhỏ hơn độ hỗ trợ tối thiểu MinSupp=50% (cho trước) nên bị loại.
Các vector biểu diễn nhị phân cho các tập 3 thuộc tính có dạng: {A,B,D} {A,B,E} {B,C, E} {B,D,E}
1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 0 1 1 1 1 0 0 0 0
Bảng 3.5. Vector biểu diễn nhị phân cho các tập 3 thuộc tính
Các vector biểu diễn nhị phân cho các tập 4 thuộc tính có dạng: {A,B,C,D} {A,B,C,E} {A,C,D,E} {B,C,D,E}
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn 45