juice
juice copied to clipboard
make layer API rustic
The API includes too much boilerplate, consider builder pattern.
@drahnr Could you add some more detail on what you would like the API to look like or which approach to take? I'm considering helping out.
@Anton-4 I brainstormed a builder like pattern with one of my former colleagues ( I am looking at you @nicoretti ), I can post it later tonight :) I'd be glad to see some more faces around the codebase 👍
let me know if I can help you getting kickstarted.
Ideally the both APIs could co-exist for a while before retireing the existing one.
This is only for input:
// cfg.add_framework(OPENCL).gpuset([0..2])
// cfg.add_framework()
// cfg.add_layer(fc1).framework(CUDA).config(LinearConfig().output_size(4096))
// cfg.add_layer(fc1).framework(AUTOSELECT).config(PoolingConfig().stride(2).output_size(4096))
// impl Config {
// fn add_layer(self, name : String) -> LayerConfig<> {
// self.lc = LayerConfig<>::new(name);
// &self.lc
// }
// }
// impl Layer {
// fn new() -> LayerConfig {
// }
// fn config(self, lc : LayerConfig) -> Self {
// self.layerconfig = lc;
// self
// }
Here is my opinion on that issue:
I do want to have sort of device manager, like:
use co::prelude::*;
let mut discoverer = DeviceDiscoverer::new();
/// my laptop has 2 gpus 1 nvidia (CUDA and OpenCL) and integrated intel (OpenCL only)
discoverer.add_discoverer(co::cuda::CudaDiscoverer::new()); // firstly added - higher priority
discoverer.add_discoverer(co::opencl::OpenCLDiscoverer::only_gpu());
discoverer.add_discoverer(co::native::NativeDiscoverer::new());
let device_set = discoverer.discover(); // here we have 3 devices - [Nvidia<CUDA>, Intel<OpenCL>, CPU<Native>]
println!("Found: {}", device_set);
let backend = SharedBackend::new(device_set);
let model = build_model(backend);
let mut trainer = Trainer::new();
trainer.set_solver(Adam::new(0.01, ...));
trainer.set_model(model);
let epochs = trainer.fit_iter(1000); // run 1000 epochs
for epoc in epochs {
println!("{}", epoch);
}
fn build_model(b: Rc<Backend>) -> impl ILayer {
model! {
<Sequential input_shape=(28, 28, 1)>
<Reshape shape=(768) />
<Linear units={128} />
<Activation type={Sigmoid} />
<Linear units={256} />
<Activation type={Sigmoid} />
<Linear units={10} />
<Activation type={Sigmoid} />
<Softmax classes={10} />
</Sequential>
}
}
That makes a lot of sense, but this adds a optimization pass (at least a bucket filling pass, but that might be way too simplistic).
I would also prefer something less xml-ish