Files
rustytorch/crates/specialized/rtx-nmf/examples/basic_usage.rs
T
2026-03-04 00:08:42 +00:00

146 lines
4.5 KiB
Rust

//! Basic NMF usage example
//!
//! This example demonstrates the basic usage of the RTX-NMF crate
//! for matrix decomposition with both synthetic data and image-like data.
use rtx_nmf::{Device, NMFConfig, NMFDecomposer, Tensor, demo::NMFDemo};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 RTX-NMF Basic Usage Example");
println!("==============================\n");
// Initialize device (GPU if available, CPU fallback)
let device = Device::cuda(0).unwrap_or_else(|_| {
println!("⚠️ CUDA not available, using CPU");
Device::cpu()
});
println!("🔧 Using device: {:?}\n", device);
// Example 1: Basic matrix decomposition
basic_matrix_example(&device)?;
// Example 2: Image decomposition demo
image_decomposition_demo(&device)?;
// Example 3: Faces decomposition demo
faces_decomposition_demo(&device)?;
println!("\n🎉 All examples completed successfully!");
Ok(())
}
fn basic_matrix_example(device: &Device) -> Result<(), Box<dyn std::error::Error>> {
println!("📊 Example 1: Basic Matrix Decomposition");
println!("-----------------------------------------");
// Create a simple non-negative matrix
let matrix_data = vec![
1.0, 2.0, 3.0, 4.0, 2.0, 4.0, 6.0, 8.0, 3.0, 6.0, 9.0, 12.0, 1.0, 3.0, 5.0, 7.0, 2.0, 5.0,
8.0, 11.0,
];
let matrix = Tensor::from_data(matrix_data, [5, 4], device)?;
println!("Input matrix shape: {:?}", matrix.shape());
// Configure NMF
let config = NMFConfig::new()
.with_components(2)
.with_max_iterations(100)
.with_tolerance(1e-5);
println!("NMF configuration:");
println!(" Components: {}", config.components());
println!(" Max iterations: {}", config.max_iterations());
println!(" Tolerance: {:.0e}", config.tolerance());
// Run decomposition
let mut decomposer = NMFDecomposer::new(config);
println!("\n⚡ Running NMF decomposition...");
let result = decomposer.fit_transform_detailed(&matrix)?;
println!("✅ Decomposition completed!");
println!(" W matrix shape: {:?}", result.w.shape());
println!(" H matrix shape: {:?}", result.h.shape());
println!(" Iterations: {}", result.iterations);
println!(" Converged: {}", result.converged);
println!(" Reconstruction error: {:.6}", result.reconstruction_error);
println!(" Computation time: {:.3}s", result.computation_time);
// Verify reconstruction
let reconstruction = result.reconstruct()?;
let reconstruction_error = result.calculate_error(&matrix)?;
println!(" Verification error: {:.6}\n", reconstruction_error);
Ok(())
}
fn image_decomposition_demo(device: &Device) -> Result<(), Box<dyn std::error::Error>> {
println!("🖼️ Example 2: Image Decomposition Demo");
println!("---------------------------------------");
let mut demo = NMFDemo::new(device.clone());
// Run image demo with a small image
let result = demo.run_image_demo(32, 24)?;
println!("Demo summary: {}", result.format_summary());
// Show performance metrics
println!("Performance metrics:");
let metrics = demo.get_performance_metrics();
for (key, value) in metrics {
println!(" {}: {}", key, value);
}
println!();
Ok(())
}
fn faces_decomposition_demo(device: &Device) -> Result<(), Box<dyn std::error::Error>> {
println!("👥 Example 3: Faces Decomposition Demo");
println!("---------------------------------------");
let mut demo = NMFDemo::new(device.clone());
// Run faces demo with small face images
let result = demo.run_faces_demo(8, 16, 16)?;
println!("Faces demo summary: {}", result.format_summary());
println!("Face basis components found:");
println!(" Original faces: {:?}", result.original_image.shape);
println!(" Basis matrix W: {:?}", result.w_matrix.shape);
println!(" Coefficients H: {:?}", result.h_matrix.shape);
println!(
" Each face can be reconstructed as a linear combination of {} basis faces",
result.components
);
println!();
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_example() {
let device = Device::cpu();
assert!(basic_matrix_example(&device).is_ok());
}
#[test]
fn test_image_demo() {
let device = Device::cpu();
assert!(image_decomposition_demo(&device).is_ok());
}
#[test]
fn test_faces_demo() {
let device = Device::cpu();
assert!(faces_decomposition_demo(&device).is_ok());
}
}