juice icon indicating copy to clipboard operation
juice copied to clipboard

make layer API rustic

Open drahnr opened this issue 7 years ago • 5 comments

The API includes too much boilerplate, consider builder pattern.

drahnr avatar Apr 21 '17 12:04 drahnr

@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 avatar Oct 23 '17 14:10 Anton-4

@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.

drahnr avatar Oct 23 '17 15:10 drahnr

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
//     }

drahnr avatar Oct 23 '17 20:10 drahnr

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>
    }
}

andreytkachenko avatar Jun 24 '19 20:06 andreytkachenko

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

drahnr avatar Jan 08 '20 13:01 drahnr