Ideas de modelado matemático de la Copa Shenzhen 2023-Caso_ID3-Algoritmo de clasificación del árbol de decisión

0 Ideas para el concurso

(Compartir en CSDN tan pronto como salgan las preguntas de la competencia)

https://blog.csdn.net/dc_sinor?type=blog

1 Introducción al algoritmo

El nombre completo del algoritmo FP-Tree es el algoritmo FrequentPattern Tree, que es el algoritmo de árbol de patrones frecuentes.Al igual que el algoritmo Apriori, también se usa para extraer conjuntos de elementos frecuentes, pero la diferencia es que el algoritmo FP-Tree es una optimización proceso del algoritmo Apriori Resuelve el Apriori El algoritmo generará una gran cantidad de conjuntos de candidatos en el proceso, mientras que el algoritmo FP-Tree encuentra patrones frecuentes sin generar conjuntos de candidatos. Pero después de extraer los patrones frecuentes, los pasos para generar reglas de asociación siguen siendo los mismos que a priori.

Hay dos algoritmos comunes para extraer conjuntos de elementos frecuentes, uno es el algoritmo Apriori y el otro es el crecimiento de FP. A priori extrae conjuntos de elementos frecuentes mediante la construcción continua de conjuntos de candidatos y la selección de conjuntos de candidatos. Necesita escanear los datos originales varias veces. Cuando los datos originales son grandes, los tiempos de E/S del disco son demasiados y la eficiencia es relativamente baja. FPGrowth es diferente de la estrategia de "sondeo" de Apriori. El algoritmo solo necesita escanear los datos originales dos veces y comprimir los datos originales a través de la estructura de datos del árbol FP, que es más eficiente.

FP significa patrón frecuente, y el algoritmo se divide principalmente en dos pasos: construcción de árboles FP y extracción de conjuntos de elementos frecuentes.

Representación de árbol de 2 FP

El árbol de FP se construye leyendo las transacciones una por una y asignando las transacciones a una ruta en el árbol de FP. Dado que diferentes transacciones pueden tener varios elementos idénticos, sus rutas pueden superponerse parcialmente. Cuanto más se superpongan las rutas entre sí, mejor será el efecto de compresión obtenido al usar la estructura de árbol de FP; si el árbol de FP es lo suficientemente pequeño para almacenarse en la memoria, los conjuntos de elementos frecuentes se pueden extraer directamente de la estructura en la memoria sin tener que escanear repetidamente los datos almacenados en el disco duro.

En la siguiente figura se muestra un árbol de FP:
  inserte la descripción de la imagen aquí
Por lo general, el tamaño del árbol de FP es más pequeño que el de los datos sin comprimir, porque las transacciones de los datos a menudo comparten algunos elementos comunes. En el mejor de los casos, todas las transacciones tienen el mismo conjunto de elementos. , FP El árbol contiene solo una ruta de nodo; cuando cada transacción tiene un conjunto de elementos único, lo que lleva al peor de los casos, dado que las transacciones no contienen elementos comunes, el tamaño del árbol FP es efectivamente el mismo que el tamaño del original datos.

El nodo raíz del árbol FP está representado por φ, y los nodos restantes incluyen un elemento de datos y el soporte del elemento de datos en este camino; cada camino es un conjunto de elementos de datos que cumple con el soporte mínimo en los datos de entrenamiento; el FP El árbol también incluye todos Los mismos elementos están conectados en una lista vinculada, que se representa con una línea azul en la figura anterior.

Para acceder rápidamente al mismo elemento en el árbol, también es necesario mantener una lista de punteros (headTable) que conecta los nodos con el mismo elemento.Cada elemento de la lista incluye: elemento de datos, el soporte mínimo global del elemento y un lista de enlaces que apunta al elemento en el puntero del árbol FP del encabezado.
  inserte la descripción de la imagen aquí

3 Construir árbol FP

Ahora tenga los siguientes datos:

inserte la descripción de la imagen aquí

El algoritmo de crecimiento de FP necesita escanear el conjunto de entrenamiento original dos veces para construir el árbol de FP.

En el primer escaneo, se filtran todos los artículos que no cumplen con el soporte mínimo, para los artículos que cumplen con el soporte mínimo, se ordenan de acuerdo con el soporte mínimo global. ordenados de nuevo según las palabras clave de los elementos.
inserte la descripción de la imagen aquí

El segundo escaneo construye el árbol FP.

Participar en el escaneo son los datos filtrados. Si se encuentra un elemento de datos por primera vez, cree el nodo y agregue un puntero al nodo en la tabla de cabecera; de lo contrario, busque el nodo correspondiente al elemento de acuerdo con la ruta y modifique el nodo. información. El proceso específico es el siguiente:

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
 De lo anterior se puede ver que el headTable no se crea junto con el FPTree, sino que se ha creado en el primer escaneo Al crear el FPTree, solo necesita apuntar el puntero al nodo correspondiente. A partir de la transacción 004, es necesario crear una conexión entre los nodos para que los mismos elementos en diferentes rutas se conecten en una lista enlazada.

4 Código de implementación

def loadSimpDat():
    simpDat = [['r', 'z', 'h', 'j', 'p'],
               ['z', 'y', 'x', 'w', 'v', 'u', 't', 's'],
               ['z'],
               ['r', 'x', 'n', 'o', 's'],
               ['y', 'r', 'x', 'z', 'q', 't', 'p'],
               ['y', 'z', 'x', 'e', 'q', 's', 't', 'm']]
    return simpDat

def createInitSet(dataSet):
    retDict = {
    
    }
    for trans in dataSet:
        fset = frozenset(trans)
        retDict.setdefault(fset, 0)
        retDict[fset] += 1
    return retDict

class treeNode:
    def __init__(self, nameValue, numOccur, parentNode):
        self.name = nameValue
        self.count = numOccur
        self.nodeLink = None
        self.parent = parentNode
        self.children = {
    
    }

    def inc(self, numOccur):
        self.count += numOccur

    def disp(self, ind=1):
        print('   ' * ind, self.name, ' ', self.count)
        for child in self.children.values():
            child.disp(ind + 1)


def createTree(dataSet, minSup=1):
    headerTable = {
    
    }
    #此一次遍历数据集, 记录每个数据项的支持度
    for trans in dataSet:
        for item in trans:
            headerTable[item] = headerTable.get(item, 0) + 1

    #根据最小支持度过滤
    lessThanMinsup = list(filter(lambda k:headerTable[k] < minSup, headerTable.keys()))
    for k in lessThanMinsup: del(headerTable[k])

    freqItemSet = set(headerTable.keys())
    #如果所有数据都不满足最小支持度,返回None, None
    if len(freqItemSet) == 0:
        return None, None

    for k in headerTable:
        headerTable[k] = [headerTable[k], None]

    retTree = treeNode('φ', 1, None)
    #第二次遍历数据集,构建fp-tree
    for tranSet, count in dataSet.items():
        #根据最小支持度处理一条训练样本,key:样本中的一个样例,value:该样例的的全局支持度
        localD = {
    
    }
        for item in tranSet:
            if item in freqItemSet:
                localD[item] = headerTable[item][0]

        if len(localD) > 0:
            #根据全局频繁项对每个事务中的数据进行排序,等价于 order by p[1] desc, p[0] desc
            orderedItems = [v[0] for v in sorted(localD.items(), key=lambda p: (p[1],p[0]), reverse=True)]
            updateTree(orderedItems, retTree, headerTable, count)
    return retTree, headerTable


def updateTree(items, inTree, headerTable, count):
    if items[0] in inTree.children:  # check if orderedItems[0] in retTree.children
        inTree.children[items[0]].inc(count)  # incrament count
    else:  # add items[0] to inTree.children
        inTree.children[items[0]] = treeNode(items[0], count, inTree)
        if headerTable[items[0]][1] == None:  # update header table
            headerTable[items[0]][1] = inTree.children[items[0]]
        else:
            updateHeader(headerTable[items[0]][1], inTree.children[items[0]])

    if len(items) > 1:  # call updateTree() with remaining ordered items
        updateTree(items[1:], inTree.children[items[0]], headerTable, count)


def updateHeader(nodeToTest, targetNode):  # this version does not use recursion
    while (nodeToTest.nodeLink != None):  # Do not use recursion to traverse a linked list!
        nodeToTest = nodeToTest.nodeLink
    nodeToTest.nodeLink = targetNode

simpDat = loadSimpDat()
dictDat = createInitSet(simpDat)
myFPTree,myheader = createTree(dictDat, 3)
myFPTree.disp()

El código anterior no ordena los elementos filtrados de cada dato de entrenamiento después del primer escaneo, pero coloca la clasificación en el segundo escaneo, lo que puede simplificar la complejidad del código.

Información de la consola:

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/dc_sinor/article/details/131868085
Recomendado
Clasificación