8  Reglas de asociación

Las reglas de asociación son una técnica fundamental en ML que se utiliza para descubrir patrones significativos y relaciones ocultas en conjuntos de datos, especialmente aquellos que involucran transacciones o cestas de la compra. Estas reglas desempeñan un papel crucial en la extracción de conocimiento de datos, y su aplicación abarca una amplia variedad de dominios.

Descubriendo Patrones Relevantes: Las reglas de asociación son un enfoque de ML diseñado para identificar patrones de co-ocurrencia entre elementos o características en conjuntos de datos. Estas reglas permiten revelar conexiones interesantes y relaciones significativas que a menudo pasan desapercibidas a simple vista. Las reglas de asociación sirven para descrubrir patrones de ocurrencia, no sirven para comprobar ideas o hipótesis sobre los datos. Los escenarios ideales para su aplicación incluyen, pero no se limitan a, datos de transacciones de compras de clientes, registros de usuarios en línea y registros de interacciones de productos.

Nota

Supongamos que disponemos de un conjunto de datos de compras de clientes en una tienda en línea. Los datos pueden verse de la siguiente manera:

Transacción Productos comprados
1 Pan, Leche, Huevos
2 Leche, Queso, Yogur
3 Pan, Leche, Mantequilla
4 Pan, Huevos
5 Leche, Huevos, Queso
6 Huevos, Queso, Yogur
7 Mantequilla, Chocolate
8 Pan, Leche, Chocolate

En este conjunto de datos, cada fila representa una transacción y los productos comprados en esa transacción. Las reglas de asociación se utilizan para descubrir patrones de co-ocurrencia entre productos. Por ejemplo, podríamos encontrar las siguientes reglas de asociación:

Si un cliente compra Pan y Leche, entonces también compra Huevos. Si un cliente compra Leche y Queso, entonces también compra Yogur.

La Estructura de “Si… Entonces…”: Como acabas de ver en el ejemplo, estas reglas de asociación se expresan típicamente en una estructura condicional “si… entonces…”, donde se establece una relación entre los elementos o características. Esta estructura es fácilmente interpretable y ofrece una base sólida para la toma de decisiones y la generación de recomendaciones. La interpretación de estas reglas \(X\Rightarrow Y\) se hace desde un punto de vista de frecuencia, esto es, cuando en un conjunto aparece el conjunto de items \(X\) entonces también suele aparecer o es probable que aparezca el item \(Y\):

Importante

A lo largo del libro, hemos utilizado \(X\) para referirnos a las variables explicativas e \(Y\) para referirnos al target. Sin embargo, en este capítulo ambas hacen referencias a transacciones (\(X\) el antecedente e \(Y\) el consecuente) y tomarán valores del estilo \(X\) = {leche, huevos, chocolate}, \(Y\) = {mantequilla}

Mediciones de Fuerza de Asociación: Para cuantificar la importancia de estas reglas, se utilizan tres métricas clave: el soporte (support), la confianza (confidence) y lift:

Estas métricas ayudan a determinar la solidez y la utilidad de las reglas de asociación descubiertas.

Veamos un ejemplo con los datos de la tabla de arriba:

Aplicaciones en Diversos Campos: Las reglas de asociación tienen una amplia gama de aplicaciones en el mundo real. Desde el ámbito del comercio electrónico, donde se utilizan para generar recomendaciones de productos personalizadas, hasta la investigación de mercado, donde ayudan a identificar tendencias y patrones de consumo. También se aplican en la optimización de la colocación de productos en tiendas y la detección de anomalías en datos, como fraudes o comportamientos inusuales.

Algoritmos Especializados: Para extraer reglas de asociación, se utilizan algoritmos especializados como Apriori y FP-Growth. Estos algoritmos son capaces de manejar grandes conjuntos de datos y descubrir patrones complejos de manera eficiente.

8.1 Reglas de asociación en R

Vamos a emplear un ejemplo en R. El conjunto de datos Groceries contiene datos de ventas de una tienda de comestibles con \(9835\) transacciones y \(169\) artículos (grupos de productos).

library(arulesViz)
Loading required package: arules
Loading required package: Matrix

Attaching package: 'arules'
The following objects are masked from 'package:base':

    abbreviate, write
# Limitamos el número de decimales en la salida
 options(digits = 2)
# reproducible
 set.seed(1234)
 
 data("Groceries")
 summary(Groceries)
transactions as itemMatrix in sparse format with
 9835 rows (elements/itemsets/transactions) and
 169 columns (items) and a density of 0.026 

most frequent items:
      whole milk other vegetables       rolls/buns             soda 
            2513             1903             1809             1715 
          yogurt          (Other) 
            1372            34055 

element (itemset/transaction) length distribution:
sizes
   1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
2159 1643 1299 1005  855  645  545  438  350  246  182  117   78   77   55   46 
  17   18   19   20   21   22   23   24   26   27   28   29   32 
  29   14   14    9   11    4    6    1    1    1    1    3    1 

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      1       2       3       4       6      32 

includes extended item information - examples:
       labels  level2           level1
1 frankfurter sausage meat and sausage
2     sausage sausage meat and sausage
3  liver loaf sausage meat and sausage

El resumen muestra algunas estadísticas básicas del conjunto de datos. Por ejemplo, vemos que hay un total de 9835 transacciones, un total de 169 items diferentes y una densidad muy bajita, ligeramente superior al \(2,6\%\) (esta densidad indica el porcentaje de celdas distintas de 0 en la matriz de 9835x169 de datos). También muestra que la leche entera es el artículo más popular y que la transacción media es de 4 unidades. Element length distribution indica cómo son las transacciones: hay 2159 transacciones de 1 elemento, 1643 de 2 elementos o una única transacción de 32 elementos.

A continuación, extraemos reglas de asociación mediante el algoritmo Apriori implementado en la librería arules.

# soporte minimo 0.001
# confianza 0.5
rules <- apriori(Groceries, parameter=list(support=0.001, confidence=0.5))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport maxtime support minlen
        0.5    0.1    1 none FALSE            TRUE       5   0.001      1
 maxlen target  ext
     10  rules TRUE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 9 

set item appearances ...[0 item(s)] done [0.00s].
set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s].
sorting and recoding items ... [157 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 3 4 5 6 done [0.01s].
writing ... [5668 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].
rules
set of 5668 rules 

El resultado es un conjunto de \(5668\) reglas de asociación. Las tres reglas más importantes con respecto a la medida lift, una medida popular de la fuerza de las reglas, son:

inspect(head(rules, n = 3, by ="lift"))
    lhs                              rhs              support confidence
[1] {Instant food products, soda} => {hamburger meat} 0.0012  0.63      
[2] {soda, popcorn}               => {salty snack}    0.0012  0.63      
[3] {flour, baking powder}        => {sugar}          0.0010  0.56      
    coverage lift count
[1] 0.0019   19   12   
[2] 0.0019   17   12   
[3] 0.0018   16   10   

Aquí podemos ver el soporte, esto es, la relevancia en términos de la ocurrencia de cada regla, así como la confianza, o probablidad de que se cumpla.

Además, se pueden analizar reglas específicas que nos interesen, por ejemplo, qué items compran los clientes y llevan asociado comprar salsichas. Para ello, indicamos en el código default="lhs y rhs="sausage":

# soporte minimo 0.001
# confianza 0.5
rules_sausage <- apriori(Groceries, parameter=list(support=0.001, confidence=0.5),
                       appearance = list(default="lhs", rhs="sausage"))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport maxtime support minlen
        0.5    0.1    1 none FALSE            TRUE       5   0.001      1
 maxlen target  ext
     10  rules TRUE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 9 

set item appearances ...[1 item(s)] done [0.00s].
set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s].
sorting and recoding items ... [157 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 3 4 5 6 done [0.01s].
writing ... [4 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].
inspect(rules_sausage)
    lhs                    rhs       support confidence coverage lift count
[1] {citrus fruit,                                                         
     other vegetables,                                                     
     hard cheese}       => {sausage}  0.0010       0.59   0.0017  6.3    10
[2] {pip fruit,                                                            
     yogurt,                                                               
     sliced cheese}     => {sausage}  0.0012       0.60   0.0020  6.4    12
[3] {whole milk,                                                           
     domestic eggs,                                                        
     chocolate}         => {sausage}  0.0010       0.50   0.0020  5.3    10
[4] {butter,                                                               
     yogurt,                                                               
     brown bread}       => {sausage}  0.0010       0.56   0.0018  5.9    10

Del mismo modo, podemos estar interesados en saber qué se compra asociado al azúcar:

rules_sugar <- apriori(Groceries, parameter=list(support=0.001, confidence=0.3),
                       appearance = list(lhs="sugar", default="rhs"))
Apriori

Parameter specification:
 confidence minval smax arem  aval originalSupport maxtime support minlen
        0.3    0.1    1 none FALSE            TRUE       5   0.001      1
 maxlen target  ext
     10  rules TRUE

Algorithmic control:
 filter tree heap memopt load sort verbose
    0.1 TRUE TRUE  FALSE TRUE    2    TRUE

Absolute minimum support count: 9 

set item appearances ...[1 item(s)] done [0.00s].
set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s].
sorting and recoding items ... [157 item(s)] done [0.00s].
creating transaction tree ... done [0.00s].
checking subsets of size 1 2 done [0.00s].
writing ... [2 rule(s)] done [0.00s].
creating S4 object  ... done [0.00s].
inspect(rules_sugar)
    lhs        rhs                support confidence coverage lift count
[1] {sugar} => {other vegetables} 0.011   0.32       0.034    1.6  106  
[2] {sugar} => {whole milk}       0.015   0.44       0.034    1.7  148  

8.2 Visualizando las reglas

En conjuntos de datos reales, es imposible repasar manualmente el elevado número de reglas de asociación que se crean. ¡En el ejemplo anterior se habían creado \(5668\) reglas!

Una visualización sencilla de las reglas de asociación es utilizar un gráfico de dispersión con dos medidas de interés en los ejes.

plot(rules)
To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.

Podemos ver que las normas con gran elevación (lift) suelen tener un soporte relativamente bajo. Las reglas más interesantes aparecen en la frontera support/confidence. Otro gráfico intersante es el siguiente. En este caso, el soporte y la confianza se utilizan para los ejes X e Y, y el color de los puntos se utiliza para indicar el “orden”, es decir, el número de elementos que contiene la regla.

 plot(rules, method = "two-key plot")
To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.

Del gráfico se desprende claramente que el orden y el soporte tienen una relación inversa muy fuerte, lo que es un hecho conocido para las reglas de asociación.

Podemos visualizar grupos de reglas más específicamente:

subrules <- rules[quality(rules)$confidence > 0.9]
plot(subrules,method="grouped")

Finalmente, podemos visualizar las reglas de asociación mediante vértices y aristas en los que los vértices anotados con etiquetas de elementos representan elementos y los conjuntos de elementos o reglas se representan como un segundo conjunto de vértices. Los elementos se conectan con los conjuntos de elementos/reglas mediante flechas. En el caso de las reglas, las flechas que apuntan de los artículos a los vértices de las reglas indican los artículos del LHS y una flecha de una regla a un artículo indica el RHS. Las medidas de interés suelen añadirse al gráfico mediante el color o el tamaño de los vértices que representan los conjuntos de elementos/reglas. La visualización basada en gráficos ofrece una representación muy clara de las reglas, pero tienden a saturarse con facilidad, por lo que sólo son viables para conjuntos de reglas muy pequeños.

subrules2 <- head(rules, n = 10, by = "lift")
plot(subrules2, method = "graph")

La representación anterior se centra en cómo las reglas se componen de elementos individuales y muestra qué reglas comparten elementos.

plot(subrules2, method = "paracoord", control = list(reorder = TRUE))