Itemset: combinação sem direção
Um itemset é apenas um conjunto de itens que aparecem juntos.
Aqui ainda não estamos dizendo que um produto leva ao outro. Estamos apenas perguntando: “quantas compras contêm os dois?”
APRENDIZAGEM NÃO SUPERVISIONADA · REGRAS DE ASSOCIAÇÃO
Aprenda como o algoritmo sai de uma lista de compras e chega a regras como “quem compra Pão tende a comprar Manteiga” — entendendo exatamente o que significam suporte, confiança e lift.
COMECE PELO PROBLEMA
Imagine que você tenha milhares de compras de supermercado. Cada compra é uma transação. O objetivo é descobrir quais produtos aparecem juntos com frequência e, a partir desses padrões, gerar regras de associação.
Um itemset é apenas um conjunto de itens que aparecem juntos.
Aqui ainda não estamos dizendo que um produto leva ao outro. Estamos apenas perguntando: “quantas compras contêm os dois?”
Depois que encontramos combinações frequentes, podemos criar regras:
A leitura é: “entre as compras que contêm Pão, com que frequência também aparece Manteiga?”
NOSSA BASE DIDÁTICA
Com uma base pequena conseguimos contar tudo manualmente. Depois o algoritmo faz exatamente a mesma lógica em milhares ou milhões de transações.
Para estudar a regra Pão ⇒ Manteiga, precisamos saber:
ANTES DO ALGORITMO
Clique em cada métrica. As próprias transações serão destacadas para mostrar exatamente qual é o numerador e qual é o denominador.
1 · SUPORTE
O suporte mede a frequência do itemset completo. Para Pão e Manteiga, contamos quantas das 10 compras contêm os dois ao mesmo tempo.
Interpretação: em 40% de todas as compras da base, Pão e Manteiga aparecem juntos.
Porque ele não quer perder tempo explorando combinações muito raras. Definimos um suporte mínimo, por exemplo 30%.
Se um conjunto aparece em menos de 30% das compras, ele não é considerado frequente e pode ser descartado.
2 · CONFIANÇA
Agora não olhamos mais para todas as 10 compras. Olhamos apenas para as compras que já possuem o antecedente da regra.
Existem 6 compras com Pão. Em 4 delas também existe Manteiga.
Logo: entre quem comprou Pão, 66,7% também comprou Manteiga.
O itemset é o mesmo {Pão, Manteiga}, mas a confiança muda porque o denominador é o antecedente.
3 · LIFT
Uma confiança alta pode enganar quando o consequente já é muito popular. O lift compara a confiança da regra com a frequência normal do consequente.
Manteiga aparece normalmente em 50% da base. Mas entre as compras com Pão, aparece em 66,7%.
Leitura: Pão e Manteiga aparecem juntos cerca de 1,33 vez o esperado sob independência.
Considere Café ⇒ Leite. Entre as 5 compras com Café, 4 têm Leite:
Parece uma ótima regra. Mas Leite já aparece em 90% de todas as compras.
Ou seja: entre compradores de Café, Leite aparece até menos do que na população geral.
AGORA SIM: O APRIORI
Se existem milhares de produtos, há combinações demais. O Apriori usa o suporte e uma propriedade simples para eliminar grande parte delas antes de chegar às regras.
Pão, Manteiga, Leite, Café.
Aplicar o suporte mínimo.
Contar quais aparecem juntos.
Eliminar combinações infrequentes e seus supersets.
Calcular confiança e lift dos padrões encontrados.
O ALGORITMO POR DENTRO
for?Antes de usar C₁, L₁ ou qualquer notação, pense no programa executando. Em cada rodada existem candidatos atuais. O Apriori percorre cada compra e pergunta, candidato por candidato: “todos os itens desta combinação aparecem neste carrinho?”
for interno é apenas CONTAR. Ele ainda não calcula confiança nem lift. Ele verifica se o candidato está contido na compra e, se estiver, soma +1 à contagem daquele candidato.
if candidato ⊆ compra.
Estes números começam em zero. Eles só aumentam quando todos os itens do candidato aparecem na compra atual.
for: percorre comprasEle pega a Compra 1, depois a Compra 2, depois a Compra 3... até visitar toda a base.
for: percorre candidatosPara a mesma compra, ele testa todos os candidatos daquela rodada. Na primeira rodada são itens; na seguinte são pares; depois podem ser trios.
if: a combinação está inteira no carrinho?Para {Pão, Manteiga}, não basta existir Pão. Pão e Manteiga precisam estar juntos na mesma compra.
for terminamSó agora a contagem vira suporte. Os candidatos abaixo do mínimo morrem; os demais serão usados para construir a rodada seguinte.
Suponha que os candidatos atuais sejam {Pão,Manteiga}, {Pão,Leite} e {Manteiga,Café}, e a compra atual seja:
| Candidato | Pergunta feita pelo if | Resposta | Ação |
|---|---|---|---|
| {Pão,Manteiga} | Pão E Manteiga estão na compra? | Sim | contador += 1 |
| {Pão,Leite} | Pão E Leite estão na compra? | Sim | contador += 1 |
| {Manteiga,Café} | Manteiga E Café estão na compra? | Não | não altera o contador |
for externo passa para a próxima compra e repete exatamente os mesmos testes. Quando todas as compras terminarem, teremos a frequência de cada candidato.Depois de calcular o suporte, ficamos apenas com os sobreviventes. Então o Apriori combina esses sobreviventes para tentar criar conjuntos um item maiores.
for das comprasEXECUTANDO O ALGORITMO NA MÃO
Agora vamos executar o algoritmo de verdade usando as mesmas 10 compras. Definiremos suporte mínimo = 30%. Como existem 10 transações, um conjunto precisa aparecer em pelo menos 3 compras para continuar vivo.
No começo não conhecemos nenhuma relação. Então o algoritmo simplesmente conta em quantas transações cada item aparece.
| Candidato C₁ | Contagem | Cálculo do suporte | Suporte | Resultado |
|---|---|---|---|---|
| {Pão} | 6 compras | 6 ÷ 10 | 60% | fica em L₁ |
| {Manteiga} | 5 compras | 5 ÷ 10 | 50% | fica em L₁ |
| {Leite} | 9 compras | 9 ÷ 10 | 90% | fica em L₁ |
| {Café} | 5 compras | 5 ÷ 10 | 50% | fica em L₁ |
O Apriori usa os itens de L₁ para criar os candidatos de tamanho 2, chamados C₂. Agora ele volta às transações e conta quantas vezes cada par aparece junto.
| Candidato C₂ | Contagem conjunta | Suporte | Resultado |
|---|---|---|---|
| {Pão, Manteiga} | 4 compras | 4 ÷ 10 = 40% | frequente |
| {Pão, Leite} | 6 compras | 6 ÷ 10 = 60% | frequente |
| {Pão, Café} | 3 compras | 3 ÷ 10 = 30% | frequente |
| {Manteiga, Leite} | 5 compras | 5 ÷ 10 = 50% | frequente |
| {Manteiga, Café} | 2 compras | 2 ÷ 10 = 20% | eliminado |
| {Leite, Café} | 4 compras | 4 ÷ 10 = 40% | frequente |
Agora o Apriori poderia tentar todos os trios possíveis. Mas antes de consultar a base, ele verifica uma regra simples: todos os pares que formam aquele trio precisam estar em L₂.
Seus pares são:
{Pão, Manteiga} ✓ {Pão, Leite} ✓ {Manteiga, Leite} ✓
Todos são frequentes. Portanto o trio vale ser contado.
Seus pares são:
{Pão, Manteiga} ✓ {Pão, Café} ✓ {Manteiga, Café} ✗
Como um de seus subconjuntos já falhou, o trio inteiro é podado.
| Trio | Teste Apriori | Contagem | Resultado |
|---|---|---|---|
| {Pão, Manteiga, Leite} | todos os pares frequentes | 4/10 = 40% | L₃ |
| {Pão, Leite, Café} | todos os pares frequentes | 3/10 = 30% | L₃ |
| {Pão, Manteiga, Café} | {Manteiga,Café} falhou | nem precisa | podado |
| {Manteiga, Leite, Café} | {Manteiga,Café} falhou | nem precisa | podado |
O único conjunto de 4 itens possível seria:
Mas ele contém o subconjunto {Manteiga, Café}, que já sabemos ser infrequente. Portanto ele também pode ser descartado.
Os itemsets frequentes dizem apenas “estes itens aparecem juntos bastante”. Para produzir uma regra, dividimos um itemset frequente em dois lados.
suporte = 40%
Para cada direção, o algoritmo calcula confiança e depois lift. Se você também definir uma confiança mínima, regras abaixo desse valor podem ser descartadas.
EXEMPLO COMPLETO
Com 10 transações, um itemset precisa aparecer em pelo menos 3 compras para sobreviver.
DE ITEMSET PARA REGRA
O itemset frequente {Pão, Manteiga} pode originar duas regras diferentes. O suporte é o mesmo, mas a confiança pode ser diferente porque a direção mudou.
Suporte = 40% · Confiança = 66,7% · Lift = 1,33
Suporte = 40% · Confiança = 80% · Lift = 1,33
LABORATÓRIO
O laboratório usa as mesmas 10 compras. Escolha uma regra; ele conta antecedente, consequente e ocorrência conjunta, calcula as três métricas e destaca as transações relevantes.
O QUE SAI NO FINAL?
Na prática, você recebe uma tabela de regras. Cada linha precisa ser interpretada observando as métricas em conjunto.
| Regra | Suporte | Confiança | Lift | Leitura |
|---|---|---|---|---|
| Pão ⇒ Manteiga | 40% | 66,7% | 1,33 | Associação positiva nesta base. |
| Manteiga ⇒ Pão | 40% | 80% | 1,33 | Mesma coocorrência, confiança maior pela direção. |
| Café ⇒ Leite | 40% | 80% | 0,89 | Confiança alta, mas abaixo da taxa normal de Leite. |
| Pão + Café ⇒ Leite | 30% | 100% | 1,11 | Todos os carrinhos com Pão+Café têm Leite, mas Leite já é muito comum. |
GUARDE ESTA IDEIA
“Isso acontece bastante?”
Olha para a base inteira.
“Quando A acontece, B aparece quanto?”
Olha apenas para casos com A.
“Isso é mais do que eu esperaria normalmente?”
Compara a regra com a popularidade de B.
IMPLEMENTAÇÃO DO ZERO
Este código não chama apriori(), mlxtend nem uma implementação pronta. Observe principalmente os dois laços aninhados: para cada compra → para cada candidato → verificar se o candidato está dentro da compra → incrementar a contagem. Depois a contagem vira suporte, os sobreviventes geram novos candidatos e a varredura começa novamente.
# =========================================================
# APRIORI DO ZERO — SEM BIBLIOTECA DE MINERAÇÃO
# =========================================================
transacoes = [
{'Pão', 'Manteiga', 'Leite', 'Café'},
{'Pão', 'Manteiga', 'Leite'},
{'Pão', 'Manteiga', 'Leite', 'Café'},
{'Pão', 'Manteiga', 'Leite'},
{'Pão', 'Leite', 'Café'},
{'Pão', 'Leite'},
{'Manteiga', 'Leite'},
{'Leite', 'Café'},
{'Leite'},
{'Café'}
]
SUPORTE_MINIMO = 0.30
CONFIANCA_MINIMA = 0.60
# ---------------------------------------------------------
# 1. GERAR COMBINAÇÕES SEM itertools
# ---------------------------------------------------------
def combinacoes(lista, tamanho, inicio=0, atual=None):
if atual is None:
atual = []
if len(atual) == tamanho:
return [atual[:]]
resultado = []
for i in range(inicio, len(lista)):
atual.append(lista[i])
resultado += combinacoes(lista, tamanho, i + 1, atual)
atual.pop()
return resultado
# ---------------------------------------------------------
# 2. CONTAR CANDIDATOS
# ---------------------------------------------------------
def contar_candidatos(transacoes, candidatos):
contagem = {}
# Todos começam com zero ocorrências.
for candidato in candidatos:
contagem[candidato] = 0
# FOR EXTERNO:
# pega UMA compra por vez.
for compra in transacoes:
# FOR INTERNO:
# testa TODOS os candidatos nessa compra.
for candidato in candidatos:
# O candidato está INTEIRO dentro da compra?
if candidato.issubset(compra):
contagem[candidato] += 1
return contagem
# ---------------------------------------------------------
# 3. TRANSFORMAR CONTAGEM EM SUPORTE E FILTRAR
# ---------------------------------------------------------
def filtrar_por_suporte(candidatos, contagem, total_transacoes):
frequentes = []
suportes = {}
for candidato in candidatos:
suporte = contagem[candidato] / total_transacoes
suportes[candidato] = suporte
if suporte >= SUPORTE_MINIMO:
frequentes.append(candidato)
return frequentes, suportes
# ---------------------------------------------------------
# 4. GERAR OS PRÓXIMOS CANDIDATOS + PODA APRIORI
# ---------------------------------------------------------
def gerar_proximos_candidatos(frequentes_anteriores, novo_tamanho):
candidatos = set()
frequentes_set = set(frequentes_anteriores)
# Junta sobreviventes dois a dois.
for a in frequentes_anteriores:
for b in frequentes_anteriores:
candidato = a | b
# Queremos exatamente um item a mais.
if len(candidato) != novo_tamanho:
continue
# Antes de aceitar esse candidato, verificamos
# todos os subconjuntos com tamanho novo_tamanho - 1.
lista = list(candidato)
subconjuntos = combinacoes(lista, novo_tamanho - 1)
pode_testar = True
for subconjunto_lista in subconjuntos:
subconjunto = frozenset(subconjunto_lista)
# Se algum subconjunto já foi infrequente,
# o candidato maior é PODADO sem contar na base.
if subconjunto not in frequentes_set:
pode_testar = False
break
if pode_testar:
candidatos.add(frozenset(candidato))
return list(candidatos)
# ---------------------------------------------------------
# 5. CRIAR OS CANDIDATOS DE 1 ITEM
# ---------------------------------------------------------
itens = set()
for compra in transacoes:
for item in compra:
itens.add(item)
candidatos = []
for item in itens:
candidatos.append(frozenset([item]))
# ---------------------------------------------------------
# 6. LOOP PRINCIPAL DO APRIORI
# ---------------------------------------------------------
todos_frequentes = []
suportes_globais = {}
tamanho = 1
while len(candidatos) > 0:
print('\nRODADA', tamanho)
print('Candidatos:', [set(c) for c in candidatos])
# A) percorre todas as compras e conta os candidatos.
contagem = contar_candidatos(transacoes, candidatos)
# B) contagem / número de compras = suporte.
frequentes, suportes = filtrar_por_suporte(
candidatos,
contagem,
len(transacoes)
)
for candidato in candidatos:
print(
set(candidato),
'contagem =', contagem[candidato],
'suporte =', round(suportes[candidato] * 100, 1), '%'
)
# C) guarda somente os sobreviventes.
if len(frequentes) == 0:
break
todos_frequentes += frequentes
suportes_globais.update(suportes)
# D) cria candidatos um item maiores.
tamanho += 1
candidatos = gerar_proximos_candidatos(
frequentes,
tamanho
)
# O while volta para o começo.
# Os NOVOS candidatos serão novamente testados
# contra TODAS as compras.
# ---------------------------------------------------------
# 7. FUNÇÃO DE SUPORTE PARA ITEMSETS JÁ ENCONTRADOS
# ---------------------------------------------------------
def suporte(itemset):
if itemset in suportes_globais:
return suportes_globais[itemset]
contagem = 0
for compra in transacoes:
if itemset.issubset(compra):
contagem += 1
return contagem / len(transacoes)
# ---------------------------------------------------------
# 8. SÓ AGORA GERAR REGRAS
# ---------------------------------------------------------
regras = []
for itemset in todos_frequentes:
if len(itemset) < 2:
continue
itens_do_itemset = list(itemset)
# Testa antecedentes com 1 item, 2 itens, ...
for tamanho_antecedente in range(1, len(itemset)):
possibilidades = combinacoes(
itens_do_itemset,
tamanho_antecedente
)
for antecedente_lista in possibilidades:
antecedente = frozenset(antecedente_lista)
consequente = itemset - antecedente
suporte_itemset = suporte(itemset)
suporte_antecedente = suporte(antecedente)
suporte_consequente = suporte(consequente)
confianca = suporte_itemset / suporte_antecedente
lift = confianca / suporte_consequente
if confianca >= CONFIANCA_MINIMA:
regras.append({
'antecedente': antecedente,
'consequente': consequente,
'suporte': suporte_itemset,
'confianca': confianca,
'lift': lift
})
# ---------------------------------------------------------
# 9. RESULTADO
# ---------------------------------------------------------
print('\nREGRAS ENCONTRADAS')
for regra in regras:
print(
set(regra['antecedente']),
'=>',
set(regra['consequente']),
'| suporte =', round(regra['suporte'] * 100, 1), '%',
'| confiança =', round(regra['confianca'] * 100, 1), '%',
'| lift =', round(regra['lift'], 2)
)
Combina os itemsets frequentes do nível anterior para tentar criar conjuntos um item maiores.
Antes de contar um candidato, verifica se todos os seus subconjuntos de tamanho k−1 sobreviveram no nível anterior.
Repete a geração e a filtragem até não existir mais nenhum conjunto frequente maior.
REFERÊNCIAS
Agrawal, R.; Srikant, R. Fast Algorithms for Mining Association Rules. VLDB, 1994.
Oracle Machine Learning. Apriori — avaliação de regras por suporte, confiança e lift.
mlxtend. Association Rules — definições e fórmulas das métricas de regras de associação.
IBM. Apriori Algorithm — visão geral de itemsets frequentes, suporte, confiança e lift.