Crates.io | wyrm |
lib.rs | wyrm |
version | 0.9.1 |
source | src |
created_at | 2017-12-26 16:52:00.339488 |
updated_at | 2018-06-02 18:20:23.656996 |
description | A low-overhead, define-by-run autodifferentiation library. |
homepage | |
repository | https://github.com/maciejkula/wyrm |
max_upload_size | |
id | 44468 |
size | 288,878 |
A reverse mode, define-by-run, low-overhead autodifferentiation library.
Performs backpropagation through arbitrary, define-by-run computation graphs, emphasizing low overhead estimation of sparse, small models on the CPU.
Highlights:
The following defines a univariate linear regression model, then backpropagates through it.
let slope = ParameterNode::new(random_matrix(1, 1));
let intercept = ParameterNode::new(random_matrix(1, 1));
let x = InputNode::new(random_matrix(1, 1));
let y = InputNode::new(random_matrix(1, 1));
let y_hat = slope.clone() * x.clone() + intercept.clone();
let mut loss = (y.clone() - y_hat).square();
To optimize the parameters, create an optimizer object and go through several epochs of learning:
let mut optimizer = SGD::new(0.1, vec![slope.clone(), intercept.clone()]);
for _ in 0..num_epochs {
let x_value: f32 = rand::random();
let y_value = 3.0 * x_value + 5.0;
// You can re-use the computation graph
// by giving the input nodes new values.
x.set_value(x_value);
y.set_value(y_value);
loss.forward();
loss.backward(1.0);
optimizer.step(loss.parameters());
}
You can use rayon
to fit your model in parallel, by first creating a set of shared
parameters, then building a per-thread copy of the model:
let slope_param = Arc::new(HogwildParameter::new(random_matrix(1, 1)));
let intercept_param = Arc::new(HogwildParameter::new(random_matrix(1, 1)));
let num_epochs = 10;
(0..rayon::current_num_threads())
.into_par_iter()
.for_each(|_| {
let slope = ParameterNode::shared(slope_param.clone());
let intercept = ParameterNode::shared(intercept_param.clone());
let x = InputNode::new(random_matrix(1, 1));
let y = InputNode::new(random_matrix(1, 1));
let y_hat = slope.clone() * x.clone() + intercept.clone();
let mut loss = (y.clone() - y_hat).square();
let mut optimizer = SGD::new(0.1, vec![slope.clone(), intercept.clone()]);
for _ in 0..num_epochs {
let x_value: f32 = rand::random();
let y_value = 3.0 * x_value + 5.0;
x.set_value(x_value);
y.set_value(y_value);
loss.forward();
loss.backward(1.0);
optimizer.step(loss.parameters());
}
});
You should enable BLAS support to get (much) better performance out of matrix-multiplication-heavy
workloads. To do so, add the following to your Cargo.toml
:
ndarray = { version = "0.11.0", features = ["blas", "serde-1"] }
blas-src = { version = "0.1.2", default-features = false, features = ["openblas"] }
openblas-src = { version = "0.5.6", default-features = false, features = ["cblas"] }