Skip to content

Add burn::linalg::{vector_norm,l2_norm} #3131

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 21 commits into from
May 7, 2025

Conversation

crutcher
Copy link
Contributor

@crutcher crutcher commented May 1, 2025

Pull Request Template

Checklist

  • Confirmed that run-checks all script has been executed.
  • Made sure the book is up to date with changes in this PR.

Changes

Added burn::linalg::{vector_norm,l2_norm}

Testing

Testgen tests.

Copy link

codecov bot commented May 1, 2025

Codecov Report

Attention: Patch coverage is 94.65021% with 13 lines in your changes missing coverage. Please review.

Project coverage is 81.47%. Comparing base (f77b405) to head (8622f98).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...rates/burn-tensor/src/tensor/linalg/vector_norm.rs 84.70% 13 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3131      +/-   ##
==========================================
+ Coverage   81.39%   81.47%   +0.08%     
==========================================
  Files         821      823       +2     
  Lines      118058   118301     +243     
==========================================
+ Hits        96088    96385     +297     
+ Misses      21970    21916      -54     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@laggui laggui left a comment

Choose a reason for hiding this comment

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

That's a nice addition! Good start to the linalg module 🙂

A couple minor comments below.

Also, not sure about all the redefined functions for typical norms like l0_norm, l1_norm, etc. We could probably remove those and simply add the definitions to the docstring 🤔

@crutcher
Copy link
Contributor Author

crutcher commented May 1, 2025

I think there's a lot of value in having common functions defined explicitly, even if they're defined in terms of other functions. I could see renaming the +inf/-inf norm functions; if you have better names.

We could also fix the lack of .abs_min_dim(); and drop these; idk.

But if you think about these in terms of "how readable are callers", a lot of literature is written wrt l1 and l2 norms; and i think at least those should have their own alias functions.

@crutcher crutcher requested a review from laggui May 1, 2025 18:36
Copy link
Member

@laggui laggui left a comment

Choose a reason for hiding this comment

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

But if you think about these in terms of "how readable are callers", a lot of literature is written wrt l1 and l2 norms; and i think at least those should have their own alias functions.

For readability and explicitness, I agree. But the negative norm names are a bit awkward indeed, and the match on the f64 as well.

What do you think about an enum?

Could be something along the lines of..

pub enum Norm {
    L0,
    L1,
    L2,
    LInf,
    LNegInf,
    Lp(f64),
}

For ease of use, we could accept p: N where N: Into<Norm>.

So one could specify Norm::L0 and other explicit norms. But also if we have From implementations we could have something more seamless. Just a quick example:

impl From<i32> for Norm {
    fn from(value: i32) -> Self {
        match value {
            0 => Norm::L0,
            1 => Norm::L1,
            2 => Norm::L2,
            v => Norm::Lp(v as f64)
        }
    }
}

could probably be added for i64, f32 and f64 for better type inference.

Lmk what you think 🙂

Otherwise, the actual implementation LGTM. Just a matter of defining the correct interface.

@ArthurBrussee
Copy link
Contributor

ArthurBrussee commented May 2, 2025

Drive-by comment: is it worth specializing L2 as diff * diff instead of a powf_scalar? Just since L2 is so common everywhere in ML, might be worth benching

@crutcher
Copy link
Contributor Author

crutcher commented May 2, 2025

@ArthurBrussee I have specialized it (for the .powi_scalar(2) part); but I can't specialize for the .sqrt() call, and have to use the .powf_scalar(0.5) call; untill/unless I do some additional work on the trait bounds.

@laggui I ran with your idea; and updated the PR.

I would like someone to look at this and suggest what numeric traits, if any, we should bind the methods to; and how I express those traits.

It seems like some of these (max abs, min abs, count) don't need float; but l2 and lp both probably need float. (Also, it's ... weird that .powf_scalar() doesn't require the Float trait, but .sqrt() does ...)

@crutcher crutcher requested a review from laggui May 2, 2025 18:30
@crutcher
Copy link
Contributor Author

crutcher commented May 2, 2025

Please re-review.

I think I've addressed the type bounds to the best of my ability.

@crutcher
Copy link
Contributor Author

crutcher commented May 2, 2025

Discovered, worked-around #3139

@crutcher
Copy link
Contributor Author

crutcher commented May 2, 2025

Wait on: #3140

@crutcher crutcher marked this pull request as draft May 3, 2025 03:07
@crutcher
Copy link
Contributor Author

crutcher commented May 3, 2025

Converted into a draft until the above bug / fix goes in.

@crutcher
Copy link
Contributor Author

crutcher commented May 5, 2025

Should this be moved to burn-core?

@laggui
Copy link
Member

laggui commented May 5, 2025

Should this be moved to burn-core?

I briefly had a thought about this over the weekend. Most of the "tensor ops" are just being thrown in burn-tensor but I think we should have a better separation overall (base / numeric / etc ops are not always clearly distinguishable).

Right now burn-tensor probably still makes the most sense. In the future, if we have enough ops we could have a burn-linalg crate (re-exported via a feature flag).

@crutcher crutcher force-pushed the crutcher/vector_norm branch from 286e080 to 94b8841 Compare May 5, 2025 18:27
@crutcher crutcher marked this pull request as ready for review May 5, 2025 18:27
@crutcher
Copy link
Contributor Author

crutcher commented May 5, 2025

Done!
I've updated this now that the .max_dim() fix is in.

Copy link
Member

@laggui laggui left a comment

Choose a reason for hiding this comment

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

Just a minor comment regarding naming for the max/min norms to make sure.

Otherwise should be good to go! Thanks for going through the rounds in this PR.

/// # Returns
///
/// The L:INFINITY norm of the input tensor.
pub fn max_abs_norm<B: Backend, const D: usize, K>(
Copy link
Member

Choose a reason for hiding this comment

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

Much better naming than l_inf_norm 😅

Is it called the max abs norm or just max norm typically? My linear algebra terminology is a little dusty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really, it really is called the l-infinity-norm:
https://mathworld.wolfram.com/L-Infinity-Norm.html

Copy link
Member

Choose a reason for hiding this comment

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

Yes of course but there are often other names used interchangeably (e.g., euclidean norm or l2 norm).

Max norm seems to also be used, but not sure if it is that common. Anyway, either max_abs_norm, max_norm or infinity_norm (without the L prefix) should be suitable.

Comment on lines +15 to +17
linalg::max_abs_norm(x.clone(), 0)
.into_data()
.assert_eq(&TestTensor::<2>::from([[3., 4.]]).into_data(), true);
Copy link
Member

Choose a reason for hiding this comment

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

Technically this would test pretty much the same code path, but I have no strong opposition against the additional test here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes; it's verifying that the dispatch in vector_norm works

@crutcher
Copy link
Contributor Author

crutcher commented May 6, 2025

I missed the previous discussion about the ops; I'll try and adjust

Copy link
Contributor Author

@crutcher crutcher left a comment

Choose a reason for hiding this comment

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

will adjust

Comment on lines +15 to +17
linalg::max_abs_norm(x.clone(), 0)
.into_data()
.assert_eq(&TestTensor::<2>::from([[3., 4.]]).into_data(), true);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes; it's verifying that the dispatch in vector_norm works

@crutcher crutcher force-pushed the crutcher/vector_norm branch from b0e765e to 8622f98 Compare May 6, 2025 21:38
@laggui laggui merged commit 80de1fa into tracel-ai:main May 7, 2025
10 of 11 checks passed
@crutcher crutcher deleted the crutcher/vector_norm branch May 20, 2025 17:15
Helios113 pushed a commit to Helios113/burn that referenced this pull request Jul 1, 2025
* Add burn::linalg::{vector_norm,l2_norm}

* fmt

* doc

* freshen up inf

* l1 norm

* aliases

* docs

* close for l2

* approx_eq

* long

* improve tolerance

* review

* vector_normalize

* Refactor for review

* typing; make .sqrt() work for l2_norm

* eps type conversion

* test integer tensors, workaround new bug: tracel-ai#3139

* generalize

* remove empty where clause

* Remove workaround for tracel-ai#3119

* Update vector_norm.rs

Push a change to jiggle stuck test Action.
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