mod models;
use fandhe_ai::compat::Sequential;
use fandhe_ai::models::{LeNet, Mlp};
fn print_param_map(
title: &str,
rows: impl Iterator<Item = (String, String, Vec<usize>, Vec<usize>, bool)>,
) {
println!("\n== {title} ==");
println!(
"{:<12} {:<16} {:<18} {:<18} transpose",
"fandhe", "pytorch", "fandhe_shape", "pytorch_shape"
);
for (fandhe_key, pytorch_key, fandhe_shape, pytorch_shape, transpose) in rows {
println!(
"{fandhe_key:<12} {pytorch_key:<16} {fandhe_shape:<18?} {pytorch_shape:<18?} {transpose}"
);
}
}
fn run_mlp() -> Result<(), Box<dyn std::error::Error>> {
let mlp = Mlp::new(784, &[256, 128], 10, 0.2)?;
println!(
"Mlp: input_dim=784 hidden_dims=[256, 128] output_dim=10 dropout={}",
mlp.dropout()
);
let mlp_seeded = Mlp::with_seed(784, &[256, 128], 10, 0.2, 12345)?;
fandhe_ai::manual_seed(0);
let x = fandhe_ai::rand(&[4, 784])?;
let mut eval_mlp = mlp_seeded;
eval_mlp.sequential_mut().eval();
let y = eval_mlp.predict(&x)?;
println!("Mlp::predict 出力 shape: {:?}", y.shape());
let tape = fandhe_ai::tape();
let xv = tape.var(&x);
let via_forward = eval_mlp.forward(&tape, &xv)?;
println!(
"Mlp::forward 出力 shape: {:?}",
via_forward.to_tensor().shape()
);
let seq: &Sequential = eval_mlp.sequential();
println!(
"Mlp 内部 Sequential::training() (eval 後): {}",
seq.training()
);
print_param_map(
"Mlp <-> PyTorch nn.Sequential(Linear, ReLU, Dropout, ...)",
models::mlp::mlp_pytorch_param_map(&eval_mlp, 784, &[256, 128], 10)?
.into_iter()
.map(|m| {
(
m.fandhe_key,
m.pytorch_key,
m.fandhe_shape,
m.pytorch_shape,
m.transpose,
)
}),
);
Ok(())
}
fn run_lenet() -> Result<(), Box<dyn std::error::Error>> {
let lenet = LeNet::new(10, 67890)?;
println!("\nLeNet: num_classes={}", lenet.num_classes());
fandhe_ai::manual_seed(0);
let x = fandhe_ai::rand(&[4, 1, 28, 28])?;
let mut eval_lenet = lenet;
eval_lenet.sequential_mut().eval();
let y = eval_lenet.predict(&x)?;
println!("LeNet::predict 出力 shape: {:?}", y.shape());
let tape = fandhe_ai::tape();
let xv = tape.var(&x);
let via_forward = eval_lenet.forward(&tape, &xv)?;
println!(
"LeNet::forward 出力 shape: {:?}",
via_forward.to_tensor().shape()
);
print_param_map(
"LeNet <-> PyTorch Conv2d(1,6,5) -> Conv2d(6,16,5) -> Linear(256,120) -> Linear(120,10)",
models::lenet::lenet_pytorch_param_map(&eval_lenet)?
.into_iter()
.map(|m| {
(
m.fandhe_key,
m.pytorch_key,
m.fandhe_shape,
m.pytorch_shape,
m.transpose,
)
}),
);
let seq: &Sequential = eval_lenet.sequential();
println!(
"LeNet 内部 Sequential::training() (eval 後): {}",
seq.training()
);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
run_mlp()?;
run_lenet()?;
Ok(())
}