9个版本
使用旧的Rust 2015
0.12.4 | 2022年6月12日 |
---|---|
0.12.3 | 2021年4月15日 |
0.12.2 | 2019年7月28日 |
0.12.1 | 2019年5月4日 |
0.9.0 | 2018年3月1日 |
#547 in 算法
61 每月下载量
20KB
209 行
Rust中的多臂老虎机算法
Cargo
[dependencies]
bandit = "0.12.3"
描述和范围
此库目前仅实现了退火softmax老虎机算法。未来的工作也可能实现其他老虎机算法变体(欢迎提交pull-requests)。
本项目受到了John Myles White所著《网站优化的老虎机算法》一书的很多启发。版权所有2013年John Myles White,978-1-449-34133-6
使用和配置
首先,你需要创建一个带有三个参数的老虎机
let bandit = AnnealingSoftmax::new(arms, DEFAULT_BANDIT_CONFIG.clone(), DEFAULT_CONFIG);
第一个参数是老虎机将要抽取的臂的列表。一个臂可以是实现 Clone + Hash + Eq + Identifiable
特性的任何东西。你很可能总是会派生前三个特性,但最后一个特性 Identifiable
是特殊的。
pub trait Identifiable {
fn ident(&self) -> String;
}
其实并不特别,它应该很容易实现。添加此附加特性的原因是完整的老虎机状态可以持久化到磁盘(JSON格式),以便稍后可以在算法的确切状态下继续。不幸的是,Hash
不保证使用的哈希算法,并且可能在Rust版本之间发生变化。由于我们希望能够在不同的Rust版本之间加载状态,我们要求该特性能返回一个唯一的、易于序列化的 String
作为臂的唯一标识符。
下一个参数是通用老虎机配置
#[derive(Debug, PartialEq, Clone)]
pub struct BanditConfig {
/// Log file for logging details about the bandit algorithm
/// run. What will be logged depends on the bandit algorithm
/// implementation.
pub log_file: Option<PathBuf>
}
允许你可选地提供日志文件的路径,其中算法的每一步都会记录到该文件。日志文件是一个简单的csv文件,记录臂抽取状态和奖励更新
SELECT;threads:5;1529824600935
SELECT;threads:18;1529825031483
UPDATE;threads:18;1529825931520;0.1320011111111111
SELECT;threads:9;1529825931560
UPDATE;threads:9;1529826831455;0.1326688888888889
SELECT;threads:14;1529826831506
UPDATE;threads:14;1529827731423;0.13315000000000002
SELECT;threads:7;1529827731455
UPDATE;threads:7;1529828631384;0.12791666666666668
...
最后一个参数是退火softmax算法的特殊配置
#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
pub struct AnnealingSoftmaxConfig {
/// The higher the value the faster the algorithms tends toward selecting
/// the arm with highest reward. Should be a number between [0, 1.0)
pub cooldown_factor : f64
}
它目前只有一个选项:cooldown_factor
,它可以是0和1.0之间的浮点数。你可以使用此因子来控制退火的快慢。cooldown_factor
越高,算法越快停止探索新臂,并坚持使用迄今为止发现的最高奖励的臂。你可能需要通过实验来找到最适合你特定设置的因子(还有一些工具可以帮助你,见下文)。
在构造和配置你的老虎机之后,你可以开始选择臂
let arm = bandit.select_arm();
并更新武器的奖励
let reward = ... some f64 value
bandit.update(arm, reward);
基本上就是这样。在某个时候,在获得足够的奖励(以及取决于你选择的 cooldown_factor
)之后,系统将完全冷却,并始终选择最高奖励的武器。让系统长时间运行是安全的,因为它始终在选择武器和更新,不用担心溢出错误和不一致的强盗状态(这是在单元测试中发现的,感谢单元测试)。
保存和恢复状态
强盗可以将其自身保存到文件中
bandit.save_bandit(<path to save file>);
可以从特定的实现中再次加载强盗
let arms = ... list of arms, as in the initial creation
let bandit_config = ... BanditConfig, like in second parameter from initial creation
let bandit_loaded = AnnealingSoftmax::load_bandit(arms, bandit_config, <path to save file>);
提供的武器不一定必须与从文件中恢复的武器匹配。如果删除了某个武器,它将在加载后被删除。再次保存强盗后,你将丢失存储的奖励。如果添加了新的武器,它将从零奖励开始。
可视化强盗武器选择数据
强盗工具应用允许你分析存储的状态文件和日志文件。详细信息请参阅单独的仓库 bandit_tool。你可以在这里找到网络应用程序:https://ragnaroek.github.io/bandit-tools/。
依赖项
~0.9–1.7MB
~37K SLoC