一,介紹
學習K-搖臂賭博機的相關算法需要明白兩個概念:探索和利用。
僅探索:將所有嘗試機會平均分給每個搖臂,以各個搖臂的平均吐幣概率作爲獎賞期望。
僅利用:按下目前最優的搖臂,有多個則隨機選取一個。
算法一:ε-貪心算法
基於概率對探索和利用折中:以ε的概率進行探索,以1-ε的概率進行利用,一般如果嘗試次數非常大,可以讓ε隨着嘗試次數增加而減小。
我們用Q(k)表示平均獎賞:
算法二:Softmax算法
此算法假設已知各搖臂平均獎賞,基於Boltzmann分佈選取搖臂:
其中Q(i)爲當前平均獎賞,τ>0稱爲“溫度”。
二,代碼
import random # ε貪心算法 def EGreedy(e=0.9,T=1000): # 構造一個5臂的搖臂機 ArmedBandit = [random.randint(0,100)/100,random.randint(0,100)/100,random.randint(0,100)/100,random.randint(0,100)/100,random.randint(0,100)/100] Q=[0.0,0.0,0.0,0.0,0.0];count=[0,0,0,0,0];select=0;bonus=0;v=0 while T>0: # 開始循環,假設中獎都是1,未中獎爲0 rand = random.randint(0, 100) / 100 # 產生隨機數用於判斷是探索還是利用 r = random.randint(0, 100) / 100 # 產生隨機數判斷是否中獎 v=0 if(rand<e): # 探索 select = select % 5 count[select]+=1 if(r<ArmedBandit[select]): bonus+=1 v=1 Q[select] +=(1/count[select]) * (v-Q[select]) select += 1 else: # 利用 index = Q.index(max(Q)) # 獲取最優的搖臂 count[index] += 1 if (r < ArmedBandit[index]): bonus += 1 v = 1 Q[index] +=(1/count[index]) * (v-Q[index]) T-=1 e-=e/(T+1) return bonus if __name__=="__main__": bonus = EGreedy() print(bonus)
import random import math # Softmax算法 def Softmax(au=1,T=1000): # 構造一個5臂的搖臂機 ArmedBandit = [random.randint(0, 100) / 100, random.randint(0, 100) / 100, random.randint(0, 100) / 100, random.randint(0, 100) / 100, random.randint(0, 100) / 100] # 搖臂初始獎賞, Q = ArmedBandit.copy() count = [100, 100, 100, 100, 100]; #假設初始獎賞是各個搖臂100次計算出來的 bonus = 0 def Boltzmann(au, Q): # 計算Boltzmann分佈 P = [];sum=0.0 for i in range(len(Q)): sum += math.exp(Q[i] / au) for i in range(len(Q)): P.append(math.exp(Q[i]/au)/sum) return P while T>0: p = Boltzmann(au,Q) r=random.randint(0, 10000) / 10000 #產生隨機數獲取搖桿 rand = random.randint(0, 100) / 100 # 產生隨機數用於判斷是否中獎 sum = 0.0;select=0;v=0 for i in range(len(p)): # 獲取選擇的搖桿 sum+=p[i] if(r<sum): select = i break if(rand<ArmedBandit[select]): bonus += 1 v = 1 count[select]+=1 Q[select] += (1 / count[select]) * (v - Q[select]) T-=1 return bonus if __name__=="__main__": bonus = Softmax() print(bonus)