超越机器学习管道:使用 MLJ

2019 年 5 月 2 日 | Anthony Blaom,Diego Arenas,Franz Kiraly,Yiannis Simillides,Sebastian Vollmer

  1. 简介
  2. MLJ 特性
  3. 学习网络
  4. 构建一个简单的网络
  5. 导出和重新训练
  6. 只需“写出数学公式!”
  7. 邀请加入社区

简介

MLJ 是一个用纯 Julia 编写的开源机器学习工具箱。它提供了一个统一的接口来与目前分散在不同 Julia 包中的监督和无监督学习模型进行交互。

在早期的概念验证的基础上,开发工作于 2018 年 12 月在艾伦·图灵研究所正式开始。在短时间内,兴趣不断增长,该项目现已成为该研究所星标最多的软件库。

在概述了 MLJ 的当前功能之后,本文介绍了 MLJ 的学习网络,这是一种用于模型组合的超级管道功能。

快速链接

MLJ 与 ScikitLearn.jl 的比较

☞ 2019 年 3 月伦敦 Julia 用户组聚会上的视频(跳至21'39 处的演示) 


☞ MLJ 的教程

☞ 构建一个自调整随机森林

☞ MLJ 的docker 镜像(包括教程)

☞ 为一个新模型实现 MLJ 接口

☞ 如何贡献代码

☞ Julia Slack 频道:#mlj。

☞ 为MLJ加星标以表示支持,我们将不胜感激!

MLJ 特性

MLJ 已经拥有强大的功能

未来计划的增强功能包括集成 Flux.jl 的深度学习模型,以及使用自动微分进行梯度下降调整连续超参数。

虽然目前只有少量机器学习模型实现了 MLJ 接口,但正在进行的工作旨在将流行的 Python 框架 scikit-learn 支持的模型作为临时解决方案进行包装。有关 MLJ 的设计与 Julia 包装ScikitLearn.jl的比较,请参见此常见问题解答

学习网络

MLJ 的模型组合接口足够灵活,可以实现例如数据科学竞赛中流行的模型堆栈。为了处理此类示例,接口设计必须考虑到预测和训练模式中的信息流不同。从以下简单双模型堆栈示意图(视为网络)可以看出这一点

构建一个简单的网络

在 MLJ 中,模型网络是使用您已经熟悉的声明式语法构建的,这与包的基本用法相同。例如,在对分类特征进行独热编码后,在 MLJ 中训练决策树的普通语法如下所示

using MLJ
@load DecisionTreeRegressor

# load some data:
task = load_reduced_ames();
X, y = task();

# one-hot encode the inputs, X:
hot_model = OneHotEncoder()
hot = machine(hot_model, X)
fit!(hot)
Xt = transform(hot, X)

# fit a decision tree to the transformed data:
tree_model = DecisionTreeRegressor()
tree = machine(tree_model, Xt, y)
fit!(tree, rows = 1:1300)

请注意,MLJ 中的模型只是一个包含超参数的结构体。将模型包装在数据中会生成一个机器结构体,该结构体还将记录训练结果。

如果没有管道,每次我们想要呈现新的数据进行预测时,都必须首先应用独热编码

Xnew = X[1301:1400,:];
Xnewt = transform(hot, Xnew);
yhat = predict(tree, Xnewt);
yhat[1:3]
 3-element Array{Float64,1}:
  223956.9999999999
  320142.85714285733
  161227.49999999994

要构建一个管道,只需将提供的源数据包装在源节点中并重复类似的声明,省略对fit!的调用。现在不同之处在于每个“变量”(例如,Xtyhat)都是我们管道的节点,而不是具体数据

Xs = source(X)
ys = source(y)

hot = machine(hot_model, Xs)
Xt = transform(hot, Xs);

tree = machine(tree_model, Xt, ys)
yhat = predict(tree, Xt)

如果我们愿意,可以将节点视为动态数据——“数据”因为它可以被调用(按行索引),但“动态”因为结果取决于训练事件的结果,而训练事件又取决于超参数值。例如,在拟合完成的管道后,我们可以像这样进行新的预测

fit!(yhat, rows=1:1300)
 [ Info: Training NodalMachine @ 151.
 [ Info: Spawned 1300 sub-features to one-hot encode feature :Neighborhood.
 [ Info: Spawned 1300 sub-features to one-hot encode feature :MSSubClass.
 [ Info: Training NodalMachine @ 117.
 Node @ 179 = predict(117, transform(151, 107))

yhat(rows=1301:1302) # to predict on rows of source node
yhat(Xnew)           # to predict on new data
156-element Array{Float64,1}:
 223956.9999999999
 320142.85714285733
 ...

导出和重新训练

一旦构建了这样的管道并在样本数据上进行了测试,就可以将其导出为一个独立的模型,准备在任何数据集上进行训练。有关详细信息,请参阅 MLJ 的文档。将来,Julia 宏将允许用几行代码构建常见的架构(例如,线性管道)。

最后,我们提到 MLJ 学习网络及其导出的对应物在某种意义上是“智能的”,因为更改超参数不会触发更改上游组件模型的重新训练

tree_model.max_depth = 4
fit!(yhat, rows=1:1300)
 [ Info: Not retraining NodalMachine @ 151. It is up-to-date.
 [ Info: Updating NodalMachine @ 117.
 Node @ 179 = predict(117, transform(151, 107))

只需“写出数学公式!”

由于 Julia 的泛型编程特性,您可以对数据应用的任何类型的操作(算术运算、行选择、列连接等)都可以被重载以用于节点。这样,MLJ 的网络构建语法简洁、直观且易于阅读。在这方面,我们受到了关于机器学习和编程语言的启发。

邀请加入社区

我们现在邀请社区试用我们新注册的MLJ 包,并提供您在未来可能有的任何反馈或建议。我们也特别想知道您将如何使用我们的包,以及它可能缺少哪些功能。