• Saltar al contenido principal
  • Skip to secondary menu
  • Saltar a la barra lateral principal
  • Saltar al pie de página
  • Inicio
  • Secciones
    • Ciencia de datos
    • Criptografía
    • Herramientas
    • Machine Learning
    • Noticias
    • Opinión
    • Productividad
    • Programación
      • JavaScript
      • Julia
      • Matlab
      • Python
      • R
  • Programación
    • JavaScript
    • Julia
    • Matlab
    • Python
    • R
  • Laboratorio
    • Encuestas: Tamaño de Muestra
    • Lotería: Probabilidad de Ganar
    • Reparto de Escaños (D’Hondt)
    • Tres en Raya con IA
  • Noticias
  • Boletín
  • Contacto
  • Tienda
    • Libros
    • Equipamiento de oficina
    • Equipamiento en movilidad
    • Tiendas afiliadas
      • AliExpress
      • Amazon
      • Banggood
      • GeekBuying
      • Lenovo

Analytics Lane

Ciencia e ingeniería de datos aplicada

  • Ciencia de datos
  • Machine Learning
  • IA Generativa
  • Python
  • Pandas
  • NumPy
  • Excel
  • Matlab

CP-UCB para un problema Bandido Multibrazo (Multi-Armed Bandit)

junio 4, 2021 Por Daniel Rodríguez Deja un comentario
Tiempo de lectura: 4 minutos

La familia de algoritmos UCB es una de las que mejores resultados producen a la hora de enfrentarse a problemas tipo bandido multibrazo. En la que en bandido se selecciona teniendo en cuenta el intervalo de confianza de la recompensa empírica. Así no se selecciona el bandido cuya recompensa observada sea la mayor, sino aquel en el que estadísticamente se puede esperar el máximo valor para un nivel de confianza dado sea el mayor. Permitiendo explorar de este modo los estados con un nivel de incertidumbre elevado y explotar aquellos con mayor esperanza. Entre esta familia de algoritmos se encuentra el UCB de Clopper-Pearson (CP-UCB) en el cual se asume que la recompensa se genera mediante una distribución binomial.

CP-UCB

El algoritmo CP-UCB propone asumir que las recompensas obtenidas provienen de una distribución binomial. Así, a partir de los datos empíricos, se puede calcular para cada uno de los bandidos su intervalo de confianza para un nivel de significancia dada. Nivel de significación que se reducirá a medida que aumente el número de muestras.

X_{CP-UCB} = U^{CP} \left(R_j, n_j, \frac{1}{N \ln{N}^c} \right)

En donde U^{CP} es la función que nos calcular el intervalo de confianza de una distribución binomial, R_j las recompensas totales observadas en en bandido j, n_j las veces que se ha jugado con el bandido j, N el número de veces totales que se ha jugado y c un parámetro que se puede seleccionar para cambiar la velocidad de aprendizaje.

Curiosidad: La maldición de la dimensionalidad, o por qué añadir más datos puede empeorar tu modelo
En Analytics Lane
Curiosidad: La maldición de la dimensionalidad, o por qué añadir más datos puede empeorar tu modelo

Publicidad


Implementación en Python de CP-UCB

Para implementar CP-UCB necesitamos una función con la que se puede calcular el intervalo de confianza de una distribución binomial. Una función como proportion_confint la cual se puede encontrar en el paquete statsmodels.

Una vez que tenemos la función con la que calcular el intervalo de confianza, como en ocasiones anteriores, nos podemos basar en la clase Epsilon implementada en la entrada de valores iniciales optimistas. Para ello solamente hay que crear una clase hija con el siguiente código.

from statsmodels.stats.proportion import proportion_confint

class CPUCB(Epsilon):
    def __init__(self, bandits, c=1, method='beta'):
        self.bandits = bandits
        self.c = c
        self.method = method
        
        self.reset()
        
    def run(self, episodes=1):
        for i in range(episodes):
            # Selección del bandido
            bandit = self.select()
            
            # Obtención de una nueva recompensa
            reward = bandits[bandit].pull()
            
            # Agregación de la recompensa al listado
            self._rewards.append(reward)
            
            # Actualización de la media
            self._plays[bandit] += 1
            self._mean[bandit] = (1 - 1.0/self._plays[bandit]) * self._mean[bandit] \
                                 + 1.0/self._plays[bandit] * reward
            self._reward[bandit] += reward
        
        return self.average_reward()
    
    
    def select(self):
        num_bandits = len(self.bandits)
        total = len(self._rewards)
        
        if total < num_bandits:
            bandit = total
        else:
            ucb = [0] * num_bandits
                
            for i in range(num_bandits):
                confidence = 1 / (total * np.log(total) ** self.c)
                ucb[i] = proportion_confint(self._reward[i], self._plays[i], confidence, method=self.method)[1]            
            
            max_bandits = np.where(ucb == np.max(ucb))[0]
            bandit = np.random.choice(max_bandits)
            
        return bandit
    
    
    def reset(self, initial=None):
        self._rewards = []
        self._plays = [0] * len(self.bandits)
        self._mean = [0] * len(self.bandits)
        self._reward = [0] * len(self.bandits)

En este caso ha sido necesario cambiar el método run() ya que, además de los valores usados anteriormente, es necesario guardar también la recompensa obtenida. Valor que se guarda en la propiedad privada _reward. Por otro lado, también se ha modificado el método select(), usando la función proportion_confint para calcular el valor usado para seleccionar el bandido. Finalmente, en el método reset() de la clase hay que agregar la inicialización de la propiedad _reward.

Evaluación de los resultados de CP-UCB

Una vez implementado el algoritmo se puede ver cómo funciona este en comparación con UCB1. Para lo que se puede usar los bandidos basados en la distribución binomial de las entradas anteriores. Así, se puede usar el siguiente código para evaluar ambos algoritmos.

np.random.seed(0)

bandits = [Bandit(0.02), Bandit(0.06), Bandit(0.10)]

cpucb = CPUCB(bandits)
ucb1 = UCB1(bandits)

cpucb.run(200000)
ucb1.run(200000)

cpucb.plot(True, label='CPUCB')
ucb1.plot(True, True, label='UCB1')
plt.legend()

print(cpucb._plays)
print(ucb1._plays)

Obteniendo como resultado la siguiente figura.

Evolución de la recompensa promedio con el numero de tiradas para el algoritmo CP-UCB y UCB1 con tres bandidos basados en una distribución binomial
Evolución de la recompensa promedio con el numero de tiradas para el algoritmo CP-UCB y UCB1 con tres bandidos basados en una distribución binomial

Lo primero que se puede ver en esta gráfica es que CP-UCB converge mucho más rápido hacia la recompensa óptima que UCB1. Algo que queda de manifiesto al comprobar que solamente ha jugado con el primer y segundo bandido 169 y 1263 veces respectivamente. Sumando ambas menos que las veces que UCB1 ha jugado con el primer bandido (3089). Lo que se traduce en haber seleccionado muchas más veces el bandido óptimo.

Este resultado tiene un precio. El uso de la función proportion_confint en cada una de las selecciones hace que este algoritmo sea uno de los más lentos, tardando 10 veces más que UCB2, UCB1-Tuned o UCB1-Normal.

En este caso el resultado es en cierta medida el esperado, ya que el bandido usa una distribución binomial para generar la recompensa. Por lo que el algoritmo se adapta perfectamente al problema.

Publicidad


Conclusiones

En esta entrada hemos visto otro algoritmo de la familia UCB en el que se asume que las recompensas de los bandidos proceden de una distribución binomial. Por lo que los resultados obtenidos en los bandidos de prueba han sido de los mejores. Algo que también tiene un coste, el cálculo de intervalo de confianza es más costosos que otros algoritmos de la familia, por lo que usar este se traduce en la necesidad de más tiempo para tomar las decisiones. Lo que puede ser un problema en algunas situaciones.

Imagen de Paul Edney en Pixabay

¿Te ha parecido de utilidad el contenido?

¡Puntúalo entre una y cinco estrellas!

Puntuación promedio 0 / 5. Votos emitidos: 0

Ya que has encontrado útil este contenido...

¡Síguenos en redes sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?

Publicaciones relacionadas

  • Curiosidad: La maldición de la dimensionalidad, o por qué añadir más datos puede empeorar tu modelo
  • ¿Está concentrado el MSCI World? Un análisis con Gini, Lorenz y leyes de potencia
  • Curiosidad: ¿Por qué usamos p < 0.05? Un umbral que cambió la historia de la ciencia
  • Programador de tareas de Windows: Guía definitiva para automatizar tu trabajo (BAT, PowerShell y Python)
  • La Paradoja del Cumpleaños, o por qué no es tan raro compartir fecha de nacimiento
  • Cómo abrir una ventana de Chrome con tamaño y posición específicos desde la línea de comandos en Windows
  • Curiosidad: El sesgo de supervivencia, o por qué prestar atención sólo a los que “llegaron” puede engañarte
  • Documentar tu API de Express con TypeScript usando OpenAPI (Swagger)
  • Data Lake y Data Warehouse: diferencias, usos y cómo se complementan en la era del dato

Publicado en: Ciencia de datos Etiquetado como: Aprendizaje por refuerzo, Machine learning, Multi-Armed Bandit

Interacciones con los lectores

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

I accept the Terms and Conditions and the Privacy Policy

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Barra lateral principal

Suscríbete a nuestro boletín

Suscríbete al boletín semanal para estar al día de todas las publicaciones.

Política de Privacidad

Analytics Lane en redes sociales

  • Amazon
  • Bluesky
  • Facebook
  • GitHub
  • Instagram
  • Mastodon
  • Pinterest
  • RSS
  • Telegram
  • Tumblr
  • Twitter
  • YouTube

Publicidad

Entradas recientes

Data Lake y Data Warehouse: diferencias, usos y cómo se complementan en la era del dato

octubre 23, 2025 Por Daniel Rodríguez

Documentar tu API de Express con TypeScript usando OpenAPI (Swagger)

octubre 21, 2025 Por Daniel Rodríguez

Curiosidad: El sesgo de supervivencia, o por qué prestar atención sólo a los que “llegaron” puede engañarte

octubre 16, 2025 Por Daniel Rodríguez

Publicidad

Es tendencia

  • Procesadores cuánticos en Machine Learning e Inteligencia Artificial Procesadores cuánticos en Machine Learning e Inteligencia Artificial: Transformando el futuro de la tecnología publicado el febrero 12, 2025 | en Ciencia de datos, Criptografía, Opinión
  • Gráficos de barras en Matplotlib publicado el julio 5, 2022 | en Python
  • Método del codo (Elbow method) para seleccionar el número óptimo de clústeres en K-means publicado el junio 9, 2023 | en Ciencia de datos
  • Hoja de cálculo para repartir los escaños en base al método D’Hont Aplicar el método D’Hondt en Excel publicado el abril 14, 2021 | en Herramientas
  • El método de Muller e implementación en Python publicado el marzo 24, 2023 | en Ciencia de datos

Publicidad

Lo mejor valorado

4.9 (24)

Seleccionar filas y columnas en Pandas con iloc y loc

4.6 (16)

Archivos JSON con Python: lectura y escritura

4.4 (14)

Ordenación de diccionarios en Python mediante clave o valor

4.7 (13)

Operaciones de filtrado de DataFrame con Pandas en base a los valores de las columnas

4.5 (10)

Diferencias entre var y let en JavaScript

Publicidad

Comentarios recientes

  • Daniel Rodríguez en Probabilidad básica: cómo entender el azar en nuestra vida diaria
  • Pepe en Probabilidad básica: cómo entender el azar en nuestra vida diaria
  • CARLOS ARETURO BELLO CACERES en Justicio: La herramienta gratuita de IA para consultas legales
  • Piera en Ecuaciones multilínea en Markdown
  • Daniel Rodríguez en Tutorial de Mypy para Principiantes

Publicidad


Footer

Analytics Lane

  • Acerca de Analytics Lane
  • Boletín de noticias
  • Contacto
  • Libros
  • Lo más popular
  • Noticias
  • Tienda
  • Tiendas afiliadas

Secciones

  • Ciencia de datos
  • Criptografía
  • Herramientas
  • Machine Learning
  • Opinión
  • Productividad
  • Programación
  • Reseñas

Sobre de Analytics Lane

En Analytics Lane tratamos de explicar los principales conceptos de la ciencia e ingeniería de datos con un enfoque práctico. Los principales temas tratados son ciencia de datos, ingeniería de datos, inteligencia artificial, machine learning, deep learning y criptografía. Además, también se habla de los principales lenguajes de programación y herramientas utilizadas por los científicos e ingenieros de datos.

Copyright © 2018-2025 Analytics Lane ·Términos y condiciones ·Política de Cookies ·Política de Privacidad ·Herramientas de privacidad ·Contacto