Implementación de Algoritmos de Muestreo en Redes Bayesianas con Python

Clasificado en Matemáticas

Escrito el en español con un tamaño de 3,61 KB

Algoritmos de Inferencia y Muestreo en Redes Bayesianas

A continuación, se presentan diversas implementaciones en Python diseñadas para realizar inferencia en redes bayesianas mediante diferentes técnicas de muestreo estocástico.

Ejercicio 1: Orden Compatible (Ordenamiento Topológico)

Esta función permite obtener un orden compatible de las variables, asegurando que cada nodo sea procesado solo después de sus padres.

def orden_compatible(red):
    orden = []
    pendientes = list(variables.keys())
    while pendientes:
        for var in pendientes:
            if all(p in orden for p in padres[var]):
                orden.append(var)
                pendientes.remove(var)
                break
    return orden

Ejercicio 2: Función de Muestreo Básico

Implementación de un método para obtener un valor aleatorio basado en una distribución de probabilidad discreta.

def muestreo(valores, distr):
    r = rd.random()
    acumulado = 0
    for valor, p in zip(valores, distr):
        acumulado += p
        if r < acumulado:
            return valor
    return valores[-1]

Ejercicio 3: Muestreo a Priori

Generación de un evento completo en la red siguiendo el orden topológico definido previamente.

def muestreo_a_priori(red):
    variables, padres, tablas = red
    orden = orden_compatible(red)   # ejercicio 1
    evento = {}
    for var in orden:
        padres_var = padres[var]
        valores_padres = tuple(evento[p] for p in padres_var)
        distr = tablas[var][valores_padres]
        valores_posibles = variables[var]
        evento[var] = muestreo(valores_posibles, distr)
    return evento

Ejercicio 5: Muestreo con Rechazo

Este algoritmo estima la distribución de una variable dada una evidencia observada, descartando aquellas muestras que no coinciden con los datos conocidos.

def muestreo_con_rechazo_bis(var, observado, red, N):
    variables, padres, tablas = red
    acum = {valor: 0 for valor in variables[var]}
    rechazadas = 0   # contador de muestras descartadas
    for _ in range(N):
        muestra = muestreo_a_priori(red)
        if all(muestra[v] == observado[v] for v in observado):
            acum[muestra[var]] += 1
        else:
            rechazadas += 1  
    return normaliza(acum)

Ejercicio 6: Ponderación por Verosimilitud

Técnica avanzada que optimiza el muestreo asignando un peso de verosimilitud a cada muestra en lugar de rechazarlas, mejorando la convergencia en presencia de evidencia.

def muestra_ponderada(red, observado):
    variables, padres, tablas = red
    orden = orden_compatible(red)
    evento = {}
    peso = 1
    for var in orden:
        padres_var = padres[var]
        valores_padres = tuple(evento[p] for p in padres_var)
        distr = tablas[var][valores_padres]
        valores_posibles = variables[var]
        if var in observado:
            valor_observado = observado[var]
            indice = valores_posibles.index(valor_observado)
            peso *= distr[indice]
            evento[var] = valor_observado
        else:
            evento[var] = muestreo(valores_posibles, distr)
    return evento, peso

def ponderacion_por_verosimilitud(var, observado, red, N):
    variables, padres, tablas = red
    acum = {valor: 0 for valor in variables[var]}
    for _ in range(N):
        muestra, peso = muestra_ponderada(red, observado)
        acum[muestra[var]] += peso
    return normaliza(acum)

Entradas relacionadas: