Простой код игрового автомата выбирает тот же вариант (выборка Томпсона)

#python #machine-learning

Вопрос:

Попробуйте этот простой код игрового автомата.

 import numpy as np

slotConRates = [.02, .013, .013, .015, .018]
# Number of Tries
N = 10000
# Number of Machines
d = len(slotConRates)

# Add 1 if you get a Win in the Array X
X = np.zeros((N,d))
for i in range(N):
  for j in range(d):
    if np.random.rand() < slotConRates[j]:
      X[i][j] = 1

win_reward = np.zeros(d)
loss_reward = np.zeros(d)

# Taking our best Slot Machine through beta distribution and updating it's loss and wins

for i in range(N):
  selected = 0
  MaxRandom = 0
  for j in range(d):
    randomBeta = np.random.beta(win_reward[j]   1, loss_reward[j]   1)
    if randomBeta > MaxRandom:
      MaxRandom = randomBeta
      selected = j
      if X[i][selected] == 1:
        win_reward[selected]  = 1
      else:
        loss_reward[selected]  = 1
# Showing which slot machine is considered the best
nSelected = win_reward   loss_reward 
for i in range(d):
    print('Machine number '   str(i   1)   ' was selected '   str(nSelected[i])   ' times')
print('Conclusion: Best machine is machine number '   str(np.argmax(nSelected)   1))
 

Тем не менее, он всегда выбирает 1-ю машину для каждой итерации.

 Machine number 1 was selected 10000.0 times
Machine number 2 was selected 1181.0 times
Machine number 3 was selected 1108.0 times
Machine number 4 was selected 640.0 times
Machine number 5 was selected 1314.0 times
Conclusion: Best machine is machine number 1
 

Как мне это исправить? Проблема заключается во втором for цикле. Есть какие-нибудь идеи о том, почему это происходит?

Комментарии:

1. Вы начинаете каждый j цикл с MaxRandom = 0 и, следовательно randomBeta > MaxRandom , всегда True для j == 0 ?

Ответ №1:

Я действительно не понимаю, что вы делаете, но я почему-то думаю, что эта небольшая модификация (изменение отступа последнего if else блока) может быть тем, что вы ищете:

 ...
for i in range(N):
    selected = 0
    MaxRandom = 0
    for j in range(d):
        randomBeta = np.random.beta(win_reward[j]   1, loss_reward[j]   1)
        if randomBeta > MaxRandom:
            MaxRandom = randomBeta
            selected = j
    if X[i][selected] == 1:
        win_reward[selected]  = 1
    else:
        loss_reward[selected]  = 1
...
 

Редактировать:
Типичный результат после корректировки:

 win_reward = array([ 34.,   7.,   3.,  20., 124.])
loss_reward = array([1733.,  656.,  431., 1271., 5721.])
nSelected = array([1767.,  663.,  434., 1291., 5845.])
Machine number 1 was selected 1767.0 times
Machine number 2 was selected 663.0 times
Machine number 3 was selected 434.0 times
Machine number 4 was selected 1291.0 times
Machine number 5 was selected 5845.0 times
Conclusion: Best machine is machine number 5
(Test sum over selections: 10000.0)
 

Полный список, который я использовал:

 import numpy as np

slotConRates = [.02, .013, .013, .015, .018]
N = 10000
d = len(slotConRates)

X = np.zeros((N,d))
for i in range(N):
    for j in range(d):
        if np.random.rand() < slotConRates[j]:
            X[i][j] = 1

win_reward = np.zeros(d)
loss_reward = np.zeros(d)

for i in range(N):
    selected = 0
    MaxRandom = 0
    for j in range(d):
        randomBeta = np.random.beta(win_reward[j]   1, loss_reward[j]   1)
        if randomBeta > MaxRandom:
            MaxRandom = randomBeta
            selected = j
    if X[i][selected] == 1:
        win_reward[selected]  = 1
    else:
        loss_reward[selected]  = 1

nSelected = win_reward   loss_reward 
print(f'{win_reward = }')
print(f'{loss_reward = }')
print(f'{nSelected = }')
for i in range(d):
    print(f'Machine number {i   1} was selected {nSelected[i]} times')
print(f'Conclusion: Best machine is machine number {np.argmax(nSelected)   1}')
print(f'(Test sum over selections: {nSelected.sum()})')
 

Комментарии:

1. Нет. Это не то. Это простая демонстрация для выборки Томпсона, используемая в искусственном интеллекте. Вопрос в целой программе. Вы можете просто скопировать его и запустить, чтобы проверить.

2. @AbhishekRai Хорошо, тогда смотрите мой комментарий выше: 10000 неизбежно для nSelected[0] .

3. @AbhishekRai Кроме того: Если отступ в if else блоке —правильный, то почему строка selected = j , а не просто использовать просто j ?

4. @AbhishekRai Последний комментарий: Если вы посмотрите здесь , где-то после середины, вы найдете код, который очень похож на ваш (начинается с # Implementing Thompson Sampling ). И отступ в if else блоке—, который подсчитывает награды, в значительной степени соответствует моему предложению.

5. Вот и все…Не знаю, почему это не сработало вчера.