如何随机生成随机矩阵(Stochastic Matrix)或ndarray?
Rust 生成概率向量/随机矩阵/随机ndarray方案
现有Crate推荐
目前没有专门一键生成这类结构的Crate,但基于ndarray和ndarray-rand可以快速实现,完全满足简洁性需求。
向量化实现方案(基于ndarray)
利用ndarray的广播特性和沿维度求和功能,能避免循环,实现高效的向量化运算,同时优化数值稳定性。
概率向量(一维)
采用整数生成再归一化的方式提升数值稳定性:
use ndarray::Array1; use ndarray_rand::RandomExt; use ndarray_rand::rand_distr::Uniform; fn main() { // 生成1-100的随机整数,转换为浮点数后归一化 let a = Array1::random(10, Uniform::new(1u32, 100u32)) .map(|x| x as f64); let sum = a.sum(); let prob_vec = &a / sum; println!("向量和:{:?}", prob_vec.sum()); }
随机矩阵/高维随机ndarray
针对任意高维数组,只需沿最后一维求和,再通过广播完成逐元素归一化:
use ndarray::{Array, Array2, Axis}; use ndarray_rand::RandomExt; use ndarray_rand::rand_distr::Uniform; fn main() { // 生成3行5列的随机矩阵,按列归一化(最后一维为列) let mat = Array2::random((3, 5), Uniform::new(1u32, 100u32)) .map(|x| x as f64); // 沿最后一维求和,得到形状为(3,)的数组 let col_sums = mat.sum_axis(Axis(-1)); // 扩展维度实现广播除法,每行元素除以对应列的和 let stochastic_mat = mat / &col_sums.insert_axis(Axis(-1)); // 验证每列和是否为1 for col in stochastic_mat.axis_iter(Axis(1)) { println!("列和:{:.6}", col.sum()); } // 3维数组示例 let arr3d = Array::random((2, 3, 4), Uniform::new(1u32, 100u32)) .map(|x| x as f64); let sums = arr3d.sum_axis(Axis(-1)); let stochastic_3d = arr3d / &sums.insert_axis(Axis(-1)); }
核心是sum_axis(Axis(-1))获取最后一维的和,再用insert_axis(Axis(-1))扩展维度以支持广播,全程无需手动循环。
非ndarray方案(基于标准库+rand)
如果不依赖ndarray,用标准库Vec结合rand也能实现:
概率向量
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); let vec: Vec<u32> = (0..10).map(|_| rng.gen_range(1..100)).collect(); let sum: u32 = vec.iter().sum(); let prob_vec: Vec<f64> = vec.iter().map(|&x| x as f64 / sum as f64).collect(); println!("向量和:{:?}", prob_vec.iter().sum::<f64>()); }
随机矩阵
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); // 3行5列矩阵,按列归一化 let mut mat: Vec<Vec<u32>> = (0..3).map(|_| { (0..5).map(|_| rng.gen_range(1..100)).collect() }).collect(); // 计算每列的和 let col_sums: Vec<u32> = (0..5).map(|col| { mat.iter().map(|row| row[col]).sum() }).collect(); // 归一化处理 let stochastic_mat: Vec<Vec<f64>> = mat.iter().map(|row| { row.iter().enumerate().map(|(col, &x)| x as f64 / col_sums[col] as f64).collect() }).collect(); }
关于ndarray-rand直接生成的说明
ndarray-rand目前没有内置分布直接生成归一化后的随机数组,这类需求本质是先采样再归一化,用现有工具组合已经足够简洁高效。
内容的提问来源于stack exchange,提问作者nbro
相关产品推荐
相关产品推荐

