第八讲:随机搜索调优——当穷举法遇上随机性
网格搜索听起来很完美,对吧?把所有参数组合都试一遍,总能找到最优解。但我在实盘交易中遇到过一个问题:当参数空间超过3维时,网格搜索的计算量会爆炸式增长。你想想看,如果每个参数取10个值,5个参数就是10万次回测——这还不算交叉验证。
这时候,随机搜索就派上用场了。说白了,它就是在参数空间里随机撒点,用更少的计算资源找到足够好的解。嗯,这里要注意:随机搜索不是瞎蒙,它背后有扎实的数学原理。
随机搜索原理
随机搜索的核心思想很简单:在参数空间中随机采样,评估每个样本点的性能,然后选择最优的。但为什么这种方法有效?
我个人的理解是:大多数优化问题中,好的参数区域只占整个空间的一小部分。网格搜索会把大量计算浪费在"坏区域"的精细扫描上,而随机搜索则能更快地覆盖到"好区域"。
核心定理:当采样次数足够多时,随机搜索找到的最优解会以概率1收敛到全局最优解。这个收敛速度与参数空间的维度无关——这是它比网格搜索强的地方。
我在做基差交易策略时,遇到过参数空间高达8维的情况。如果用网格搜索,每个参数取10个值,那就是1亿次回测。我的笔记本直接罢工了。改用随机搜索后,5000次采样就找到了不错的参数组合。
随机采样策略
随机搜索不是简单地用均匀分布采样。不同的采样策略会影响搜索效率。我常用的几种策略:
| 采样策略 | 适用场景 | 我的经验 |
|---|---|---|
| 均匀采样 | 参数范围明确,无先验知识 | 最常用,简单可靠 |
| 对数均匀采样 | 参数跨度大(如学习率1e-5到1e-1) | 做止损参数时必用 |
| 拉丁超立方采样 | 需要更好的空间覆盖 | 高维参数空间效果显著 |
| 自适应采样 | 已有部分好结果,想聚焦搜索 | 第二阶段调优常用 |
举个例子,如果你要优化基差交易中的持仓周期参数,范围是1到100天。用均匀采样,每个值被选中的概率相同。但如果你觉得最优值可能在10天以内,可以用对数均匀采样,让短周期有更高的采样密度。
# 对数均匀采样示例
import numpy as np
def log_uniform_sample(low, high, size):
"""在log空间均匀采样"""
log_low = np.log(low)
log_high = np.log(high)
return np.exp(np.random.uniform(log_low, log_high, size))
# 采样100个持仓周期参数
samples = log_uniform_sample(1, 100, 100)
print(f"采样范围: {samples.min():.1f} - {samples.max():.1f}")
print(f"中位数: {np.median(samples):.1f}")
随机搜索 vs 网格搜索
这个问题我经常被问到。直接说结论:在低维空间(≤3维),网格搜索更好;在高维空间,随机搜索完胜。
为什么会这样?我画个图你就明白了。
看到没?网格搜索在9个点上均匀分布,但只有1个点落在最优区域附近。随机搜索用了12个点,有2个点直接命中了最优区域。这就是随机搜索的威力——同样的计算量,覆盖效率更高。
我的经验法则:当参数维度d > 3时,优先用随机搜索。网格搜索需要的采样数是O(k^d),而随机搜索只需要O(k)就能达到同样的效果。
随机搜索的收敛性
收敛性这个问题,说白了就是:随着采样次数增加,找到的解会不会越来越接近全局最优?答案是肯定的,但有个前提——采样必须覆盖整个参数空间。
我曾经犯过一个错误:在调优基差交易策略的开仓阈值参数时,我把采样范围设得太窄,结果找到了一个局部最优,但错过了真正的全局最优。后来我学乖了,先用大范围粗搜,再在小范围精搜。
随机搜索的收敛速度可以用一个公式描述:
P(找到ε-最优解) ≥ 1 - (1 - δ)^n
其中:
- ε: 可接受的误差范围
- δ: 最优区域占整个参数空间的比例
- n: 采样次数
这个公式告诉我们:收敛速度取决于最优区域的大小,而不是参数空间的维度。这就是为什么随机搜索在高维空间依然有效。
随机搜索的实践技巧
做了这么多年量化交易,我总结了几条随机搜索的实战技巧:
- 先粗后精:先用大范围采样100-200次,找到有希望的区域,再缩小范围精细搜索。
- 多阶段搜索:我习惯分3个阶段——粗搜(500次)、精搜(200次)、微调(50次)。
- 使用随机种子:固定随机种子,确保结果可复现。不然你找到好参数后,下次跑不出来了。
- 并行化采样:随机搜索天然适合并行。我经常用多进程同时跑几十个回测。
- 记录所有结果:不要只记最优解,把所有采样点的参数和性能都记下来。这些数据对后续分析很有用。
避坑指南:我曾经在调优时忽略了参数之间的相关性。比如基差交易中的止损比例和持仓周期是强相关的——周期越长,止损比例应该越大。如果独立采样,可能会产生不合理的参数组合。建议在采样时加入业务约束。
# 带约束的随机搜索示例
def constrained_random_search(param_ranges, constraints, n_iter=1000):
best_score = -np.inf
best_params = None
for i in range(n_iter):
# 采样参数
params = {name: np.random.uniform(low, high)
for name, (low, high) in param_ranges.items()}
# 检查约束
if not all(constraint(params) for constraint in constraints):
continue
# 评估性能
score = evaluate_strategy(params)
if score > best_score:
best_score = score
best_params = params.copy()
return best_params, best_score
# 约束条件示例:止损比例不能大于持仓周期的1%
constraints = [
lambda p: p['stop_loss'] < p['holding_period'] * 0.01
]
嗯,最后说一句:随机搜索不是万能药。如果你的参数空间非常小(比如只有2-3个参数),网格搜索可能更直接。但面对高维、复杂的参数优化问题,随机搜索绝对是你的得力助手。
我在实盘交易中,80%的参数调优都是用随机搜索完成的。它帮我节省了大量时间,而且找到的参数组合往往比网格搜索更稳定——因为随机搜索天然避免了过拟合到网格点上的风险。
公众号:蓝海资料掘金营,微信deep3321