{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Apriori en Python\n", "===\n", "\n", "* *10 min* | Última modificación: Junio 28, 2019." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A continuación se presenta una implementación simple del algoritmo Apriori en Python, como complemento a la implementación presentada en R." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "##\n", "## Preparación\n", "##\n", "from apyori import apriori \n", "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[['x1', 'x2', 'x3'],\n", " ['x1', 'x3'],\n", " ['x2', 'x4'],\n", " ['x1', 'x2', 'x3'],\n", " ['x1', 'x2', 'x5'],\n", " ['x1', 'x2', 'x3', 'x4'],\n", " ['x4', 'x6'],\n", " ['x1', 'x2', 'x4', 'x6'],\n", " ['x1', 'x3', 'x4'],\n", " ['x1', 'x2', 'x3']]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "##\n", "## Se preparan los datos\n", "##\n", "data = [['x1', 'x2', 'x3'], \n", " ['x1', 'x3'],\n", " ['x2', 'x4'],\n", " ['x1', 'x2', 'x3'],\n", " ['x1', 'x2', 'x5'],\n", " ['x1', 'x2', 'x3', 'x4'],\n", " ['x4', 'x6'],\n", " ['x1', 'x2', 'x4', 'x6'],\n", " ['x1', 'x3', 'x4'],\n", " ['x1', 'x2', 'x3']]\n", "\n", "data" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "transactions_rules = apriori(data, \n", " min_support=0.006, \n", " min_confidence=0.25, \n", " min_lift=1, \n", " min_length=1) \n", "transactions_rules = list(transactions_rules) \n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "17\n" ] } ], "source": [ "print(len(transactions_rules)) " ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RelationRecord(items=frozenset({'x1'}), support=0.8, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x1'}), confidence=0.8, lift=1.0)])\n", "RelationRecord(items=frozenset({'x2'}), support=0.7, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x2'}), confidence=0.7, lift=1.0)])\n", "RelationRecord(items=frozenset({'x3'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x3'}), confidence=0.6, lift=1.0)])\n", "RelationRecord(items=frozenset({'x4'}), support=0.5, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x4'}), confidence=0.5, lift=1.0)])\n", "RelationRecord(items=frozenset({'x1', 'x2'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1'}), items_add=frozenset({'x2'}), confidence=0.7499999999999999, lift=1.0714285714285714), OrderedStatistic(items_base=frozenset({'x2'}), items_add=frozenset({'x1'}), confidence=0.8571428571428572, lift=1.0714285714285714)])\n", "RelationRecord(items=frozenset({'x3', 'x1'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1'}), items_add=frozenset({'x3'}), confidence=0.7499999999999999, lift=1.2499999999999998), OrderedStatistic(items_base=frozenset({'x3'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x5', 'x1'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x5', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286)])\n", "RelationRecord(items=frozenset({'x6', 'x4'}), support=0.2, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4'}), items_add=frozenset({'x6'}), confidence=0.4, lift=2.0), OrderedStatistic(items_base=frozenset({'x6'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "RelationRecord(items=frozenset({'x3', 'x1', 'x2'}), support=0.4, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1', 'x2'}), items_add=frozenset({'x3'}), confidence=0.6666666666666667, lift=1.1111111111111114), OrderedStatistic(items_base=frozenset({'x3', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x5', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x5', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x6', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x6', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x6', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x4', 'x3', 'x1'}), support=0.2, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1'}), items_add=frozenset({'x3'}), confidence=0.6666666666666667, lift=1.1111111111111114), OrderedStatistic(items_base=frozenset({'x4', 'x3'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x1'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1'}), items_add=frozenset({'x6'}), confidence=0.33333333333333337, lift=1.6666666666666667), OrderedStatistic(items_base=frozenset({'x6', 'x1'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x2'}), items_add=frozenset({'x6'}), confidence=0.33333333333333337, lift=1.6666666666666667), OrderedStatistic(items_base=frozenset({'x6', 'x2'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "RelationRecord(items=frozenset({'x4', 'x3', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x3', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1', 'x2'}), items_add=frozenset({'x6'}), confidence=0.5, lift=2.5), OrderedStatistic(items_base=frozenset({'x6', 'x1', 'x2'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0), OrderedStatistic(items_base=frozenset({'x6', 'x4', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x6', 'x4', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n" ] } ], "source": [ "for item in transactions_rules:\n", " print(item) " ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RelationRecord(items=frozenset({'x1'}), support=0.8, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x1'}), confidence=0.8, lift=1.0)])\n", "['x1']\n", "RelationRecord(items=frozenset({'x2'}), support=0.7, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x2'}), confidence=0.7, lift=1.0)])\n", "['x2']\n", "RelationRecord(items=frozenset({'x3'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x3'}), confidence=0.6, lift=1.0)])\n", "['x3']\n", "RelationRecord(items=frozenset({'x4'}), support=0.5, ordered_statistics=[OrderedStatistic(items_base=frozenset(), items_add=frozenset({'x4'}), confidence=0.5, lift=1.0)])\n", "['x4']\n", "RelationRecord(items=frozenset({'x1', 'x2'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1'}), items_add=frozenset({'x2'}), confidence=0.7499999999999999, lift=1.0714285714285714), OrderedStatistic(items_base=frozenset({'x2'}), items_add=frozenset({'x1'}), confidence=0.8571428571428572, lift=1.0714285714285714)])\n", "['x1', 'x2']\n", "RelationRecord(items=frozenset({'x3', 'x1'}), support=0.6, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1'}), items_add=frozenset({'x3'}), confidence=0.7499999999999999, lift=1.2499999999999998), OrderedStatistic(items_base=frozenset({'x3'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x3', 'x1']\n", "RelationRecord(items=frozenset({'x5', 'x1'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x5', 'x1']\n", "RelationRecord(items=frozenset({'x5', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286)])\n", "['x5', 'x2']\n", "RelationRecord(items=frozenset({'x6', 'x4'}), support=0.2, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4'}), items_add=frozenset({'x6'}), confidence=0.4, lift=2.0), OrderedStatistic(items_base=frozenset({'x6'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "['x6', 'x4']\n", "RelationRecord(items=frozenset({'x3', 'x1', 'x2'}), support=0.4, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x1', 'x2'}), items_add=frozenset({'x3'}), confidence=0.6666666666666667, lift=1.1111111111111114), OrderedStatistic(items_base=frozenset({'x3', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x3', 'x1', 'x2']\n", "RelationRecord(items=frozenset({'x5', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x5', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x5', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x5', 'x1', 'x2']\n", "RelationRecord(items=frozenset({'x6', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x6', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x6', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x6', 'x1', 'x2']\n", "RelationRecord(items=frozenset({'x4', 'x3', 'x1'}), support=0.2, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1'}), items_add=frozenset({'x3'}), confidence=0.6666666666666667, lift=1.1111111111111114), OrderedStatistic(items_base=frozenset({'x4', 'x3'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x4', 'x3', 'x1']\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x1'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1'}), items_add=frozenset({'x6'}), confidence=0.33333333333333337, lift=1.6666666666666667), OrderedStatistic(items_base=frozenset({'x6', 'x1'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "['x6', 'x4', 'x1']\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x2'}), items_add=frozenset({'x6'}), confidence=0.33333333333333337, lift=1.6666666666666667), OrderedStatistic(items_base=frozenset({'x6', 'x2'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0)])\n", "['x6', 'x4', 'x2']\n", "RelationRecord(items=frozenset({'x4', 'x3', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x3', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x4', 'x3', 'x1', 'x2']\n", "RelationRecord(items=frozenset({'x6', 'x4', 'x1', 'x2'}), support=0.1, ordered_statistics=[OrderedStatistic(items_base=frozenset({'x4', 'x1', 'x2'}), items_add=frozenset({'x6'}), confidence=0.5, lift=2.5), OrderedStatistic(items_base=frozenset({'x6', 'x1', 'x2'}), items_add=frozenset({'x4'}), confidence=1.0, lift=2.0), OrderedStatistic(items_base=frozenset({'x6', 'x4', 'x1'}), items_add=frozenset({'x2'}), confidence=1.0, lift=1.4285714285714286), OrderedStatistic(items_base=frozenset({'x6', 'x4', 'x2'}), items_add=frozenset({'x1'}), confidence=1.0, lift=1.25)])\n", "['x6', 'x4', 'x1', 'x2']\n" ] } ], "source": [ "for item in transactions_rules:\n", " pair = item[0] \n", " items = [x for x in pair]\n", " print(item)\n", " print(items)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x1, x2, x3\n", "x1, x3\n", "x2, x4\n", "x1, x2, x3\n", "x1, x2, x5\n", "x1, x2, x3, x4\n", "x4, x6\n", "x1, x2, x4, x6\n", "x1, x3, x4\n", "x1, x2, x3" ] } ], "source": [ "##\n", "## arules lee un archivo en formato CSV.\n", "## Se crea un archivo con los datos del \n", "## problema planteado\n", "##\n", "data <- paste(\n", " \"x1, x2, x3\", \n", " \"x1, x3\",\n", " \"x2, x4\",\n", " \"x1, x2, x3\",\n", " \"x1, x2, x5\",\n", " \"x1, x2, x3, x4\",\n", " \"x4, x6\",\n", " \"x1, x2, x4, x6\",\n", " \"x1, x3, x4\",\n", " \"x1, x2, x3\", \n", " sep=\"\\n\")\n", "\n", "## Se imprime en pantalla para verificar\n", "cat(data)\n", "\n", "## Se escribe el archivo en disco duro\n", "write(data, file = \"data/apriori.csv\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Objetivos de aprendizaje" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Al finalizar este tutorial, usted estará en capacidad de:\n", "\n", "* Explicar que es un conjunto de ítems.\n", "\n", "\n", "* Explicar que es una regla de asociación y cómo se aplica en sistemas de recomendación.\n", "\n", "\n", "* Describir las componentes del algoritmo Apriori.\n", "\n", "\n", "* Explicar los conceptos de *lift*, *support* y *confidence*.\n", "\n", "\n", "* Encontrar a mano las reglas de asociación para un conjunto pequeño de transacciones." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Definición del problema real" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Un problema típico de los retailers es poder recomendar productos afines a sus compradores basados en el histórico general de las ventas. Estas recomendaciones tienen como fin sugerirle al usuario productos que podría haber olvidado y que usualmente se llevan juntos, o nuevos productos sustitutos que reemplazarían productos ya posicionados. Esta recomendación se basa en el histórico general de la tienda (productos que todas las personas usualmente llevan juntos) y no en las preferencias individuales de los clientes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Definición del problema en términos de los datos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para ejemplificar el proceso de construcción de las reglas de inducción, se tiene un conjunto ficticio de 10 transacciones realizadas sobre seis posibles ítems ($x_1, ..., x_6)$, donde cada fila representa una transacción:\n", "\n", "\n", " # Productos\n", " --------------------\n", " 1 x1, x2, x3\n", " 2 x1, x3\n", " 3 x2, x4\n", " 4 x1, x2, x3\n", " 5 x1, x2, x5\n", " 6 x1, x2, x3, x4\n", " 7 x4, x6\n", " 8 x1, x2, x4, x6\n", " 9 x1, x3, x4\n", " 10 x1, x2, x3\n", " \n", "\n", "El problema consiste en derivar un conjunto de reglas de asociación que permita recomenda un grupo de productos a partir de los productos que ya seleccionó el cliente. Por ejemplo, si un cliente compra $x_1$ y $x_3$, ¿qué producto o productos se le deben recomendar?" ] }, { "cell_type": "markdown", "metadata": { "toc-hr-collapsed": false }, "source": [ "## Solución" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transacción" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Una **transacción** se representa a través del conjunto de ítems comprados en ella. Así, una transacción con cuatro ítems se representa como:\n", "\n", "$$\\{x_1, x_2, x_3, x_4 \\}$$\n", "\n", "El problema descrito equivale a determinar los productos $x_i$, con $x_i \\notin \\{x_1, x_2, x_3, x_4 \\}$, con mayor probabilidad de ser comprados sabiendo que el cliente ya seleccionó $x_1$, $x_2$, $x_3$ y $x_4$. Dicho de otra forma, se deben computar las probabilidades condicionales $\\text{Pr}(x_i \\, | \\, x_1, x_2, x_3, x_4)$ y recomendar los $N$ productos $x_i$ con mayor probabilidad condicional de compra. En este problema se asume que SI existe una dependencia entre la compra de un producto y otro; si esta dependencia no existe, no tiene sentido construir el sistema de recomendación." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Regla de asociación" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "De esta forma, el objetivo del sistema de recomendación es construir una **regla de asociación** de la forma:\n", "\n", "$$\\{x_2, x_3, x_4 \\} \\rightarrow x_1$$\n", "\n", "la cual indica que cuando se compran $x_2$, $x_3$ y $x_4$ también se compra (implica) $x_1$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Es posible evaluar todas las posibles reglas por fuerza bruta (enumeración). Para el caso anterior, las reglas podrían ser: $\\{x_2\\} \\rightarrow x_1$, $\\{x_3\\} \\rightarrow x_1$, $\\{x_4\\} \\rightarrow x_1$, $\\{x_1\\} \\rightarrow x_2$, $\\{x_3\\} \\rightarrow x_2$, ..., \n", "$\\{x_2, x_3\\} \\rightarrow x_1$, $...$, $\\{x_1, x_2\\} \\rightarrow x_4$ y así sucesivamente, hasta construir todas las permutaciones posibles. Sin embargo, esta solución resulta imposible en términos prácticos debido a que la cantidad de reglas crece exponencialmente." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "**Ejercicio.--** ¿Cuántas reglas posibles hay para el caso anterior?\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Algoritmo Apriori" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El algoritmo **Apriori** se basa en evaluar solamente las reglas que tienen una frecuencia alta (mayor probabilidad). El algoritmo se basa en la siguiente heurística: para que el conjunto $\\{x_1, x_2\\}$ sea frecuente (que tenga una probabilidad alta), los ítems $x_1$ y $x_2$ deben ser frecuentes; es decir, si $x_1$ o $x_2$ son infrecuentes, su combinación no es evaluada. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para medir la **importancia** de una regla se usa el soporte y la confianza. Si una regla de asocación se escribe como \n", "\n", "$$X \\rightarrow Y$$\n", "\n", "el soporte es la proporción de veces que $X$ aparece respecto al total de transacciones; nótese que acá se está hablando explícitamente de probabilidad. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La **confianza** se define como:\n", "\n", "$$\\text{confidence}(X \\rightarrow Y) = \\frac{\\text{support}(X, Y)}{\\text{support}(X)} $$\n", "\n", "la cual se interpreta como la cantidad de veces en que la presencia de $X$ resulta en la presencia de $Y$. Es decir, ya que se dio $X$ que tan probable es que se de $Y$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "**Actividad.--** Responda la siguiente pregunta: ¿Es verdad que $\\text{confidence}(X \\rightarrow Y) = \\text{confidence}(Y \\rightarrow X)$?\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El algoritmo Apriori opera en dos fases: En la primera fase se identifican todos los conjuntos de ítems que cumplen con el soporte mínimo requerido (o probabilidad mínima de compra). En la segunda fase, con los ítems identificados en la fase uno, se crean reglas que cumplen con la confianza mínima requerida." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En la **primera fase**, se procede de forma constructiva de la siguiente forma (explícitamente se está calculado probabilidad):\n", "\n", "* Se calcula el soporte de cada ítem y se seleccionan aquellos ítems que cumplen con el soporte mínimo requerido.\n", "\n", "\n", "* Se forman todos las conjuntos (combinaciones) de dos ítems. Sólo se consideran combinaciones de dos ítems que contengan ítems que cumplen el soporte mínimo requerido. Se seleccionan aquellas combinaciones de dos ítems que cumplen con el soporte mínimo requerido.\n", "\n", "\n", "* Se forman todos los conjuntos de tres ítems. No se consideran combinaciones que contengan conjuntos no frecuentes de dos ítems. Es decir, si la combinación {$x_1$, $x_4$} no se frecuente (no cumple con el soporte mínimo requerido), entonces no se consideran combinaciones como {$x_1$, $x_3$, $x_4$} o {$x_1$, $x_2$, $x_4$}.\n", "\n", "\n", "* Se continua con las combinaciones de cuatro ítems y se seleccionan aquellas que cumplan con el soporte mínimo requerido. El algoritmo se detiene cuando ya no hay combinaciones de ítems que cumpan con el soporte mínimo." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "**Actividad.--** Calcule el soporte para $x_1$, ..., $x_6$, esto es, la probabilidad de que $x_i$ aparezca en una transacción. Si el soporte mínimo requerido es del 40%, ¿cuáles ítems debe seleccionarse?\n", "\n", " X support seleccionado\n", " --------------------------------\n", " x1 ? ?\n", " x2 7/10 Si\n", " x3 ? ?\n", " x4 ? ?\n", " x5 ? ?\n", " x6 2/10 No\n", "\n", "\n", "**Actividad.--** Cuáles las combinaciones de dos ítems que deben ser consideradas de acuerdo con el resultado del ejercicio anterior? Cúales cumplen con un soporte mínimo del 40%?\n", "\n", " X support seleccionado\n", " -------------------------------------\n", " {x1, x2} 6/10 Si\n", " ? ? ?\n", " ? ? ?\n", " ? ? ?\n", " {x2, x4} 3/10 No\n", " ? ? ?\n", " \n", "\n", "**Actividad.--** Cúales combinaciones de tres ítems pueden considerarse y cuáles cumplen con el soporte mínimo requerido?\n", "\n", " X support seleccionado\n", " ---------------------------------------\n", " {x1, x2, x3} 4/10 Si\n", " {?, ?, ?} ? ?\n", " {?, ?, ?} ? ?\n", "\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En la **segunda fase**, para todas las combinaciones de 2, 3, ... ítems, se generan todas las reglas posibles y se evalúa su confianza. Se seleccionan aquellas que cumplen con la confianza mínima requerida. Si la combinación {$x_1$, $x_2$} cumplio con el soporte mínimo, entonces se consideran las reglas {$x_1$} $\\to$ {$x_2$} y {$x_2$} $\\to$ {$x_1$}. Nótese que es posible considerar reglas con varios elementos en el consecuente como por ejemplo {$x_1$} $\\to$ {$x_2$, $x_3$}." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El *lift* de una regla mide la importancia de una regla en relación a la tasa típica de compra, dado que se sabe que un ítem o un conjunto de ítems han sido comprados.\n", "\n", "$$\\text{lift}(X \\rightarrow Y) = \\frac{\\text{confidence}(X, Y)}{\\text{support}(Y)} $$\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "**Actividad.--** Para todas las combinaciones que cumplen con el soporte mínimo requerido, forme las correspodientes reglas y cómpute la confianza y el lift. Si la confianza mínima es del 70%, ¿cuáles reglas deben ser seleccionadas?\n", "\n", "\n", " Combinación Reglas Confianza Lift Seleccionada\n", " ----------------------------------------------------------------\n", " {x1, x2} {x1} -> {x2} 75% ? Si\n", " {x2} -> {x1} 86% ? ?\n", " ----------------------------------------------------------------\n", " {?, x3} {?} -> {?} ? ? ?\n", " {x3} -> {?} ? ? ?\n", " ----------------------------------------------------------------\n", " {x2, ?} {?} -> {x2} ? ? ?\n", " {?} -> {?} ? ? ?\n", " ----------------------------------------------------------------\n", " {x1, x2, x3} {?} -> {?, ?} ? ? ?\n", " {?} -> {?, ?} ? ? ?\n", " {x3} -> {x1, x2} 67% ? No\n", " {?, x2} -> {?} ? ? ?\n", " {?, ?} -> {x2} ? ? ?\n", " {x2, x1} -> {?} ? ? ?\n", " ----------------------------------------------------------------\n", " \n", "\n", "**Actividad.--** Si un cliente compra $x_1$ y $x_3$, ¿qué producto o productos se le deben recomendar?\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Solución usando el lenguaje R" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A continuación se describen las funcionalidades del paquete `arules` del lenguaje R para la construcción de reglas de asociación." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Preparación" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "## Se instala el paquete\n", "## install.packages(\"arules\")\n", "\n", "## Se carga la librería\n", "library(arules)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Formtao del archivo de datos" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x1, x2, x3\n", "x1, x3\n", "x2, x4\n", "x1, x2, x3\n", "x1, x2, x5\n", "x1, x2, x3, x4\n", "x4, x6\n", "x1, x2, x4, x6\n", "x1, x3, x4\n", "x1, x2, x3" ] } ], "source": [ "##\n", "## arules lee un archivo en formato CSV.\n", "## Se crea un archivo con los datos del \n", "## problema planteado\n", "##\n", "data <- paste(\n", " \"x1, x2, x3\", \n", " \"x1, x3\",\n", " \"x2, x4\",\n", " \"x1, x2, x3\",\n", " \"x1, x2, x5\",\n", " \"x1, x2, x3, x4\",\n", " \"x4, x6\",\n", " \"x1, x2, x4, x6\",\n", " \"x1, x3, x4\",\n", " \"x1, x2, x3\", \n", " sep=\"\\n\")\n", "\n", "## Se imprime en pantalla para verificar\n", "cat(data)\n", "\n", "## Se escribe el archivo en disco duro\n", "write(data, file = \"data/apriori.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Lectura de las transacciones" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "##\n", "## Se leen los datos\n", "##\n", "transactions <- read.transactions(\"data/apriori.csv\", sep = \",\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " items \n", "[1] {x1,x2,x3} \n", "[2] {x1,x3} \n", "[3] {x2,x4} \n", "[4] {x1,x2,x3} \n", "[5] {x1,x2,x5} \n", "[6] {x1,x2,x3,x4}\n", "[7] {x4,x6} \n", "[8] {x1,x2,x4,x6}\n", "[9] {x1,x3,x4} \n", "[10] {x1,x2,x3} \n" ] } ], "source": [ "##\n", "## Se imprimen los items por transacción\n", "##\n", "inspect(transactions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Análisis exploratorio" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "transactions as itemMatrix in sparse format with\n", " 10 rows (elements/itemsets/transactions) and\n", " 6 columns (items) and a density of 0.4833333 \n", "\n", "most frequent items:\n", " x1 x2 x3 x4 x6 (Other) \n", " 8 7 6 5 2 1 \n", "\n", "element (itemset/transaction) length distribution:\n", "sizes\n", "2 3 4 \n", "3 5 2 \n", "\n", " Min. 1st Qu. Median Mean 3rd Qu. Max. \n", " 2.00 2.25 3.00 2.90 3.00 4.00 \n", "\n", "includes extended item information - examples:\n", " labels\n", "1 x1\n", "2 x2\n", "3 x3" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "##\n", "## Se obtiene la información más relevante de los datos:\n", "##\n", "## * Número de transacciones\n", "## * Número total de ítems\n", "## * Número de transacciones por cantidad de ítems (y cuartiles)\n", "##\n", "summary(transactions)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "