[PYTHON] Mehrarmiges Banditenproblem

einpacken

Ich habe versucht, das mehrarmige Banditenproblem mit Thompson Sampling zu lösen.

Was ist das Problem der mehrarmigen Banditen?

(Im Fall von Bernoulli Bandit) Es gibt mehrere Spielautomaten, und wenn Sie sie spielen, erhalten Sie Treffer und Fehler. Die Gewinnwahrscheinlichkeit ist für jeden Slot unterschiedlich, der Wert ist jedoch unbekannt. Zu diesem Zeitpunkt möchte ich mit der festgelegten Anzahl von Spielen viel gewinnen.

Dies nennt man Bernoulli Bandit Die diskrete Verteilung mit der Wahrscheinlichkeit p von 1 und p-1 von 0 ist [Bernouy-Verteilung](https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%AB%E3%83%8C % E3% 83% BC% E3% 82% A4% E5% 88% 86% E5% B8% 83) Deshalb.

Als ein zu lösendes Bild,

Was ist Thompson Sampling?

Einer der Algorithmen zur Lösung des Problems der mehrarmigen Banditen.

Die Beta-Verteilung hier ist, dass, wenn die Wahrscheinlichkeitsverteilung die Bernoulli-Verteilung wie diese ist, Wenn die vorherige Verteilung die Beta-Verteilung ist, ist die hintere Wahrscheinlichkeit auch die Beta-Verteilung. Es scheint, dass es sich um eine konjugierte vorherige Verteilung handelt [2]

Ich habe es so implementiert.

self.results braucht nur Sat und Fat, aber ich behalte es, weil ich es später verwenden kann.

import scipy
import scipy.stats
import numpy.random
import collections
import pprint


# Banding machine simulator.
def getResult(prob):
    return scipy.stats.bernoulli.rvs(prob, size=1)[0]

# Multiarm Bandit Problem solver using Thompson Sampling.
class BernoulliBandit:
    def __init__ (self, numBandits):
        self.numBandits = numBandits
        self.results = dict([(i, []) for i in range(self.numBandits)])
        
    def getBandit(self):
        posteriors = []
        for b in range(self.numBandits):
            Sat = len([r for r in self.results[b] if r == 1])
            Fat = len([r for r in self.results[b] if r == 0])    
            posteriors.append(numpy.random.beta(Sat+1, Fat+1))
        return numpy.array(posteriors).argmax()
    
    def feed(self, selectedBandit, result):
        self.results[selectedBandit].append(result)
        
    def __str__(self):
        out = ""
        for b in range(self.numBandits):
            Sat = len([r for r in self.results[b] if r == 1])
            Fat = len([r for r in self.results[b] if r == 0])    
            out += "Bandit[%d]   Fails: %4d\t  Successes: %6d\n" % (b, Sat, Fat)
        return out

if __name__ == "__main__":
    # set parameters
    numBandits = 3
    numTrials = 5000
    rewards = [0.9, 0.9, 0.4]   # expected rewards (hidden)

    bandit = BernoulliBandit(numBandits)
    for t in range(numTrials):
        if t % 100 == 0:
            print t,
        b = bandit.getBandit()
        r = getResult(rewards[b])
        bandit.feed(b, r)
    print
    print bandit
    print "Rewards", rewards

Das Ausführungsergebnis ist wie folgt. Ich habe die wahren Belohnungserwartungen nicht erfüllt. Was ist eine naive Implementierung wie diese? Oder ist es ein Fehler bei der Implementierung?

0 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 4100 4200 4300 4400 4500 4600 4700 4800 4900
Bandit[0]   Fails:  250	  Successes:     40
Bandit[1]   Fails: 4261	  Successes:    446
Bandit[2]   Fails:    0	  Successes:      3

Rewards [0.9, 0.9, 0.4]

jupyter gist

Verweise

  1. http://ibisml.org/archive/ibis2014/ibis2014_bandit.pdf
  2. http://jmlr.org/proceedings/papers/v23/agrawal12/agrawal12.pdf

Recommended Posts

Mehrarmiges Banditenproblem
Wahrscheinlichkeitsproblem