use custos::{range, CPU};
use custos_math::nn::{cce, cce_grad};
use gradients::{Adam, Linear, NeuralNetwork, OnehotOp, ReLU, Softmax};
use purpur::{Apply, Converter, ImageReturn, Transforms};
#[derive(NeuralNetwork)]
struct Network<'a, T> {
lin1: Linear<'a, T, { 100 * 100 * 3 }, 512>,
relu1: ReLU<'a, T>,
lin2: Linear<'a, T, 512, 16>,
relu2: ReLU<'a, T>,
lin3: Linear<'a, T, 16, 3>,
softmax: Softmax<'a, T>,
}
#[test]
fn test_berries_net() -> Result<(), std::io::Error> {
let mut ir = ImageReturn::default();
let mut trans = Transforms::new(vec![Apply::GetImgRet(&mut ir)]).shuffle();
trans.apply("../../gradients-fallback/datasets/berries_aug_6xx/train")?;
let device = CPU::new();
let x = Matrix::from((
&device,
(ir.sample_count(), ir.features()),
ir.data.as_f32(),
));
let x = x.divs(255.);
let y = Matrix::from((
&device,
(ir.sample_count(), 1),
ir.get_classes_for_imgs().as_f32(),
));
let y = device.onehot(&y);
let mut net = Network {
lin1: Linear::new(&device),
lin2: Linear::new(&device),
lin3: Linear::new(&device),
..Default::default()
};
let mut opt = Adam::new(1e-4);
for epoch in range(1000) {
let predicted = net.forward(&x);
let loss = cce(&device, &predicted, &y);
let grad = cce_grad(&device, &predicted, &y);
net.backward(&grad);
opt.step(&device, net.params());
println!("epoch: {epoch}, loss: {loss}");
}
Ok(())
}