Skip to content

Add left to right broadcast for Standard binary ops #362

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 6, 2021

Conversation

yanndupis
Copy link
Member

Hey @jvmncs, is it something like that you had in mind?

@mortendahl, fyi, if we have discovered that ndarray for binary operation only broadcast the right tensors to the left and not the opposite (which is supported by numpy). This makes the MAPE metric in the linear regression fail because we try to divide a tensor of shape (1,) by a tensor of shape (n, 1). So trying to find a solution.

Thanks,

@yanndupis yanndupis requested review from mortendahl and jvmncs and removed request for mortendahl July 1, 2021 01:05
@rdragos
Copy link
Contributor

rdragos commented Jul 1, 2021

Is MAPE used anywhere in production? If not I'd suggest we keep the things as they are and only use MAPE as the test when the entire pipeline is in Rust.
Since we're going to get rid of pymoose in anycase...

Copy link
Member

@jvmncs jvmncs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just about what I was thinking, small correction in the comment

Comment on lines 225 to 228
let lhs_to_rhs_broadcast = self.0.broadcast(other.0.dim());
match lhs_to_rhs_broadcast {
Some(lhs_broadcasted) => StandardTensor::<T>(lhs_broadcasted.to_owned() / other.0),
None => {
Copy link
Member

@jvmncs jvmncs Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this broadcast will already be checked & attempted when we try to do self.0/other.0, so it's not necessary to nest like this. try this:

fn div(self, other: StandardTensor<T>) -> Self::Output {
    match self.0.broadcast(other.0.dim()) {
        Some(self_broadcast) => StandardTensor::<T>(self_broadcast / other.0),
        None => StandardTensor::<T>(self.0 / other.0)  // this part will panic if other.0 cannot be broadcast into self.0
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that the documentation is incorrect, the doc says it will broadcast self to rhs, but in fact it's the other way around according to the comment I linked below (and verified by writing a simple test of the two). the code I have here should be correct though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's right. Your code snippet makes sense. I can implement for the other binary ops. Thanks

@jvmncs
Copy link
Member

jvmncs commented Jul 1, 2021

@rdragos this is more about fixing a limitation of rust's ndarray library to match what we would expect from numpy/python. according to the library author they plan to implement this natively in ndarray but are waiting for a rust feature to move from nightly to stable rust-ndarray/ndarray#437 (comment)

@rdragos
Copy link
Contributor

rdragos commented Jul 1, 2021

@jvmncs this makes sense! Good work 👍

jvmncs
jvmncs previously approved these changes Jul 1, 2021
Copy link
Member

@jvmncs jvmncs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good to go once it's passing CI

@@ -387,4 +391,23 @@ mod tests {
assert_eq!(cx, c_exp);
assert_eq!(dx, d_exp);
}

#[test]
fn test_div() {
Copy link
Member

@jvmncs jvmncs Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would consider renaming this to test_div_broadcasting (or even just test_broadcasting) to emphasize we are testing the broadcasting itself more than the div (since we rely on ndarray for op correctness)

@jvmncs jvmncs dismissed their stale review July 1, 2021 20:06

will re-approve when rest of binary ops are implemented!

@yanndupis yanndupis changed the title [WIP] Add left to right broadcast for binary ops Add left to right broadcast for binary ops Jul 2, 2021
@yanndupis
Copy link
Member Author

Hey @jvmncs, I added broadcasting to the other ops. I guess it should be ok for this PR (but happy to look into it tomorrow if we prefer), we could look into parametrized test. Here is a potential candidate: https://crates.io/crates/rstest.

@yanndupis yanndupis changed the title Add left to right broadcast for binary ops Add left to right broadcast for Standard binary ops Jul 2, 2021
@yanndupis
Copy link
Member Author

Ok, I think it should be ready now @jvmncs. As per conversation we only add implicit broadcast (left into right) to Standard ops for now.

Copy link
Member

@jvmncs jvmncs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 👍

@yanndupis yanndupis merged commit 9c525c7 into main Jul 6, 2021
@yanndupis yanndupis deleted the broadcast-bin-op branch July 6, 2021 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants