问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

推荐算法策略——多目标参数贝叶斯优化

创作时间:
作者:
@小白创作中心

推荐算法策略——多目标参数贝叶斯优化

引用
1
来源
1.
https://cloud.tencent.com/developer/article/2427140

在推荐系统中,如何有效地进行多目标参数调优是一个常见且重要的问题。本文将介绍如何使用贝叶斯优化方法来解决这一问题,包括其基本原理、具体实现步骤以及实际应用效果。

一、贝叶斯优化简介

贝叶斯优化是一种黑盒优化方法,它在每次迭代中都会平衡探索和利用的权衡,以找到最优解。针对贝叶斯优化原理就不多说了,网上很多优秀的解释。大致过程就是:

首先假设目标函数遵循高斯过程,并通过观察目标函数的值来更新这个假设。然后,它选择一个收益最大化的点作为下一个观察点。


(放一个混元理解的图片,有点抽象。。)

二、多目标超参数调优

在推荐系统中,往往模型是多目标的。以内容流为例,目标可以是:点击、时长、转发、评论、点赞、关注等等。而在实践中,一定会遇到的问题是:多目标融合公式内的超参数拍定

简单一点,可以使用“拍脑袋(经验决策)+暴力搜参”。这种方式对于超参数较少或者业务迭代的初期很适用。但是如果超参数较多,暴力搜参再进行A/B实验往往会浪费大量的时间、流量。因此可以通过贝叶斯优化来辅助我们调参。

2.1 确定需要调整的超参数

多目标常见的融合方式是幂乘,那么最简单的,超参数可以是各个目标的幂指数。

Score=\prod Predict_{i}^{α_{i}}

其中α_{i}为第i个目标的幂指数,Predict_{i}为第i个目标的模型预测值。那么α_{i}即是我们需要调整的超参数。

2.2 定义reward

贝叶斯优化中,需要确定优化目标,即一个具体的数值。因此需要根据线上A/B实验的效果来决定reward函数,比如:

Reward=20∗Time+10∗Like+35∗CTR+10∗Share

这里有几点经验:

  1. 每个目标的值最好采用A/B实验中,实验组相比对照组提升的百分点(Percentage),而不是取每个目标提升的绝对值。这样可以尽量保证每个目标的量纲不会有太大差异。当然,如果某个目标的百分点波动较大,可以适当调整该目标的权重。
  2. 当有目标出现负向显著的时候,需要给更大的惩罚。理想情况下,调权的目标是希望在不伤害任何指标的前提下,尽可能做提升。但是实际中,往往会出现严重的指标置换情况。因此,我们需要对负向的指标给更大的惩罚,来优化Reward函数,比如某个指标负向了,那么就乘2倍或者更多(根据自己业务情况调整)。
  3. reward权重拍定,在一定程度上可以理解是“可接受的指标置换”,比如上面的公式中,大致可以理解成愿意牺牲1点“Like”来置换2份“Time”。

2.3 使用贝叶斯优化进行多目标超参数调优

现在我们可以使用贝叶斯优化来寻找最优的超参数。具体步骤如下:

  1. 初始化贝叶斯优化器,设置超参数的搜索范围(边界)。
  2. 选择一个收益函数,代码中是UCB。
  3. 进行多次迭代,在每次迭代中:
  • 线上A/B实验回收数据指标
  • 离线根据2.2的reward的函数计算每组实验得分
  • 将新观察到的数据点添加到贝叶斯优化器中
  1. 在迭代完成后,贝叶斯优化器会返回一组最优的超参数。

这里需要注意的是,线上A/B实验观察的时候,尽可能的保证数据置信,比如实验组给较大流量或实验周期较长。根据自己的业务,一般3-7天可以得到相对置信的结论。

另外,最初的参数往往是人工经验拍定,差距可以大一些,作为第一轮调参进行A/B实验。

三、贝叶斯优化demo

废话不多直接上代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from bayes_opt import BayesianOptimization, UtilityFunction

def black_box_function(x, y):
    return (x - 1) ** 2 + y ** 2 - 1 

optimizer = BayesianOptimization(
    f=None,
    pbounds={'x': (-3, 3), 'y': (-3, 3)},
    verbose=2,
    random_state=1,
    allow_duplicate_points=True
)

utility = UtilityFunction(kind="ucb", kappa=2.5, xi=0.0)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

# Evaluate the black_box_function on a meshgrid
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
x, y = np.meshgrid(x, y)
z = black_box_function(x, y)

# Plot the surface
ax.plot_surface(x, y, z, cmap='viridis', alpha=0.3)

# Optimization loop
explored_points = []
for _ in range(12):
    next_point = optimizer.suggest(utility)
    target = black_box_function(**next_point)
    optimizer.register(params=next_point, target=target)
    
    explored_points.append((next_point['x'], next_point['y'], target))
    print(next_point, target)

# Plot all explored points after the optimization loop
for i in range(1, len(explored_points)):
    x_values = [explored_points[i-1][0], explored_points[i][0]]
    y_values = [explored_points[i-1][1], explored_points[i][1]]
    z_values = [explored_points[i-1][2], explored_points[i][2]]
    ax.plot(x_values, y_values, z_values, c='red', marker='o', markersize=5, linewidth=1)

plt.show()
print(optimizer.max)  
  • 这里我们定义了一个黑盒函数black_box_function来作为例子,在实际的推荐系统中,黑盒函数即是线上A/B实验的反馈结果。
  • 在demo的黑盒函数中,拥有x、y两个参数。我们为这两个参数设定了边界:pbounds={'x': (-3, 3), 'y': (-3, 3)}
  • 接着我们初始化了贝叶斯优化器以及收益函数UCB
  • 对该黑盒函数迭代12轮,每一轮将观测到的值重新register至贝叶斯优化器中,实现迭代。最终画图整个过程图。
  • 线上A/B实验和demo类似,只要把观测值离线手动算好来代替black_box_function的输出塞进来就行了。

代码参考链接:https://github.com/bayesian-optimization/BayesianOptimization

四、 线上收益

指标 提升效果
A指标 +% 正向显著
B指标 +
% 正向显著
C指标 +% 正向显著
D指标 +
% 正向显著
E指标 -**% 负向显著

最后放一下业务真实的线上指标,ABCD四个指标均有效提升,E指标负向显著。中间调过好几轮,一直会存在指标置换的情况无法避免,最后评估完置换是可以接受的。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号