コード例 #1
0
def busquedaLocal(data, k, MAX_EVALUACIONES=MAX_EVALUACIONES_GL, w_param=-1):
    """
    @brief Función de busqueda local para hallar un vector de pesos.
    @param data Lista con el conjunto de datos.
    @param k Valor de vecinos que se quieren calcular en KNN.
    @param MAX_EVALUACIONES Número máximo de evaluaciones, por defecto es MAX_EVALUACIONES_GL=15000
    @param w_param Vector de pesos del que se quiere arrancar la búsqueda local. Por defecto el valor es -1, con lo que se toma una solución inicial aleatoria.
    @return Devuelve un vector de pesos.
    """
    #Obtengo las clases de las tuplas
    labels_np = np.array([d[-1] for d in data])
    #Convierto todas las tuplas menos la clase a un numpy array
    data_np = np.array([d[:-1] for d in data])

    #El máximo número de vecinos a explorar es 20 por la dimension
    MAX_VECINOS = 20 * (len(data[0]) - 1)
    vecinos = 0
    evaluaciones = 0

    #Inicializo la solución
    w = primerVector(len(data[0]) - 1) if w_param == -1 else w_param
    posicion_mutacion = 0

    #Inicializo la valoración de la solución
    tc, tr = knn.Valoracion(data_np, data_np, k, np.array(w), labels_np,
                            labels_np, True)
    valoracion_actual = tc + tr

    #Bucle principal
    while evaluaciones < MAX_EVALUACIONES and vecinos < MAX_VECINOS:
        evaluaciones += 1
        vecinos += 1

        #Tomo un vecino con el operador de mutación
        vecino, posicion_mutacion = auxiliar.mutacion(w, posicion_mutacion)
        #Calculo su valoración
        tc, tr = knn.Valoracion(data_np, data_np, k, np.array(vecino),
                                labels_np, labels_np, True)
        valoracion_vecino = tc + tr

        #Si ha mejorado a la solución w entonces la reemplazamos
        if valoracion_vecino > valoracion_actual:
            vecinos = 0
            w = vecino
            valoracion_actual = valoracion_vecino
            posicion_mutacion = 0
        elif posicion_mutacion == len(w):
            posicion_mutacion = 0

    #Devuelve la solución como un numpy array y el número de evaluaciones
    return np.array(w), evaluaciones
コード例 #2
0
def GeneticoEstacionario(data, k, operador_cruce):
    '''
    @brief Algoritmo genético estacionario.
    @param data Conjunto de datos.
    @param k Número de vecinos para el KNN.
    @param operador_cruce Operador de cruce usado.
    @return Devuelve el mejor individuo de la población final.
    '''
    #Se fija el número de padres en función del operador
    num_padres = 0
    if operador_cruce == cruceAritmetico:
        num_padres = 4
    elif operador_cruce == cruceBLX:
        num_padres = 2
    else:
        print("Has pasado un operador de cruce no válido.")
        return (-1)

    #Se toman las tuplas y sus clases
    data_np = np.array([d[:-1] for d in data])
    labels_np = np.array([d[-1] for d in data])

    #Se genera la población inicial de forma aleatoria con sus valoraciones
    poblacion = generaPoblacionInicial(len(data[0][:-1]))
    valoraciones = np.array([
        knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
        for w in poblacion
    ])
    valoraciones = np.sum(valoraciones, axis=1)
    evaluaciones = TAM_POBLACION

    #Bucle principal
    while evaluaciones < MAX_EVALUACIONES:
        #Hijos con el operador aritmetico
        if num_padres == 4:
            padres = [torneoBinario(poblacion, valoraciones) for i in range(4)]
            hijo1 = operador_cruce(poblacion[padres[0]], poblacion[padres[1]])
            hijo2 = operador_cruce(poblacion[padres[2]], poblacion[padres[3]])
        #Hijos con el operador blx
        else:
            padres = [torneoBinario(poblacion, valoraciones) for i in range(2)]
            hijo1 = operador_cruce(poblacion[padres[0]], poblacion[padres[1]])
            hijo2 = operador_cruce(poblacion[padres[0]], poblacion[padres[1]])

        #Se hace la mutación en los dos hijos generados
        for i in range(len(hijo1)):
            if random.randint(1, 1000) <= PROB_MUTACION * 1000:
                hijo1, pos = auxiliar.mutacion(hijo1, i)
        for i in range(len(hijo2)):
            if random.randint(1, 1000) <= PROB_MUTACION * 1000:
                hijo2, pos = auxiliar.mutacion(hijo2, i)

        #Se añaden los dos hijos con sus valoraciones
        poblacion = np.append(poblacion, [hijo1], axis=0)
        tc, tr = knn.Valoracion(data_np, data_np, k, poblacion[-1], labels_np,
                                labels_np, True)
        valoraciones = np.append(valoraciones, tc + tr)
        poblacion = np.append(poblacion, [hijo2], axis=0)
        tc, tr = knn.Valoracion(data_np, data_np, k, poblacion[-1], labels_np,
                                labels_np, True)
        valoraciones = np.append(valoraciones, tc + tr)

        #Se toman los TAM_POBLACION mejores de la población después de añadir a los hijos
        indices_nueva_poblacion = np.argpartition(valoraciones,
                                                  2)[::-1][:TAM_POBLACION]
        poblacion = poblacion[indices_nueva_poblacion]
        valoraciones = valoraciones[indices_nueva_poblacion]
        evaluaciones += 2

    #Se devuelve al mejor de la población
    valoraciones_final = np.array([
        knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
        for w in poblacion
    ])
    valoraciones_final = np.sum(valoraciones_final, axis=1)
    return np.array(poblacion[np.argmax(valoraciones_final)])
コード例 #3
0
def GeneticoGeneracional(data, k, operador_cruce):
    '''
    @brief Algoritmo genético Generacional.
    @param data Conjunto de datos.
    @param k Número de vecinos en el KNN.
    @param operador_cruce Operador usado para cruzar individuos.
    '''
    #Toma las tuplas y sus clases
    data_np = np.array([d[:-1] for d in data])
    labels_np = np.array([d[-1] for d in data])

    #Número de características
    ncar = len(data[0][:-1])

    #Inicializa la población
    poblacion = generaPoblacionInicial(ncar)

    #Número de mutaciones prefijado
    mutaciones = int(PROB_MUTACION * TAM_POBLACION * ncar)

    #Número de parejas a tomar
    num_parejas = int(TAM_POBLACION * PROB_CRUCE_AGG)

    evaluaciones = TAM_POBLACION

    #Calcula las valoraciones y al mejor de la población
    valoraciones = np.array([
        knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
        for w in poblacion
    ])
    valoraciones = np.sum(valoraciones, axis=1)
    mejor_solucion_ind = np.argmax(valoraciones)
    mejor_solucion_valor = valoraciones[mejor_solucion_ind]
    mejor_solucion = poblacion[mejor_solucion_ind]

    #Bucle principal
    while evaluaciones < MAX_EVALUACIONES:
        hijos = []
        #Para cada pareja se hace el cruce
        for i in range(num_parejas):
            if operador_cruce == cruceAritmetico:
                padres = [
                    torneoBinario(poblacion, valoraciones) for i in range(4)
                ]
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))
                hijos.append(
                    operador_cruce(poblacion[padres[2]], poblacion[padres[3]]))
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[2]]))
                hijos.append(
                    operador_cruce(poblacion[padres[1]], poblacion[padres[2]]))
            else:
                padres = [
                    torneoBinario(poblacion, valoraciones) for i in range(2)
                ]
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))

        #Se mutan los hijos
        for i in range(mutaciones):
            cr = random.randint(0, len(hijos) - 1)
            gen = random.randint(0, ncar - 1)
            hijos[cr], pos = auxiliar.mutacion(hijos[cr], gen)

        #Se rellena la población de hijos con un torneo binario
        for i in range(len(hijos), TAM_POBLACION):
            hijos.append(poblacion[torneoBinario(poblacion, valoraciones)])

        poblacion = np.array(hijos)

        #Se recalculan las valoraciones
        valoraciones = np.array([
            knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
            for w in poblacion
        ])
        valoraciones = np.sum(valoraciones, axis=1)
        evaluaciones += TAM_POBLACION

        #Se comprueba si la peor solución de esta población es mejor que el mejor de la anterior, si no es asi se reemplaza
        peor_solucion_ind = np.argmin(valoraciones)
        peor_solucion_valor = valoraciones[peor_solucion_ind]
        peor_solucion = poblacion[peor_solucion_ind]
        if peor_solucion_valor < mejor_solucion_valor:
            poblacion[peor_solucion_ind] = mejor_solucion
        mejor_solucion_ind = np.argmax(valoraciones)
        mejor_solucion_valor = valoraciones[mejor_solucion_ind]
        mejor_solucion = poblacion[mejor_solucion_ind]

    #Se devuelve al mejor de la población
    return np.array(mejor_solucion)
コード例 #4
0
def EnfriamientoSimulado(data, k, MAX_EVALS=15000):
    '''
    @brief Función que implementa el algoritmo de enfriamiento simulado
    @param data Conjunto de datos
    @param k Constante que se emplea en la valoración para el KNN
    @param MAX_EVALS Número máximo de evaluaciones, por defecto es 15000
    @return Devuelve una solución de APC
    '''
    #Se toman las tuplas y sus clases
    data_np = np.array([d[:-1] for d in data])
    labels_np = np.array([d[-1] for d in data])

    #Número de características
    ncar = len(data_np[0])

    #Solución inicial
    sol = np.random.uniform(0, 1, ncar)
    mejor_sol = np.copy(sol)
    valoracion = knn.Valoracion(data_np, data_np, k, sol, labels_np, labels_np,
                                True, True)
    valoracion_mejor_sol = valoracion

    #Temperatura inicial. Probablemente mal (reemplazar por 100-valoracion)
    T0 = (MU * (valoracion)) / (-np.log(PHI))

    #Temperatura final
    #Si la temperatura inicial es menor que la inicial entonces bajamos la temperatura final
    TF = 1e-03 if 1e-03 > T0 else T0 - 1e-03

    #Número de enfriamientos, máximos vecinos y máximos éxitos
    max_vecinos = 10.0 * ncar
    K = 1
    M = MAX_EVALS / max_vecinos
    max_exitos = 0.1 * max_vecinos

    #Beta
    beta = (T0 - TF) / (M * T0 * TF)

    #Inicializa la temperatura y evaluaciones
    t = T0
    evaluaciones = 1

    #Bucle principal
    while t > TF and evaluaciones < MAX_EVALS:
        #Inicializo el número de vecinos considerados
        vecinos = 0
        #Booleano que indica si el vecino ha sido aceptado como solución
        aceptados = 0
        #Mientras que no se acepte la solución y no se halla considerado el máximo número de vecinos
        while aceptados < max_exitos and vecinos < max_vecinos:
            vecinos += 1
            evaluaciones += 1

            #Se obtiene el vecino y se ignora pos_nueva
            vecino, pos_nueva = auxiliar.mutacion(
                sol, np.random.randint(0, ncar - 1))
            valoracion_vecino = knn.Valoracion(data_np, data_np, k, vecino,
                                               labels_np, labels_np, True,
                                               True)

            #Diferencia entre las valoraciones
            delta = valoracion - valoracion_vecino

            #Si la solución es mejor o un valor aleatorio cumple la condicion
            if delta < 0 or np.random.uniform(0, 1) < np.exp(-delta / (t * K)):
                #Aceptamos la solución
                sol = vecino
                valoracion = valoracion_vecino
                aceptados += 1

                #Actualizamos la mejor solución si es necesario
                if valoracion_mejor_sol < valoracion:
                    mejor_sol = np.copy(sol)
                    valoracion_mejor_sol = valoracion
        #Disminuyo la temperatura
        t = enfriamiento(t, beta)
        K += 1

    return np.array(sol)
コード例 #5
0
def Memetico(data, k, operador_cruce, nGeneraciones, prob_bl, mejores=False):
    '''
    @brief Algoritmo memético.
    @param data Conjunto de datos.
    @param k Número de vecinos para el KNN.
    @param operador_cruce Operador de cruce usado.
    @param nGeneraciones Número de generaciones en las que se ejecutará la búsqueda local.
    @param prob_bl Porcentaje de individuos a los que se aplica la búsqueda local.
    @param mejores Booleano que indica si aplicamos la búsqueda local sobre los mejores individuos de la población.
    @return Devuelve al mejor individuo de la población final.
    '''
    #Toma las tuplas y sus clases
    data_np = np.array([d[:-1] for d in data])
    labels_np = np.array([d[-1] for d in data])
    ncar = len(data[0][:-1])

    #Genera la población inicial
    poblacion = geneticos.generaPoblacionInicial(ncar, TAM_POBLACION)

    #Número de mutaciones prefijado
    mutaciones = int(PROB_MUTACION * TAM_POBLACION * ncar)

    #Número de parejas
    num_parejas = int(TAM_POBLACION * PROB_CRUCE_AGG)

    evaluaciones = TAM_POBLACION

    #Actualiza las valoraciones y la mejor solución
    valoraciones = np.array([
        knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
        for w in poblacion
    ])
    valoraciones = np.sum(valoraciones, axis=1)
    mejor_solucion_ind = np.argmax(valoraciones)
    mejor_solucion_valor = valoraciones[mejor_solucion_ind]
    mejor_solucion = poblacion[mejor_solucion_ind]
    contador_generaciones = 1

    #Bucle principal
    while evaluaciones < MAX_EVALUACIONES:

        #Cada nGeneraciones
        if contador_generaciones % nGeneraciones == 0:
            n_elem_bl = int(prob_bl * TAM_POBLACION)
            individuos = []

            #Aplicamos BL a una muestra aleatoria de n_elem_bl elementos
            if not mejores:
                individuos = random.sample(range(TAM_POBLACION), n_elem_bl)
            #Le aplicamos la BL a los n_elem_bl mejores de la población
            else:
                individuos = valoraciones.argsort()[-n_elem_bl:][::-1]
            for ind in individuos:
                poblacion[ind], ev = busqueda_local.busquedaLocal(
                    data, k, 2 * len(data_np[0]))
                evaluaciones += ev

            #Actualiza las valoraciones
            valoraciones = np.array([
                knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np,
                               True) for w in poblacion
            ])
            valoraciones = np.sum(valoraciones, axis=1)
            evaluaciones += TAM_POBLACION

        contador_generaciones += 1
        hijos = []

        #Genera los hijos
        for i in range(num_parejas):
            if operador_cruce == geneticos.cruceAritmetico:
                padres = [
                    geneticos.torneoBinario(poblacion, valoraciones,
                                            TAM_POBLACION) for i in range(4)
                ]
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))
                hijos.append(
                    operador_cruce(poblacion[padres[2]], poblacion[padres[3]]))
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[2]]))
                hijos.append(
                    operador_cruce(poblacion[padres[1]], poblacion[padres[2]]))
            else:
                padres = [
                    geneticos.torneoBinario(poblacion, valoraciones,
                                            TAM_POBLACION) for i in range(2)
                ]
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))
                hijos.append(
                    operador_cruce(poblacion[padres[0]], poblacion[padres[1]]))

        #Muta los hijos
        for i in range(mutaciones):
            cr = random.randint(0, len(hijos) - 1)
            gen = random.randint(0, ncar - 1)
            hijos[cr], pos = auxiliar.mutacion(hijos[cr], gen)

        #Rellena la población de hijos con un torneo binario
        for i in range(len(hijos), TAM_POBLACION):
            hijos.append(poblacion[geneticos.torneoBinario(
                poblacion, valoraciones, TAM_POBLACION)])

        poblacion = np.array(hijos)

        #Actualiza las valoraciones y comprueba si la peor solución de esta población es peor que la mejor de la anterior
        valoraciones = np.array([
            knn.Valoracion(data_np, data_np, k, w, labels_np, labels_np, True)
            for w in poblacion
        ])
        valoraciones = np.sum(valoraciones, axis=1)
        evaluaciones += TAM_POBLACION
        peor_solucion_ind = np.argmin(valoraciones)
        peor_solucion_valor = valoraciones[peor_solucion_ind]
        peor_solucion = poblacion[peor_solucion_ind]
        if peor_solucion_valor < mejor_solucion_valor:
            poblacion[peor_solucion_ind] = mejor_solucion
        mejor_solucion_ind = np.argmax(valoraciones)
        mejor_solucion_valor = valoraciones[mejor_solucion_ind]
        mejor_solucion = poblacion[mejor_solucion_ind]

    #Devuelve la mejor solución
    return np.array(mejor_solucion)