How to reshape with ndarray

Hi all. Hoping someone could help me better understand ndarray and the various types. I'm trying to implement the follow Python code in Rust:

Y = Y.reshape(AL.shape)
dAL = -(np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))

Y is a 1xN Array2<f32> of 1's and 0's, and AL is also an Array2<f32>, but of arbitrary size. This is for use in a basic neural network, so the number of elements in each will match so long as all parts of the system are computed correctly.

Because ndarray doesn't have a divide function (element-wise division), I came up with this:

pub type Matrix2D = Array2<f32>;

pub fn divide(a: &Matrix2D, b: &Matrix2D) -> Matrix2D {
    Zip::from(a).and(b).map_collect(|n1, n2| {
        let v = *n1 / *n2;
        if v.is_nan() { 0.0 } else { v }
    })
}

So my Rust version of the above Python code becomes this:

let yy = y.into_shape(al.shape()).unwrap();
let dal = -(divide(&yy, &al) - divide(&(1.0 - &yy), &(1.0 - &al)));

The second line doesn't compile because the reshaping process returns type ArrayBase<OwnedRepr<f32>, Dim<IxDynImpl>>, and Array2<f32> equals ndarray::ArrayBase<ndarray::OwnedRepr<f32>, ndarray::Dim<[usize; 2]>>.

mismatched types

expected array `[usize; 2]`, found struct `ndarray::IxDynImpl`

note: expected reference `&ndarray::ArrayBase<ndarray::OwnedRepr<f32>, ndarray::Dim<[usize; 2]>>`
         found reference `&ndarray::ArrayBase<ndarray::OwnedRepr<f32>, ndarray::Dim<ndarray::IxDynImpl>>`rustc(E0308)
ml.rs(278, 47): expected array `[usize; 2]`, found struct `ndarray::IxDynImpl`

Is there a way to either resolve this type mismatch, or change the divide function so that either type will work?

The best solution I could come up with was to convert both matrices into 1D vectors so I could zip them together and get the element-wise division result using a map operation, and then reshape. This works but I suspect it's not a good/efficient solution.

let y_vec = y.iter().map(|f| *f).collect::<Vec<f32>>();
let al_vec = al.iter().map(|f| *f).collect::<Vec<f32>>();

let dal = y_vec
    .iter()
    .zip(al_vec)
    .map(|(y, a)| {
        let v = -(y / a) - (1.0 - y) / (1.0 - a);
        if v.is_nan() { 0.0 } else { v }
    })
    .collect::<Vec<f32>>();

let shape = al.shape();
let (row, col) = (shape[0], shape[1]);
let dal = Array::from_shape_vec((row, col), dal).unwrap();

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.