The Apriori Algorithm
Chapter Seventy-Seven
Syllabus topic Module 2, "Association rule mining (Apriori concept)"
Pages 485 to 494 of 591
In one line
Find the frequent itemsets one size at a time, using the fact that a set cannot be frequent unless every one of its subsets is.
Support, Confidence and Lift gave the measures and said that support must be checked first. This chapter is the algorithm that does it, published by Agrawal and Srikant in 1994 and still the standard treatment of the problem.
The problem
With m items there are 2m - 1 non-empty itemsets. Seven items give 127, which can be counted directly. A shop with ten thousand items gives 210000, which cannot be written down, let alone counted.
And the database is usually too large to hold in memory, so the number of passes over the data matters as much as the number of itemsets.
The one property that makes it possible
Downward closure, also called the Apriori property or anti-monotonicity:
if an itemset is frequent, EVERY subset of it is frequent
equivalently: if ANY subset is infrequent, the set cannot be frequent
The proof is one line, and papers ask for it: every basket containing the whole set contains each of its subsets, so a subset's count is at least the set's count, and its support is at least the set's support.
The second form is the useful one, because it lets a candidate be rejected without being counted. That is the entire saving.
The algorithm
Two steps per level, repeated until nothing survives.
- Level 1: count every single item; keep those with support at least
minsup. Call the survivorsL1. - For
k = 2, 3, ...
- Join: form candidates of size
kby joining pairs ofL(k-1)sets that agree on their firstk - 2items. - Prune: discard any candidate that has an infrequent subset of size
k - 1. No counting here. - Count the survivors in one pass over the database and keep those with support at least
minsup. These areLk.
- Stop when
Lkis empty. The frequent itemsets are the union of all theLk. - Generate rules from each frequent itemset of two or more items, and keep those whose confidence reaches
minconf.
Note the structure: support is used to search, confidence only afterwards. The search is by support because support has downward closure and confidence does not.
The run
# Apriori, run in full on the same 20 baskets: every candidate set, every count,
# the pruning step doing its work, the rules generated afterwards, and the cost
# against counting every possible itemset.
from itertools import combinations
BASKETS = [
("notebook", "pen", "tea"),
("notebook", "pen", "tea", "highlighter"),
("notebook", "pen", "tea"),
("notebook", "pen", "highlighter", "tea"),
("notebook", "pen", "tea"),
("notebook", "tea"),
("pen", "tea"),
("pen", "tea", "samosa"),
("tea", "samosa"),
("tea", "samosa"),
("tea", "samosa", "photocopy"),
("tea", "photocopy"),
("photocopy", "stapler", "tea"),
("photocopy", "stapler"),
("photocopy", "stapler", "tea"),
("notebook", "pen", "highlighter"),
("notebook", "highlighter", "tea"),
("tea",),
("tea", "samosa"),
("notebook", "pen", "tea", "samosa"),
]
SETS = [set(b) for b in BASKETS]
ITEMS = sorted({i for b in BASKETS for i in b})
n = len(BASKETS)
MINSUP = 0.15 # 3 baskets in 20
MINCONF = 0.70
counted = 0 # how many itemsets were counted against the database
passes = 0 # how many times the database was read
def count(itemset):
global counted
counted += 1
s = set(itemset)
return sum(1 for b in SETS if s <= b)
def support(itemset):
return count(itemset) / n
print("THE PROBLEM. %d items means %d non-empty itemsets to consider:"
% (len(ITEMS), 2 ** len(ITEMS) - 1))
print(" %s" % ", ".join(ITEMS))
print(" counting all %d against %d baskets is possible here and is not possible"
% (2 ** len(ITEMS) - 1, n))
print(" at all in a shop with 10000 items, where the number is 2**10000.")
print()
print("THE ONE PROPERTY THAT SAVES IT: DOWNWARD CLOSURE, also called the apriori")
print("property or anti-monotonicity.")
print(" IF AN ITEMSET IS FREQUENT, EVERY SUBSET OF IT IS FREQUENT.")
print(" equivalently: if any subset is INFREQUENT, the set cannot be frequent.")
print(" the reason is one line: every basket containing the whole set contains")
print(" each of its subsets, so a subset's count is at least the set's count.")
print()
print(" checked on this data, for every frequent pair and triple:")
ok = bad = 0
for size in (2, 3):
for c in combinations(ITEMS, size):
s = set(c)
cnt = sum(1 for b in SETS if s <= b)
if cnt / n >= MINSUP:
for k in range(1, size):
for sub in combinations(c, k):
ss = set(sub)
subcnt = sum(1 for b in SETS if ss <= b)
if subcnt >= cnt:
ok += 1
else:
bad += 1
print(" %d subset comparisons, %d of them consistent, %d violations."
% (ok + bad, ok, bad))
print()
print("MINIMUM SUPPORT %.2f, which is %d baskets of %d. MINIMUM CONFIDENCE %.2f."
% (MINSUP, round(MINSUP * n), n, MINCONF))
print()
def apriori():
global passes
frequent = {}
# ---- level 1: every single item -----------------------------------------
passes += 1
level = []
print("LEVEL 1. count every item.")
print(" itemset | baskets | support | kept")
for it in ITEMS:
c = count([it])
keep = c / n >= MINSUP
print(" %-21s | %7d | %7.4f | %s" % (it, c, c / n, "yes" if keep else "NO"))
if keep:
level.append((it,))
frequent[(it,)] = c
print(" L1 has %d itemsets." % len(level))
print()
k = 2
while level:
# ---- JOIN: two frequent (k-1)-sets sharing their first k-2 items ----
cands = []
for i in range(len(level)):
for j in range(i + 1, len(level)):
a, b = level[i], level[j]
if a[:k - 2] == b[:k - 2]:
cands.append(tuple(sorted(set(a) | set(b))))
cands = sorted(set(c for c in cands if len(c) == k))
print("LEVEL %d. JOIN gives %d candidate%s."
% (k, len(cands), "" if len(cands) == 1 else "s"))
# ---- PRUNE: drop any candidate with an infrequent (k-1)-subset ------
kept, pruned = [], []
for c in cands:
subs = [tuple(s) for s in combinations(c, k - 1)]
if all(s in frequent for s in subs):
kept.append(c)
else:
missing = [s for s in subs if s not in frequent]
pruned.append((c, missing[0]))
if pruned:
print(" PRUNE removes %d of them WITHOUT COUNTING ANYTHING:" % len(pruned))
for c, miss in pruned:
print(" %-30s because %s is not frequent"
% ("+".join(c), "+".join(miss)))
else:
print(" PRUNE removes none.")
if not kept:
print(" nothing left to count. the algorithm stops.")
print()
break
passes += 1
print(" COUNT the %d survivor%s:" % (len(kept), "" if len(kept) == 1 else "s"))
print(" itemset | baskets | support | kept")
level = []
for c in kept:
cnt = count(c)
keep = cnt / n >= MINSUP
print(" %-26s | %7d | %7.4f | %s"
% ("+".join(c), cnt, cnt / n, "yes" if keep else "NO"))
if keep:
level.append(c)
frequent[c] = cnt
print(" L%d has %d itemset%s." % (k, len(level), "" if len(level) == 1 else "s"))
print()
k += 1
return frequent
frequent = apriori()
print("THE FREQUENT ITEMSETS, all of them:")
for size in sorted({len(k) for k in frequent}):
rows = sorted(k for k in frequent if len(k) == size)
print(" size %d: %s" % (size, "; ".join("+".join(r) for r in rows)))
print()
print("THE COST, MEASURED.")
print(" itemsets counted against the database : %d" % counted)
print(" every possible non-empty itemset : %d" % (2 ** len(ITEMS) - 1))
print(" passes over the database : %d" % passes)
print(" apriori counted %.0f per cent of the itemsets a brute force would."
% (100.0 * counted / (2 ** len(ITEMS) - 1)))
print(" the saving here is modest because %d items is a toy. the saving is the"
% len(ITEMS))
print(" difference between possible and impossible on a real catalogue, and it")
print(" comes entirely from the prune step, which rejects candidates WITHOUT")
print(" LOOKING AT THE DATA AT ALL.")
print()
print("GENERATING THE RULES. for each frequent itemset of 2 or more items, every")
print("way of splitting it into a non-empty antecedent and a non-empty")
print("consequent is a candidate rule; keep those above the confidence threshold.")
print(" rule | support | conf | lift")
rules = []
for iset, cnt in frequent.items():
if len(iset) < 2:
continue
for r in range(1, len(iset)):
for a in combinations(iset, r):
b = tuple(x for x in iset if x not in a)
conf = cnt / frequent[tuple(sorted(a))]
lift = conf / (frequent[tuple(sorted(b))] / n
if tuple(sorted(b)) in frequent
else sum(1 for bk in SETS if set(b) <= bk) / n)
rules.append((conf, lift, a, b, cnt / n))
for conf, lift, a, b, sup in sorted(rules, reverse=True):
if conf >= MINCONF:
print(" %-39s | %7.4f | %6.4f | %6.4f"
% ("if " + "+".join(a) + " then " + "+".join(b), sup, conf, lift))
print()
print(" %d of the %d candidate rules pass the confidence threshold."
% (sum(1 for c, _, _, _, _ in rules if c >= MINCONF), len(rules)))
print(" NOTE THE LIFT COLUMN. several rules above %.2f confidence have a lift"
% MINCONF)
print(" near 1, and they are the tea rules again: high confidence because tea")
print(" is everywhere. apriori CANNOT filter these out, because it never looks")
print(" at lift. the filtering is the analyst's job and it is not optional.")
print()
print("THE THRESHOLD DECIDES EVERYTHING. the same data at four minimum supports:")
print(" minsup | baskets | frequent itemsets | largest itemset | rules above %.2f"
% MINCONF)
for ms in (0.05, 0.10, 0.15, 0.25, 0.50):
freq = {}
for size in range(1, len(ITEMS) + 1):
for c in combinations(ITEMS, size):
s = set(c)
cnt = sum(1 for b in SETS if s <= b)
if cnt / n >= ms:
freq[c] = cnt
biggest = max((len(k) for k in freq), default=0)
nrules = 0
for iset, cnt in freq.items():
if len(iset) < 2:
continue
for r in range(1, len(iset)):
for a in combinations(iset, r):
if cnt / freq[tuple(sorted(a))] >= MINCONF:
nrules += 1
print(" %6.2f | %7d | %17d | %15d | %d"
% (ms, round(ms * n), len(freq), biggest, nrules))
print(" at %.2f a 'finding' can rest on a single basket; at %.2f only tea"
% (0.05, 0.50))
print(" itself survives and there are no rules at all.")
print(" THERE IS NO CORRECT VALUE. the threshold is a decision about how much")
print(" of the data a finding must cover before it is worth reading, and it is")
print(" made by the person, not by the algorithm.")The Apriori Algorithm
THE PROBLEM. 7 items means 127 non-empty itemsets to consider:
highlighter, notebook, pen, photocopy, samosa, stapler, tea
counting all 127 against 20 baskets is possible here and is not possible
at all in a shop with 10000 items, where the number is 2**10000.
THE ONE PROPERTY THAT SAVES IT: DOWNWARD CLOSURE, also called the apriori
property or anti-monotonicity.
IF AN ITEMSET IS FREQUENT, EVERY SUBSET OF IT IS FREQUENT.
equivalently: if any subset is INFREQUENT, the set cannot be frequent.
the reason is one line: every basket containing the whole set contains
each of its subsets, so a subset's count is at least the set's count.
checked on this data, for every frequent pair and triple:
36 subset comparisons, 36 of them consistent, 0 violations.
MINIMUM SUPPORT 0.15, which is 3 baskets of 20. MINIMUM CONFIDENCE 0.70.
LEVEL 1. count every item.
itemset | baskets | support | kept
highlighter | 4 | 0.2000 | yes
notebook | 9 | 0.4500 | yes
pen | 9 | 0.4500 | yes
photocopy | 5 | 0.2500 | yes
samosa | 6 | 0.3000 | yes
stapler | 3 | 0.1500 | yes
tea | 18 | 0.9000 | yes
L1 has 7 itemsets.
LEVEL 2. JOIN gives 21 candidates.
PRUNE removes none.
COUNT the 21 survivors:
itemset | baskets | support | kept
highlighter+notebook | 4 | 0.2000 | yes
highlighter+pen | 3 | 0.1500 | yes
highlighter+photocopy | 0 | 0.0000 | NO
highlighter+samosa | 0 | 0.0000 | NO
highlighter+stapler | 0 | 0.0000 | NO
highlighter+tea | 3 | 0.1500 | yes
notebook+pen | 7 | 0.3500 | yes
notebook+photocopy | 0 | 0.0000 | NO
notebook+samosa | 1 | 0.0500 | NO
notebook+stapler | 0 | 0.0000 | NO
notebook+tea | 8 | 0.4000 | yes
pen+photocopy | 0 | 0.0000 | NO
pen+samosa | 2 | 0.1000 | NO
pen+stapler | 0 | 0.0000 | NO
pen+tea | 8 | 0.4000 | yes
photocopy+samosa | 1 | 0.0500 | NO
photocopy+stapler | 3 | 0.1500 | yes
photocopy+tea | 4 | 0.2000 | yes
samosa+stapler | 0 | 0.0000 | NO
samosa+tea | 6 | 0.3000 | yes
stapler+tea | 2 | 0.1000 | NO
L2 has 9 itemsets.
LEVEL 3. JOIN gives 5 candidates.
PRUNE removes 1 of them WITHOUT COUNTING ANYTHING:
photocopy+stapler+tea because stapler+tea is not frequent
COUNT the 4 survivors:
itemset | baskets | support | kept
highlighter+notebook+pen | 3 | 0.1500 | yes
highlighter+notebook+tea | 3 | 0.1500 | yes
highlighter+pen+tea | 2 | 0.1000 | NO
notebook+pen+tea | 6 | 0.3000 | yes
L3 has 3 itemsets.
LEVEL 4. JOIN gives 1 candidate.
PRUNE removes 1 of them WITHOUT COUNTING ANYTHING:
highlighter+notebook+pen+tea because highlighter+pen+tea is not frequent
nothing left to count. the algorithm stops.
THE FREQUENT ITEMSETS, all of them:
size 1: highlighter; notebook; pen; photocopy; samosa; stapler; tea
size 2: highlighter+notebook; highlighter+pen; highlighter+tea; notebook+pen; notebook+tea; pen+tea; photocopy+stapler; photocopy+tea; samosa+tea
size 3: highlighter+notebook+pen; highlighter+notebook+tea; notebook+pen+tea
THE COST, MEASURED.
itemsets counted against the database : 32
every possible non-empty itemset : 127
passes over the database : 3
apriori counted 25 per cent of the itemsets a brute force would.
the saving here is modest because 7 items is a toy. the saving is the
difference between possible and impossible on a real catalogue, and it
comes entirely from the prune step, which rejects candidates WITHOUT
LOOKING AT THE DATA AT ALL.
GENERATING THE RULES. for each frequent itemset of 2 or more items, every
way of splitting it into a non-empty antecedent and a non-empty
consequent is a candidate rule; keep those above the confidence threshold.
rule | support | conf | lift
if stapler then photocopy | 0.1500 | 1.0000 | 4.0000
if highlighter+tea then notebook | 0.1500 | 1.0000 | 2.2222
if highlighter+pen then notebook | 0.1500 | 1.0000 | 2.2222
if highlighter then notebook | 0.2000 | 1.0000 | 2.2222
if samosa then tea | 0.3000 | 1.0000 | 1.1111
if pen then tea | 0.4000 | 0.8889 | 0.9877
if notebook then tea | 0.4000 | 0.8889 | 0.9877
if notebook+pen then tea | 0.3000 | 0.8571 | 0.9524
if photocopy then tea | 0.2000 | 0.8000 | 0.8889
if pen then notebook | 0.3500 | 0.7778 | 1.7284
if notebook then pen | 0.3500 | 0.7778 | 1.7284
if highlighter then notebook+pen | 0.1500 | 0.7500 | 2.1429
if highlighter then notebook+tea | 0.1500 | 0.7500 | 1.8750
if pen+tea then notebook | 0.3000 | 0.7500 | 1.6667
if notebook+tea then pen | 0.3000 | 0.7500 | 1.6667
if highlighter+notebook then pen | 0.1500 | 0.7500 | 1.6667
if highlighter then pen | 0.1500 | 0.7500 | 1.6667
if highlighter+notebook then tea | 0.1500 | 0.7500 | 0.8333
if highlighter then tea | 0.1500 | 0.7500 | 0.8333
19 of the 36 candidate rules pass the confidence threshold.
NOTE THE LIFT COLUMN. several rules above 0.70 confidence have a lift
near 1, and they are the tea rules again: high confidence because tea
is everywhere. apriori CANNOT filter these out, because it never looks
at lift. the filtering is the analyst's job and it is not optional.
THE THRESHOLD DECIDES EVERYTHING. the same data at four minimum supports:
minsup | baskets | frequent itemsets | largest itemset | rules above 0.70
0.05 | 1 | 31 | 4 | 28
0.10 | 2 | 25 | 4 | 22
0.15 | 3 | 19 | 3 | 19
0.25 | 5 | 10 | 3 | 8
0.50 | 10 | 1 | 1 | 0
at 0.05 a 'finding' can rest on a single basket; at 0.50 only tea
itself survives and there are no rules at all.
THERE IS NO CORRECT VALUE. the threshold is a decision about how much
of the data a finding must cover before it is worth reading, and it is
made by the person, not by the algorithm.The Apriori Algorithm
Reading the levels
minsup = 0.15, which is 3 baskets of 20, and minconf = 0.70.
The Apriori Algorithm
| Level | Candidates after join | Removed by prune | Counted | Frequent |
|---|---|---|---|---|
| 1 | 7 items | 7 | 7 | |
| 2 | 21 | 0 | 21 | 9 |
| 3 | 5 | 1 | 4 | 3 |
| 4 | 1 | 1 | 0 | 0, so it stops |
The Apriori Algorithm
Level 2 can never prune anything, and it is worth knowing why. A candidate pair's only subsets of size 1 are its two items, and both came from L1, so both are frequent by construction. Pruning begins to earn its keep at level 3.
The Apriori Algorithm
And at level 3 it earns it visibly: photocopy+stapler+tea is rejected because stapler+tea is not frequent, and it is rejected without touching the data. At level 4 the single candidate highlighter+notebook+pen+tea goes the same way, because highlighter+pen+tea had only two baskets, and with nothing left to count the algorithm terminates.
The Apriori Algorithm
The stopping condition is Lk empty, not k reaching some limit. The largest frequent itemset here has three items, and the algorithm discovers that rather than being told it.
The cost
| Itemsets counted against the database | 32 |
| Every possible non-empty itemset | 127 |
| Passes over the database | 3 |
Apriori counted 25 per cent of what brute force would. Be honest about the size of that: seven items is a toy, and a quarter is not a dramatic saving. The point is not the ratio here but that the saving comes from a step that rejects candidates without looking at the data at all, and on a real catalogue that is the difference between possible and impossible.
And note the three passes. Apriori needs one pass per level, so the number of database reads is the size of the largest frequent itemset plus one. That is its main practical cost and the thing its successors attack: FP-growth builds a compressed tree of the transactions and needs only two passes, and is the algorithm actually used on large data.
Generating the rules
Each frequent itemset of size k can be split into an antecedent and a consequent in 2k - 2 ways, and every split is a candidate rule. Nineteen of the thirty-six candidates** pass a confidence of 0.70.
The best of them:
| Rule | Support | Confidence | Lift |
|---|---|---|---|
if stapler then photocopy | 0.1500 | 1.0000 | 4.0000 |
if highlighter then notebook | 0.2000 | 1.0000 | 2.2222 |
if samosa then tea | 0.3000 | 1.0000 | 1.1111 |
if pen then tea | 0.4000 | 0.8889 | 0.9877 |
if photocopy then tea | 0.2000 | 0.8000 | 0.8889 |
if notebook then pen | 0.3500 | 0.7778 | 1.7284 |
Read the lift column. if pen then tea has a confidence of 0.8889 and a lift of 0.9877, which is below 1: pen buyers take tea slightly less often than the counter's customers in general. if photocopy then tea is worse, at 0.8889 lift. Both passed the confidence threshold comfortably.
The Apriori Algorithm
Apriori cannot filter these out, because it never looks at lift. It filters by support and then by confidence, and both of those measures are satisfied by a common consequent. The filtering by lift is the analyst's job, done afterwards, and it is not optional.
The threshold decides everything
minsup | Baskets | Frequent itemsets | Largest itemset | Rules above 0.70 |
|---|---|---|---|---|
| 0.05 | 1 | 31 | 4 | 28 |
| 0.10 | 2 | 25 | 4 | 22 |
| 0.15 | 3 | 19 | 3 | 19 |
| 0.25 | 5 | 10 | 3 | 8 |
| 0.50 | 10 | 1 | 1 | 0 |
At 0.05 a finding can rest on a single basket. At 0.50 only tea itself survives and there are no rules at all.
There is no correct value. The threshold is a decision about how much of the data a finding must cover before it is worth reading, and it is made by the person. Two consequences worth stating: the output size is extremely sensitive to it, and any published set of rules is meaningless without the thresholds that produced it.
The weaknesses, and what replaced it
A paper asking for Apriori's limitations wants these.
| Weakness | Why |
|---|---|
| One pass per level | expensive when the data does not fit in memory |
| Candidate generation | the number of candidates can still be enormous at level 2, where L1 of m frequent items gives m(m-1)/2 pairs |
| The rare item problem | a minsup low enough to catch uncommon items floods the output |
| No account of lift | the rules it returns include ones with a lift below 1 |
| Binary only | an item is present or absent; quantities and prices are ignored |
FP-growth is the standard successor: it builds an FP-tree, a compressed representation of all the transactions, in two passes, and then mines it recursively with no candidate generation at all. It is faster and it is harder to explain, which is why Apriori is what is taught: the Apriori property is the idea, and FP-growth is an implementation of the same insight.
Distinctions
| Support | Confidence | |
|---|---|---|
| Has downward closure | yes | no |
| Used for | the search | filtering afterwards |
| Order in the algorithm | first | second |
| Join | Prune | |
|---|---|---|
| Produces | candidates of size k | a shorter list of the same |
| Reads the database | no | no |
| Level 2 | 21 candidates | removes 0, necessarily |
| Level 3 | 5 candidates | removes 1 |
| Apriori | FP-growth | |
|---|---|---|
| Passes over the data | one per level, 3 here | 2 |
| Candidate generation | yes | none |
| Data structure | lists of candidates | an FP-tree |
| Easier to explain | yes | no |
The Apriori Algorithm
What it does not mean
Apriori does not find rules. It finds frequent itemsets; the rules are generated afterwards.
The prune step does not count anything. That is the whole point of it.
Pruning at level 2 is not a saving. It can never remove a candidate there.
Apriori does not stop at a fixed size. It stops when a level is empty, which is how it discovers that the largest frequent itemset has three items.
A rule Apriori returns is not necessarily interesting. Several here have a lift below 1.
The rule set is not a property of the data alone. It is a property of the data and the two thresholds.
Apriori is not the algorithm used at scale. FP-growth is.
Quick revision
mitems give2m - 1itemsets: 127 for 7, and210000 for a real shop.- Downward closure: if an itemset is frequent every subset is, so if any subset is infrequent the set cannot be. Proof: a basket containing the set contains every subset, so the subset's count is at least as large.
- The algorithm: count single items to get
L1; then join, prune, count, per level; stop when a level is empty; then generate rules. - Support searches, confidence filters afterwards, because support has downward closure and confidence does not.
- Measured at
minsup = 0.15andminconf = 0.70: levels of 7, 21, 5, 1 candidates, pruning 0, then 1, then 1; frequent itemsets 7, 9, 3; it stops at level 4. - Level 2 can never prune, since a pair's single-item subsets are both in
L1. Level 3 rejectsphotocopy+stapler+teabecausestapler+teais not frequent, without reading the data. - Cost: 32 itemsets counted against 127 possible, and 3 passes, one per level.
- 19 of 36 candidate rules pass the confidence threshold, and several have a lift below 1:
if pen then teais0.8889confidence and0.9877lift. Apriori never looks at lift, so filtering by it is the analyst's job. - Thresholds decide everything:
minsupof 0.05 gives 31 itemsets and 28 rules; 0.50 gives 1 itemset and no rules. There is no correct value, and a rule set is meaningless without its thresholds. - Weaknesses: one pass per level, candidate explosion at level 2, the rare item problem, no account of lift, binary items only. FP-growth replaces it: an FP-tree in two passes with no candidate generation.
Test yourself
1. State the Apriori property and prove it. If an itemset is frequent then every subset of it is frequent; equivalently, if any subset is infrequent then the set cannot be frequent. Every transaction containing the whole itemset necessarily contains each of its subsets, so a subset's count is at least the count of the set and its support is at least the set's support.
The Apriori Algorithm
2. Describe the algorithm. Count each single item and keep those reaching the minimum support, giving L1. Then for each k from 2: join pairs of frequent (k-1)-itemsets that agree on their first k-2 items to form candidates; prune any candidate having an infrequent subset of size k-1, without counting; count the survivors in one pass over the data and keep those reaching minimum support. Stop when a level yields nothing, then generate rules from the frequent itemsets and keep those reaching the minimum confidence.
3. Why is the search done by support rather than by confidence? Because support has the downward closure property and confidence does not. A set's support cannot exceed that of any of its subsets, which allows candidates to be discarded without counting; nothing comparable holds for confidence, so it can only be applied to itemsets already found.
4. Why can the prune step never remove anything at level 2? A candidate pair's only subsets of size one are its two items, and both were taken from L1, so both are frequent by construction. Pruning first becomes useful at level 3.
5. Give an example of the prune step working, from this chapter. At level 3 the candidate photocopy, stapler and tea was discarded because the pair stapler and tea had only two baskets and so was not frequent. It was rejected without being counted at all. At level 4 the only candidate was discarded for the same reason.
6. Apriori returned a rule with a confidence of 0.8889 and a lift of 0.9877. What does that show about the algorithm? That Apriori filters by support and then by confidence and never examines lift, so it will return rules whose consequent is simply common. Here pen buyers take tea slightly less often than customers in general, yet the rule passes both thresholds. Filtering by lift must be done by the analyst afterwards.
7. How does FP-growth improve on Apriori? It makes two passes over the data instead of one per level, building an FP-tree that holds the transactions in compressed form, and then mines the frequent itemsets recursively from that tree with no candidate generation at all. It rests on the same downward closure insight but avoids both the repeated scans and the candidate lists.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself, or the past papers, for the same subject.