146 lines
4.5 KiB
Rust
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());
|
|
}
|
|
}
|