咱们来自字节跳动飞书商业应用研发部(Lark Business Applications),目前咱们在北京、深圳、上海、武汉、杭州、成都、广州、三亚都设立了工作区域。咱们关注的产品领域首要在企业经历管理软件上,包含飞书 OKR、飞书绩效、飞书招聘、飞书人事等 HCM 领域体系,也包含飞书审批、OA、法务、财务、采购、差旅与报销等体系。欢迎各位参加咱们。
本文作者:飞书商业应用研发部 魏一
欢迎咱们关注飞书技能,每周定时更新飞书技能团队技能干货内容,想看什么内容,欢迎咱们评论区留言~
为什么运用 Hyperparameter Optimization
自动化机器学习体系的各个部件,让机器学习的规划依靠于核算资源而不是专业人力。
AutoML 的目的是将模型结构和参数的查找从手艺办法变成自动化办法。其意义在于,让公司进行机器学习的才能,规划从依靠机器学习专家转化为依靠核算资源。由于持久的看来核算资源的成本比机器学习专家要低,因而 AutoML 会整体大大增加公司进行机器学习应用的才能。
AutoML Tables
自动化不必定替代人工,也可以助力人工。
AutoML 首要用于自动的进行模型的优化,模型优化可以分为两个部分:
- 特征的挑选
- 体现的优化
- 超参数优化「Hyperparameter Optimization, HPO」
- 网络结构查找「Neural Architecture Search, NAS」
- 功能的优化
首要包含是提高模型的功能,比方剪枝「Pruning」和量化「Quantization」。
易于运用
- 中心节点:负责搜集和汇总练习的成果,分发需求测验的超参数
- 核算节点:负责运用中心节点传来的超参数,运转练习脚本,回来练习成果
练习脚本满足两个根本需求:
- 需求调优的超参数可以从配置里面读入
- 可以回来练习的成果「类似于callback」
model.py
params = {'features': 512,'lr': 0.001,'momentum': 0}
optimized_params = get_next_parameter()
params.update(optimized_params)
...
class NeuralNetwork(nn.Module):
...
for t in range(epochs):
train(...)
accuracy = test(...)
report_result(accuracy)
main.py
search_space = {
'features': {'_type': 'choice', '_value': [128, 256, 512, 1024]},
'lr': {'_type': 'loguniform', '_value': [0.0001, 0.1]},
'momentum': {'_type': 'uniform', '_value': [0, 1]}
}
experiment = Experiment(trial_command='python3 model.py',
search_space=search_space)
experiment.run(8080)
常见的查找空间
- 候选集
- 数值型,比方embedding size 从 4,8, 16, 32,64中选取
- 枚举型,比方不同的优化器
- 实数性
- 从区间内,依据不同的散布选取一个随机实/整数,比方uniform、loguniform ……
HPO迭代思路
- 专业常识 – 大量测验 – 提高功率 – 加快迭代功率
- 择优更新 – 挑选更优的策略进行变换
- 运用现有数据进行猜测
- 择优更新 – 挑选更优的策略进行变换
传统的通用办法
Batch
给出几组比较有潜力的参数。把这些参数都去测验一下,便是最简略的batch办法。
最简略的方式进行超参数挑选,同时可以并行,但需求最多的先验常识。
Anneal
设置一个先验的概率,然后依据这个概率去抽取一个参数组合。
留意:要保证当时体现好的参数组合有比较大的概率被抽到。
例如:运用几何散布选取下一轮迭代的根底参数组合
先验的概率:为 1 / 第k好的试验下标 「注:下标按照体现排序,最好的在最前面」
rng = np.random.RandomState(seed)
good_idx = rng.geometric(1.0 / avg_best_idx), size=size) - 1
超参数跟着试验的进行,可选的规模逐步缩小
例如在区间内随机选取 U(l, h),当时较优参数的值为 x,那么下一次选取时的规模变为:
U(x – w/2, x + w/2),其中 w = W / (1 + T * shrink_coef)
T:当时已完结的trail数量
shrink_coef:大于0小于1的常数
Evolution
办法1:
- 比赛形式:从现有的数据中两两进行随机组合,在每组作用好的参数上进行随机改变,去重,取得新的参数
办法2:
- 自然界中:
- 体现优异的个别往往更加容易留下后代。Aging evolution算法经过采样形成一个候选集,挑选候选集中准确率最高的参数组合进行繁殖,以此模仿这个进程
- 年轻的个别比较于年老的个别一般具有更好的潜能,更有可能留下后代。Aging evolution算法每次会去除种群中一个最老的个别,并参加一个新个别,以此模仿这个进程
- 后代往往会遗传爸爸妈妈的一些特征,并在此根底上进行变异。
Hyperband
哪些要素造成了练习时长的改变?
- 练习轮数
- 样本数量
- 特征数量
- ……
将这些约束要素考虑为预算,经过合理的预算在无/有限分配的超参数组合上分配,取得最大的收益「模型体现最好」
=> 将超参数调优的问题变为无限臂山君机上进行非随机地探究的进程
根本的思路:Early-stop 尽早的完毕潜力不大的参数组合的练习,可是:
设计一个预算约束,依据不同的预算约束和需求探究的参数的组合,分配给每个组合必定的资源:
- B:总预算「上面说到的三个约束要素」
- R:每次迭代的资源数量
- S:需求进行的迭代数量「每次迭代包含屡次测验」
- : Successive Halving 中被保存的超参数组合的比例
实例:
Median Stop
无需模型、适用规模广
在第s步,假如试验t至今最优的成果差于第0到t-1次试验「之前一切」在第s步时的均匀值的中位数,那么则中止当时试验的练习。
均匀值的核算:
第s步:一般不从取前几步的成果,就像之前图所示,前期成果的置信度不高,过早完毕可能会错失最优解。「需求一个warm-up的进程」
_completed_avg_history = defaultdict(list)
for trial_job_id in trial_job_ids:
cnt, history_sum = 0, 0
for each in _running_history[trial_job_id]:
cnt += 1
history_sum += each
s_completed_avg_history[trial_job_id].append(history_sum / cnt)
# 记录 O[1:s, T]
……
avg_array = [] # 第0到t-1次试验「之前一切」在第s步时的均匀值
for id_ in _completed_avg_history:
if len(_completed_avg_history[id_]) >= curr_step:
avg_array.append(_completed_avg_history[id_][curr_step - 1])
median = avg_array[(len(avg_array)-1) // 2]
improved = False if best_history < median else True
❗️没有充分的考虑和运用历史信息
运用大局信息更充分的探究潜力较大的区域
TPE
Tree-structured Parzen Estimator Approach属于 Sequential Model-Based Global Optimization 「SMBO」
这儿的Tree表示什么:超参数是一个个进行优化的,tree指的是一种层级结构。也便是说超参数组成了一个树形结构。
在超参数的选取时,咱们期望新的超参数可以带来最大的收益。因而定义: Expected Improvement 「EI」
结合起来,
也便是说对于给定的历史数据,期望最小化 g(x) / l(x)。
rng = np.random.default_rng(seed)
below, above = split_history(param_history) # split history into good ones and bad ones
counts: List[int] = np.bincount(below)
p = (counts + prior_weight) / sum(counts + prior_weight) # add k smoothing
samples = rng.choice(size, 20, p=p)
below_llik = np.log(p[samples]) # the probablity of these samples to be good (llik means log-likelyhood)
counts: List[int] = np.bincount(above)
p = (counts + prior_weight) / sum(counts + prior_weight)
above_llik = np.log(p[samples]) # the probablity of above samples to be bad
best = samples[np.argmax(below_llik - above_llik)] # which one has best probability to be good
❗️TPE在进行超参数挑选的时分考虑到了历史信息,但没有考虑到部分超参数的相关性
GP
Gaussian Processes:类似的输入应该有类似的输出
假定有数据 D = {(x1, f1), {x2, f2}, {x3, f3}},方针是取得 f(x)。假定数据来自 N ~ (0, K)
假如现在有一个新输入 x* , 假定 x* 和现有的数据来自同一个散布,为了保证f和之前的数据具有相关,所以将已有的f和f共同构成一个新的高斯散布。
假如已有高斯散布,那个可以核算 1|2 和 1|2
因而可以核算出x对应f的均值和方差
实例:
怎么进行猜测?未知点x的猜测值f有更大的概率大于当时最优的f+。
GP和其他的贝叶斯优化「Bayesian Optimization」办法提供了一个更优的超参数选取计划。BOHB「Bayesian Optimization Hyperband」将贝叶斯优化和Hyperband结合起来。整体结构还是和Hyperband保持一致,但每轮优化开始时运用贝叶斯优化替换随机,依据上轮迭代的成果,挑选更优的可测验参数组合。
SMAC
Sequential Model-Based Optimization for General Algorithm Configuration
高斯进程更适合与处理超参数空间为接连或数值类型的情况。但经常会出现离散「例如挑选优化器」,乃至条件关系「例如与优化器相关特有的超参数」的超参数。
GP可以经过设计巧妙的办法解决这个问题「比方设计特定的核函数」,但解决起来并不自然。
需求的是 猜测值 + 不确定性 而且模型不能过于复杂。 —— 随机森林
同样数据集为:{(x_1, f(x_1)), (x_2, f(x_2)), …, (x_n, f(x_n))}
这儿的x_n是模型的超参数,而f(x_n)是在该模型超参数配置下,在某个固定的数据集上的体现
经过树立一个随机森林模型去拟合f;该进程可以类比高斯回归进程中n个点所构成的多维正态散布。
对于新参加的点x,在随机森林的每个树上有一个猜测成果,把一切树的猜测成果求均匀即得到均值,猜测成果求标准差即为标准差。
在高斯回归进程中,对于新参加的点x与之前的点构成新的多维正态散布,然后求解新参加点的边沿散布即可得到新参加的点的均值与标准差。
在对新的超参数组合进行查找的时分,会同时在现已体现比较好的超参数组合邻近进行查找,和随机选取点进行猜测。
DNGO
Deep Networks for Global Optimization
运用DNN替换随机森林。
需求可以取得 猜测值 + 不确定性,DNN怎么实现?
=》 MLP + Bayesian Linear Regression
- MLP部分
经过历史数据进行练习,猜测方针是超参数对应的成果。但在猜测时运用终究一层的输出作为basis function,用作Bayesian Linear Regression的输入。
class Net(nn.Module):
def __init__(self, n_inputs, n_units=[50, 50, 50]):
super(Net, self).__init__()
self.fc1 = nn.Linear(n_inputs, n_units[0])
self.fc2 = nn.Linear(n_units[0], n_units[1])
self.fc3 = nn.Linear(n_units[1], n_units[2])
self.out = nn.Linear(n_units[2], 1)
def forward(self, x):
x = torch.tanh(self.fc1(x))
x = torch.tanh(self.fc2(x))
x = torch.tanh(self.fc3(x))
return self.out(x)
def basis_funcs(self, x):
x = torch.tanh(self.fc1(x))
x = torch.tanh(self.fc2(x))
x = torch.tanh(self.fc3(x))
return x
- Bayesian Linear Regression
依据MLP得到的basis function进行猜测,回来均值和方差。
猜测办法:Gibbs Sampling
例如想要取得方位的f(x, y)「联合散布」,假定是高斯散布:
一个很简略的例子:
Data:{(x1, y1), …, (xn, yn)}
参数为:0 (the intercept), 1 (the gradient) and precision
假定参数的先验散布为:
经过一系列的推导,可以得到:
def gibbs(y, x):
iters = 1000
init = {"beta_0": 0,"beta_1": 0,"tau": 2} # specify hyper parameters hypers = {"mu_0": 0,"tau_0": 1,"mu_1": 0,"tau_1": 1,"alpha": 2,"beta": 1}
beta_0 = init["beta_0"]
beta_1 = init["beta_1"]
tau = init["tau"]
sample_weight = np.zeros((iters, 3)) # trace to store values of beta_0, beta_1, tau
for it in range(iters):
beta_0 = sample_beta_0(y, x, beta_1, tau, hypers["mu_0"], hypers["tau_0"])
beta_1 = sample_beta_1(y, x, beta_0, tau, hypers["mu_1"], hypers["tau_1"])
tau = sample_tau(y, x, beta_0, beta_1, hypers["alpha"], hypers["beta"])
sample_weight[it, :] = np.array((beta_0, beta_1, tau))
return sample_weight
weights = sample_weight(y, x, iters, init, hypers)
predictions = [w[0] + w[1]*x_test + w[2] for w in weights]
神经网络自身也有超参数,终究的选取经过运用多个数据集,运用GP挑选最优的超参数。
比较于随机森林,模型更为复杂,文中提供的成果显现作用优于SMAC,功能优于GP。
深度学习适用的办法
深度学习超参数/结构的查找面临的两大首要问题
- 练习耗时
- 可查找组合多
Evolution
PBT
全称:Population Based Training
结合最优探究和并行测验,在练习的进程中不断的进行模型的评价和排序。假如排名较低,则将被替换「用体现好的模型成果和超参数」,在此根底上进行探究。
Reinforcement Learning
RNN + RL
成果好,但耗时很长。
Differentiable Architecture Search
实例:embedding size查找
- 对每个模型结构挑选的当地,树立一个mixed operation。这个mixed operation有参数a,作为权重。模型自身的参数咱们设置为w
- 当模型还没有收敛时,做:
- 更新mixed operation的模型结构参数a。在模型的每个mixed operation傍边sample一个op。对于sample的ops, 本来模型的loss假如记为 L(op1, op2, … opn),则咱们核算一个L(op1 * a1′, op2 * a2′ …, opn * an’),其中ai’是a在opi上被挑选的那个权重值
- 在模型的每个mixed operation傍边sample一个op,对模型自身的参数w做gradient descent。
总结
- 易于运用,提高功率;
- 加深对业务数据的了解。
Reference
- AutoML For Lite模型 Design Doc
- bytedance.feishu.cn/minutes/obc…
- www.jmlr.org/papers/volu…
- arxiv.org/pdf/1703.01…
- arxiv.org/pdf/1711.09…
- arxiv.org/pdf/1603.06…
- arxiv.org/pdf/1802.01…
- proceedings.neurips.cc/paper/2011/…
- papers.nips.cc/paper/4443-…
- arxiv.org/abs/1807.01…
- www.microsoft.com/en-us/resea…
- www.cs.ubc.ca/~hutter/pap…
- arxiv.org/pdf/1502.05…
- arxiv.org/pdf/1211.09…
- static.googleusercontent.com/media/resea…
- arxiv.org/abs/1611.01…
- arxiv.org/abs/1812.03…
- arxiv.org/abs/1812.09…
- Embedding Size Tuning using SparseNAS Design Doc V2
参加咱们
扫码发现职位&投递简历
官网投递:job.toutiao.com/s/FyL7DRg