阅读《强化学习与大模型推荐系统》应具备一定的深度学习和推荐系统技术基础,适合于对大模型和强化学习推荐技术感兴趣的读者学习参考。
《强化学习与大模型推荐系统》全书下载地址:https://github.com/ByShui/Book_RL-LLM-In-RS

强化学习推荐系统:不同的探索策略——玻尔兹曼探索策略、熵正则化探索策略(4.5)

一个优秀的探索策略要能够同时满足探索和利用的需求,以下代码构造了一个具有5个动作的策略评估环境,以此来对不同探索策略的累计遗憾值进行分析:

class Bandit:
    def __init__(self, arm_count):
        self.arm_count = arm_count
        self.generate_arms()

    def generate_arms(self):
        self.arms = []
        for _ in range(self.arm_count):
            mean = np.random.normal(0, 1)
            std_dev = np.random.uniform(0.5, 1.5)
            self.arms.append((mean, std_dev))

    def reward(self, arm):
        mean, std_dev = self.arms[arm]
        return np.random.normal(mean, std_dev)

    def optimal_arm(self):
        return np.argmax([mean for mean, _ in self.arms])

if __name__ == "__main__":
    arm_count = 5
    bandit = Bandit(arm_count)

具体来说,策略评估环境中设置了5个臂,摇动臂的奖励 reward a \text{reward}_a rewarda服从不同的正态分布: reward a = N ( μ , σ ) \text{reward}_a=\mathcal{N}(\mu,\sigma) rewarda=N(μ,σ)其中, μ \mu μ σ \sigma σ分别是正态分布的均值和方差,它们是随机生成的。定义拥有最大均值的动作是最优动作 a ∗ a_* a,最优价值 V ∗ V_* V从最优臂的价值分布中采样得到。

优化策略需要牺牲短期利益,因为需要通过探索搜集更多的信息以获得更优的动作,使得智能体最终能够获得更多回报。探索和利用是强化学习中的一对矛盾体,这意味着在学习过程中,智能体需要在已知和未知的情况下做出最优的决策。

其中,利用是指在已知情况下选择已知最优的策略来获得收益,而探索是指在未知情况下,为了获取更多的信息和收益,选择不同的策略进行尝试。

探索是指在不确定性的环境中,探索新的策略或动作来获得更高的奖励或效用,包含两个部分:一是尝试未知的行为,以期找到更好的策略并更新模型;二是平衡已知和未知的行为,以确保不会错过可能的好策略。

在推荐系统中,探索可以包括推荐新的项目、向用户提供个性化的推荐建议或者探索不同的推荐策略(如多臂机)。探索和利用需要平衡,以确保推荐系统具有长期的优化效果。

一个标准的强化学习算法包括探索和利用两个步骤——探索帮助智能体充分了解其状态空间,利用则帮助智能体找到最优的动作序列。

用来平衡探索和利用的方法包括:贪心探索策略、高斯探索策略、UCB探索策略、玻尔兹曼探索策略、汤普森采样探索策略和熵正则化探索策略等,本篇博客我们介绍一下玻尔兹曼探索策略和熵正则化探索策略。

贪心探索策略请查看:强化学习推荐系统:不同的探索策略——贪心探索策略(4.1)
高斯探索策略请查看:强化学习推荐系统:不同的探索策略——高斯探索策略(4.2)
UCB探索策略请查看:强化学习推荐系统:不同的探索策略——UCB探索策略(4.3)
汤普森采样探索策略请查看:强化学习推荐系统:不同的探索策略——汤普森采样探索策略(4.4)

玻尔兹曼探索策略

前面提到的探索策略在选取动作时都是选取价值最大的动作,也许它确实是最优的,但其他次优动作就一定不可取吗?举个例子,尽管我最喜欢吃草莓,但同时也喜欢吃香蕉和芒果,如果每天都只让我吃草莓,这显然是不符合我的兴趣的。在多臂机问题中,玻尔兹曼探索策略可以同时考虑到多种可能。

首先,玻尔兹曼探索策略将动作的价值转换到玻尔兹曼概率分布空间上,其公式表示为:
P ( a ) = e Q t ( a ) T ∑ i e Q t ( a i ) T P(a)=\frac{\text{e}^{\frac{Q_t(a)}{T}}}{\sum_{i}\text{e}^{\frac{Q_t(a_i)}{T}}} P(a)=ieTQt(ai)eTQt(a)

其中, e \text{e} e是自然常数; T T T是玻尔兹曼分布的温度系数,温度系数越小玻尔兹曼探索策略就越接近贪心策略(选择价值最大的臂),温度系数越大玻尔兹曼探索策略就越接近均匀策略(随机选择臂)。因此,可以说贪心策略是玻尔兹曼探索策略的一种特殊形式。当温度系数 T = 1 T=1 T=1时,玻尔兹曼探索策略又称为SoftMax探索策略。

玻尔兹曼探索策略(SoftMax): a t = arg ⁡ softmax a ∈ A Q t ( a ) a_t=\arg \text{softmax}_{a\in A} Q_t(a) at=argsoftmaxaAQt(a)

贪心策略(Max): a t = arg max ⁡ a ∈ A Q t ( a ) a_t=\argmax_{a\in A}Q_t(a) at=aAargmaxQt(a)

根据公式(3-20)计算出所有动作的概率之后,就可以根据概率分布来采样动作,如下代码实现了玻尔兹曼探索策略:

def softmax(Q, temperature):
    beta_Q = Q / temperature
    exp_Q = np.exp(beta_Q - np.max(beta_Q))
    return exp_Q / exp_Q.sum()

def boltzmann(bandit, T , temperature=1):
    arm_count = bandit.arm_count
    Q = np.zeros(arm_count)
    N = np.zeros(arm_count)

    cumulative_regret = [0]
    for t in range(1, T+1):
        # arm_probs = softmax(Q, temperature)
        arm_prob = scipy.special.softmax(Q)
        arm = np.random.choice(len(Q), p=arm_prob)

        reward = bandit.reward(arm)
        N[arm] += 1
        Q[arm] += (reward - Q[arm]) / N[arm]

        optimal_reward = bandit.reward(bandit.optimal_arm())
        cumulative_regret.append(
            cumulative_regret[-1] + (optimal_reward - reward))

    return cumulative_regret

if __name__ == "__main__":
    arm_count = 5
    T = 1000
    bandit = Bandit(arm_count)

    cumulative_regret_Boltzmann = boltzmann(bandit, T)

以上代码定义了boltzmann()方法,它仅接收两个参数:

  • bandit(一个多臂机实例);
  • T(试验轮次,即在多臂机上探索/利用的轮次)。

在每轮试验中,玻尔兹曼探索策略首先将臂的价值概率,然后根据概率来采样臂作为当前的动作。在推荐系统中,玻尔兹曼探索策略可以实现更平滑及多样化的采样,这对用户体验是有帮助的。

在实际应用玻尔兹曼探索策略时,可能还需要防止极化现象。极化现象指的是随着学习的进行,期望高的动作值越来越高,导致其被采样的概率快速增大,其他动作被采样的概率迅速归零,即策略趋向于“极化”,从而过早地陷入局部最优动作。可以通过加入噪声来防止这种现象发生。

熵正则化探索策略

熵正则化探索策略利用动作空间的熵值来执行探索,它通常与玻尔兹曼探索策略结合使用,在掌握了玻尔兹曼探索策略的原理后,可以很容易地将臂的价值转化为它对应的概率值:
P ( a ) = e Q t ( a ) ∑ a ∈ A e Q t ( a ) P(a)=\frac{\text{e}^{Q_t(a)}}{\sum_{a\in A}\text{e}^{Q_t(a)}} P(a)=aAeQt(a)eQt(a)

上面的是玻尔兹曼探索策略的公式在温度系数T=1时的简化形式。在知道了每一个臂的概率 P ( a ) P(a) P(a)后,就可以利用信息熵计算公式得到动作空间的熵值:
H ( A ) = ∑ a ∈ A P ( a ) log ⁡ P ( a ) H(A)=\sum_{a\in A}P(a)\log P(a) H(A)=aAP(a)logP(a)

熵代表了臂选择的不确定度,当 H ( A ) H(A) H(A)很大时玻尔兹曼探索策略会以均等的概率在动作空间中选择动作;当 H ( A ) H(A) H(A)较小时(下限为0)玻尔兹曼策略会只偏爱动作空间中某一个或少数几个动作。
在这里插入图片描述

在这里插入图片描述

就像上面这种示意图,假设动作空间中有5个臂,则最大熵值1.61意味着各个臂被摇动的概率相等,当熵值减小时就有可能出现右图中臂3的摇动概率显著高于其他臂的情况。

熵损失探索策略将熵值 H ( A ) H(A) H(A)纳入优化目标:

a t = arg max ⁡ a ∈ A ( Q ( a ) + α H ( A ) ) a_t=\argmax_{a\in A}(Q(a)+\alpha H(A)) at=aAargmax(Q(a)+αH(A))

其中, Q ( a ) Q(a) Q(a)是臂 a a a的价值; H ( A ) H(A) H(A)是当前动作空间 A A A的熵值; α \alpha α是超参数,用于调节探索率。这个公式同时最大化熵和臂价值,在获取臂价值的同时保证了所有动作的曝光概率,让策略可以进行更广泛的探索,为策略提供了强健壮性。

如下代码实现了熵正则化探索策略:

def entropy_regularization(bandit, T):
    arm_count = bandit.arm_count
    Q = np.zeros(arm_count)
    N = np.zeros(arm_count)

    cumulative_regret = [0]
    for t in range(1, T+1):
        ent = scipy.stats.entropy(scipy.special.softmax(Q))
        arm_prob = scipy.special.softmax(np.add(Q, 1 * ent))
        arm = np.random.choice(len(Q), p=arm_prob)

        reward = bandit.reward(arm)
        N[arm] += 1
        Q[arm] += (reward - Q[arm]) / N[arm]

        optimal_reward = bandit.reward(bandit.optimal_arm())
        cumulative_regret.append(
            cumulative_regret[-1] + (optimal_reward - reward))

    return cumulative_regret

以上代码定义了entropy_regularization()方法,它仅接收两个参数:

  • Bandit(一个多臂机实例);
  • T(试验轮次,即在多臂机上探索/利用的轮次)。

在每轮试验中,汤普森采样探索策略将臂的价值与当前的熵值相加,从而鼓励算法对不同的臂进行更多的探索,这样做的目的是让每个动作都有一定的概率被选中,而不完全依赖于当前的价值估计。这实际上不是严格意义上的熵正则化探索策略,而是一种使用熵正则化思想来鼓励探索的简化方法,后面在介绍SAC算法时,会详细解释熵正则化。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐