深圳大学人工智能概述_实验三(多臂老虎机)

问题描述

你进了一家赌场,假设面前有K台老虎机(arms)。我们知道,老虎机本质上就是 个运气游戏,我们假设每台老虎机i都有一定概率p_{i}吐出一块钱,或者不吐钱( 概 率1-p_{i})。假设你手上只有 T枚代币(tokens),而每摇一次老虎机都需要花费 一枚代币,也就是说你一共只能摇T次,那么如何做才能使得期望回报(expected reward)最大呢?

不同解决思路

设置相关变量

贪心

思路:每次都选择目前估测值最高的老虎机玩,根据玩的结果更新该台老虎机的获奖概率

伪代码:

\epsilon贪心

思路:一些机会用来尝试不同的老虎机(不根据估测概率随机选---探索),根据统计结果估测每台老虎机出奖励的概率(随着尝试次数的增多,估计会越来越准确);另一些机会根据估测直接用在获奖概率最高的老虎机上(利用)

流程图:

伪代码:

softmax

思路:每次都是随机玩(不是等概率随机),但是抽中出奖概率高的老虎机的概率更大

伪代码:

程序设计

由于每台老虎机默认出奖概率设置、返回奖励机制在三种算法下统一。可用类先设计好

老虎机类
  • 属性:台数、每台机器出奖概率(设置为可手动设置也可随机初始)、最优机器概率
  • 方法:按照出奖概率返回奖励(1或0)

ps:

有0.4的概率出奖即,随机生成一个[0,1]的数,小于0.4的概率

小于0.4时返回1;否则返回0               即可实现

class BernoulliBandit():
    def __init__(self, K, probas=None):        #n为摇臂的个数,probas为每个摇臂获得奖励的概率
        assert probas is None or len(probas) == K
        self.K = K
        if probas is None:
            np.random.seed(int(time.time()))
            self.probas = [np.random.random() for _ in range(self.K)]
        else:
            self.probas = probas
            self.best_proba = max(self.probas)
    def generate_reward(self, i):
    # The player selected the i-th machine.
        if np.random.random() < self.probas[i]:
            return 1     #满足发生的概率,就获得奖励1
        else:
            return 0
求解算法有关参数设计

Q_{(i)}:第i台老虎机评估的概率          ------列表即可

count_{(i)}:第i台老虎机玩过的次数     --------列表即可

r:总获奖积分                     ------数即可

R_{k}:第k台老虎机返回的奖励                 ------列表即可

y:平均每步得分(用来衡量算法好坏)               ------列表即可

贪心算法代码
def greedy_strategy(bandit,T,r,Q,count):
        r=0
        y=[]
        for t in range(1,T+1):
            j=np.argmax(Q)
            reward=bandit.generate_reward(j)
            r+=reward
            y.append(r/t)
            Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
            count[j]+=1
        print("累积奖励:",r)
        print("每个摇臂选择次数: ",count)
        print("每个摇臂的估计值: ",Q)
        print("每个摇臂真实获奖的概率: ",bandit.probas)
        return y
\epsilon贪心算法代码
def greedy_e_strategy(bandit,K,T,epsilon,r,Q,count):
        r=0
        y=[]
        for t in range(1,T+1):
            if np.random.random()<epsilon:
                j=np.random.randint(0,K)
            else:
                j=np.argmax(Q)
            reward=bandit.generate_reward(j)
            r+=reward
            y.append(r/t)
            Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
            count[j]+=1
        print("累积奖励:",r)
        print("每个摇臂选择次数: ",count)
        print("每个摇臂的估计值: ",Q)
        print("每个摇臂真实获奖的概率: ",bandit.probas)
        return y
softmax算法代码
def softmax(bandit,K,T,epsilon,Q,r,count):
    r=0
    y=[]
    property_list=np.zeros(K)
    for t in range(1,T+1):
        Probability_accumulation=0
        total_accumulation=sum(pow(e,Q[i]/epsilon) for i in range(K))
        random_value=np.random.random()
        for i in range(K):
            property_list[i]=pow(e,Q[i]/epsilon)/total_accumulation
            Probability_accumulation+=property_list[i]
            if random_value<Probability_accumulation :
                j=i
                break
        reward=bandit.generate_reward(j)
        r+=reward
        y.append(r/t)
        Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
        count[j]+=1
    print("累积奖励:",r)
    print("每个摇臂选择次数: ",count)
    print("每个摇臂的估计值: ",Q)
    print("每个摇臂真实获奖的概率: ",bandit.probas)
    return y

结果查看

  • 可视化平均奖励

随着尝试次数的增加,平均得分趋于稳定,其中贪心(中间)的结果浮动较大。

  • 每台老虎机估测获奖概率与实际获奖概率比较

整体代码

import numpy as np
import time  
import matplotlib.pyplot as plt
e=2.718

class BernoulliBandit():
    def __init__(self, K, probas=None):        #n为摇臂的个数,probas为每个摇臂获得奖励的概率
        assert probas is None or len(probas) == K
        self.K = K
        if probas is None:
            np.random.seed(int(time.time()))
            self.probas = [np.random.random() for _ in range(self.K)]
        else:
            self.probas = probas
            self.best_proba = max(self.probas)
    def generate_reward(self, i):
    # The player selected the i-th machine.
        if np.random.random() < self.probas[i]:
            return 1     #满足发生的概率,就获得奖励1
        else:
            return 0
        
#参数K:摇臂个数,T:试验次数,epsilon:探索概率,r:累积奖励,Q:每个摇臂的估计值,count:每个摇臂的选择次数
def greedy_e_strategy(bandit,K,T,epsilon,r,Q,count):
        r=0
        y=[]
        for t in range(1,T+1):
            if np.random.random()<epsilon:
                j=np.random.randint(0,K)
            else:
                j=np.argmax(Q)
            reward=bandit.generate_reward(j)
            r+=reward
            y.append(r/t)
            Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
            count[j]+=1
        print("\n贪心-ε策略:\n")
        print("累积奖励:",r)
        print("每个摇臂选择次数: ",count)
        print("每个摇臂的估计值: ",Q)
        print("每个摇臂真实获奖的概率: ",bandit.probas)
        return y

def greedy_strategy(bandit,T,r,Q,count):
        r=0
        y=[]
        for t in range(1,T+1):
            j=np.argmax(Q)
            reward=bandit.generate_reward(j)
            r+=reward
            y.append(r/t)
            Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
            count[j]+=1
        print("\n贪心策略:\n")
        print("累积奖励:",r)
        print("每个摇臂选择次数: ",count)
        print("每个摇臂的估计值: ",Q)
        print("每个摇臂真实获奖的概率: ",bandit.probas)
        return y

def softmax(bandit,K,T,epsilon,Q,r,count):
    r=0
    y=[]
    property_list=np.zeros(K)
    for t in range(1,T+1):
        Probability_accumulation=0
        total_accumulation=sum(pow(e,Q[i]/epsilon) for i in range(K))
        random_value=np.random.random()
        for i in range(K):
            property_list[i]=pow(e,Q[i]/epsilon)/total_accumulation
            Probability_accumulation+=property_list[i]
            if random_value<Probability_accumulation :
                j=i
                break
        reward=bandit.generate_reward(j)
        r+=reward
        y.append(r/t)
        Q[j]=(Q[j]*count[j]+reward)/(count[j]+1)
        count[j]+=1
    print("\nsoftmax:\n")
    print("累积奖励:",r)
    print("每个摇臂选择次数: ",count)
    print("每个摇臂的估计值: ",Q)
    print("每个摇臂真实获奖的概率: ",bandit.probas)
    return y

fig,axs=plt.subplots(1,3,figsize=(10,5))
k_=5
T_=4000  
bandit = BernoulliBandit(K=k_)
y_ge=greedy_e_strategy(bandit,K=k_,T=T_,epsilon=0.1,r=0,Q=np.zeros(k_),count=np.zeros(k_))
x=[i for i in range(0,T_+1)]
y_ge=[0]+y_ge
axs[0].plot(x,y_ge)
axs[0].set_xlabel('round')
axs[0].set_ylabel('average reward')
axs[0].set_title('greedy-epsilon strategy')

y_g=greedy_strategy(bandit,T=T_,r=0,Q=np.zeros(k_),count=np.zeros(k_))
x=[i for i in range(0,T_+1)]
y_g=[0]+y_g
axs[1].plot(x,y_g)
axs[1].set_xlabel('round')
axs[1].set_ylabel('average reward')
axs[1].set_title('greedy strategy')

y_sf=softmax(bandit,K=k_,T=T_,epsilon=0.1,r=0,Q=np.zeros(k_),count=np.zeros(k_))
x=[i for i in range(0,T_+1)]
y_sf=[0]+y_sf
axs[2].plot(x,y_sf)
axs[2].set_xlabel('round')
axs[2].set_ylabel('average reward')
axs[2].set_title('softmax strategy')
plt.suptitle("K:%d   T:%d  "%(k_,T_))
plt.show()

想法:

1、在估测每台老虎机出奖概率Q_{i}的初始上,正常全零,会发现贪心浮动很大(时而很好时而很差),由于贪心的本质找到一个好的老虎机后该台评分被拉高,就接着选这台,即使后面没有奖励该台的评分已经超过0了,在贪心算法下它不会再选别的老虎机了。就是哪台第一次出奖励就一路选到底。但是若把Q_{i}设置为全1将大不相同!贪心也被赋予探索能力了,得分很好,本质上是失误多就不选你了。

2、这个问题可以看成多台老虎机也可以看成一个老虎机的多个摇臂。

3、可再定义忏悔值等不同指标去帮助观测算法在此问题上的差异

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值